code: def handleDat(self, pkt):
          
          log.info("Handling DAT packet - block %d" % pkt.blocknumber)
          log.debug("Expecting block %s", self.context.next_block)
          if pkt.blocknumber == self.context.next_block:
              log.debug("Good, received block %d in sequence", pkt.blocknumber)
  
              self.sendACK()
              self.context.next_block += 1
  
              log.debug("Writing %d bytes to output file", len(pkt.data))
              self.context.fileobj.write(pkt.data)
              self.context.metrics.bytes += len(pkt.data)
              # Check for end-of-file, any less than full data packet.
              if len(pkt.data) < self.context.getBlocksize():
                  log.info("End of file detected")
                  return None
  
          elif pkt.blocknumber < self.context.next_block:
              if pkt.blocknumber == 0:
                  log.warning("There is no block zero!")
                  self.sendError(TftpErrors.IllegalTftpOp)
                  raise TftpException("There is no block zero!")
              log.warning("Dropping duplicate block %d" % pkt.blocknumber)
              self.context.metrics.add_dup(pkt)
              log.debug("ACKing block %d again, just in case", pkt.blocknumber)
              self.sendACK(pkt.blocknumber)
  
          else:
              # FIXME: should we be more tolerant and just discard instead?
              msg = "Whoa! Received future block %d but expected %d" \
                  % (pkt.blocknumber, self.context.next_block)
              log.error(msg)
              raise TftpException(msg)
  
          # Default is to ack
          return TftpStateExpectDAT(self.context)
docs: This method handles a DAT packet during a client download, or a
          server upload.