Changeset f24e116 in rtems-tools


Ignore:
Timestamp:
Nov 7, 2018, 3:58:17 AM (6 months ago)
Author:
Chris Johns <chrisj@…>
Branches:
master
Children:
c4c2682
Parents:
e058db0
git-author:
Chris Johns <chrisj@…> (11/07/18 03:58:17)
git-committer:
Chris Johns <chrisj@…> (11/08/18 07:13:55)
Message:

tester: Update the Python TFTP server to fix Python3 issues.

Updated to af2f2fe89a3bf45748b78703820efb0986a8207a.
Repo is https://github.com/msoulier/tftpy.git

Location:
tester/rt
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • tester/rt/tftp.py

    re058db0 rf24e116  
    120120
    121121    def _listener(self):
    122         tftpy.log.setLevel(100)
     122        tftpy_log = logging.getLogger('tftpy')
     123        tftpy_log.setLevel(100)
    123124        try:
    124125            self.server = tftpy.TftpServer(tftproot = '.',
  • tester/rt/tftpy/TftpClient.py

    re058db0 rf24e116  
     1# vim: ts=4 sw=4 et ai:
     2# -*- coding: utf8 -*-
    13"""This module implements the TFTP Client functionality. Instantiate an
    24instance of the client, and then use its upload or download method. Logging is
    35performed via a standard logging object set in TftpShared."""
    46
    5 from __future__ import absolute_import, division, print_function, unicode_literals
     7
    68import types
     9import logging
    710from .TftpShared import *
    811from .TftpPacketTypes import *
    912from .TftpContexts import TftpContextClientDownload, TftpContextClientUpload
     13
     14log = logging.getLogger('tftpy.TftpClient')
    1015
    1116class TftpClient(TftpSession):
     
    2429        if 'blksize' in self.options:
    2530            size = self.options['blksize']
    26             tftpassert(types.IntType == type(size), "blksize must be an int")
     31            tftpassert(int == type(size), "blksize must be an int")
    2732            if size < MIN_BLKSIZE or size > MAX_BLKSIZE:
    2833                raise TftpException("Invalid blksize: %d" % size)
  • tester/rt/tftpy/TftpContexts.py

    re058db0 rf24e116  
     1# vim: ts=4 sw=4 et ai:
     2# -*- coding: utf8 -*-
    13"""This module implements all contexts for state handling during uploads and
    24downloads, the main interface to which being the TftpContext base class.
     
    911error, in which case a TftpException is returned instead."""
    1012
    11 from __future__ import absolute_import, division, print_function, unicode_literals
     13
    1214from .TftpShared import *
    1315from .TftpPacketTypes import *
    1416from .TftpPacketFactory import TftpPacketFactory
    1517from .TftpStates import *
    16 import socket, time, sys
     18import socket
     19import time
     20import sys
     21import os
     22import logging
     23
     24log = logging.getLogger('tftpy.TftpContext')
    1725
    1826###############################################################################
     
    121129        raise NotImplementedError("Abstract method")
    122130
    123     def end(self):
     131    def end(self, close_fileobj=True):
    124132        """Perform session cleanup, since the end method should always be
    125133        called explicitely by the calling code, this works better than the
    126         destructor."""
    127         log.debug("in TftpContext.end")
     134        destructor.
     135        Set close_fileobj to False so fileobj can be returned open."""
     136        log.debug("in TftpContext.end - closing socket")
    128137        self.sock.close()
    129         if self.fileobj is not None and not self.fileobj.closed:
     138        if close_fileobj and self.fileobj is not None and not self.fileobj.closed:
    130139            log.debug("self.fileobj is open - closing")
    131140            self.fileobj.close()
     
    160169            (buffer, (raddress, rport)) = self.sock.recvfrom(MAX_BLKSIZE)
    161170        except socket.timeout:
    162             log.warn("Timeout waiting for traffic, retrying...")
     171            log.warning("Timeout waiting for traffic, retrying...")
    163172            raise TftpTimeout("Timed-out waiting for traffic")
    164173
     
    174183        # Check for known "connection".
    175184        if raddress != self.address:
    176             log.warn("Received traffic from %s, expected host %s. Discarding"
     185            log.warning("Received traffic from %s, expected host %s. Discarding"
    177186                        % (raddress, self.host))
    178187
    179188        if self.tidport and self.tidport != rport:
    180             log.warn("Received traffic from %s:%s but we're "
     189            log.warning("Received traffic from %s:%s but we're "
    181190                        "connected to %s:%s. Discarding."
    182191                        % (raddress, rport,
     
    316325                    raise
    317326                else:
    318                     log.warn("resending last packet")
     327                    log.warning("resending last packet")
    319328                    self.state.resendLast()
    320329
     
    348357        self.options = options
    349358        self.packethook = packethook
     359        self.filelike_fileobj = False
    350360        # If the output object has a write() function,
    351361        # assume it is file-like.
    352362        if hasattr(output, 'write'):
    353363            self.fileobj = output
     364            self.filelike_fileobj = True
    354365        # If the output filename is -, then use stdout
    355366        elif output == '-':
    356367            self.fileobj = sys.stdout
     368            self.filelike_fileobj = True
    357369        else:
    358370            self.fileobj = open(output, "wb")
     
    396408                    raise
    397409                else:
    398                     log.warn("resending last packet")
     410                    log.warning("resending last packet")
    399411                    self.state.resendLast()
     412            except TftpFileNotFoundError as err:
     413                # If we received file not found, then we should not save the open
     414                # output file or we'll be left with a size zero file. Delete it,
     415                # if it exists.
     416                log.error("Received File not found error")
     417                if self.fileobj is not None and not self.filelike_fileobj:
     418                    if os.path.exists(self.fileobj.name):
     419                        log.debug("unlinking output file of %s", self.fileobj.name)
     420                        os.unlink(self.fileobj.name)
     421
     422                raise
    400423
    401424    def end(self):
    402425        """Finish up the context."""
    403         TftpContext.end(self)
     426        TftpContext.end(self, not self.filelike_fileobj)
    404427        self.metrics.end_time = time.time()
    405428        log.debug("Set metrics.end_time to %s" % self.metrics.end_time)
  • tester/rt/tftpy/TftpPacketFactory.py

    re058db0 rf24e116  
     1# vim: ts=4 sw=4 et ai:
     2# -*- coding: utf8 -*-
    13"""This module implements the TftpPacketFactory class, which can take a binary
    24buffer, and return the appropriate TftpPacket object to represent it, via the
    35parse() method."""
    46
    5 from __future__ import absolute_import, division, print_function, unicode_literals
     7
    68from .TftpShared import *
    79from .TftpPacketTypes import *
     10import logging
     11
     12log = logging.getLogger('tftpy.TftpPacketFactory')
    813
    914class TftpPacketFactory(object):
     
    2631        the network."""
    2732        log.debug("parsing a %d byte packet" % len(buffer))
    28         (opcode,) = struct.unpack("!H", buffer[:2])
     33        (opcode,) = struct.unpack(str("!H"), buffer[:2])
    2934        log.debug("opcode is %d" % opcode)
    3035        packet = self.__create(opcode)
  • tester/rt/tftpy/TftpPacketTypes.py

    re058db0 rf24e116  
     1# vim: ts=4 sw=4 et ai:
     2# -*- coding: utf8 -*-
    13"""This module implements the packet types of TFTP itself, and the
    24corresponding encode and decode methods for them."""
    35
    4 from __future__ import absolute_import, division, print_function, unicode_literals
     6
    57import struct
    68import sys
     9import logging
    710from .TftpShared import *
     11
     12log = logging.getLogger('tftpy.TftpPacketTypes')
    813
    914class TftpSession(object):
     
    2126        self.options = {}
    2227
     28    # Always use unicode strings, except at the encode/decode barrier.
     29    # Simpler to keep things clear.
    2330    def setoptions(self, options):
    2431        log.debug("in TftpPacketWithOptions.setoptions")
    25         log.debug("options: %s" % options)
     32        log.debug("options: %s", options)
    2633        myoptions = {}
    2734        for key in options:
    28             newkey = str(key)
    29             myoptions[newkey] = str(options[key])
    30             log.debug("populated myoptions with %s = %s"
    31                          % (newkey, myoptions[newkey]))
    32 
    33         log.debug("setting options hash to: %s" % myoptions)
     35            newkey = key
     36            if isinstance(key, bytes):
     37                newkey = newkey.decode('ascii')
     38            newval = options[key]
     39            if isinstance(newval, bytes):
     40                newval = newval.decode('ascii')
     41            myoptions[newkey] = newval
     42            log.debug("populated myoptions with %s = %s", newkey, myoptions[newkey])
     43
     44        log.debug("setting options hash to: %s", myoptions)
    3445        self._options = myoptions
    3546
     
    4758        unknown number of options. It returns a dictionary of option names and
    4859        values."""
    49         format = "!"
     60        fmt = b"!"
    5061        options = {}
    5162
    52         log.debug("decode_options: buffer is: %s" % repr(buffer))
    53         log.debug("size of buffer is %d bytes" % len(buffer))
     63        log.debug("decode_options: buffer is: %s", repr(buffer))
     64        log.debug("size of buffer is %d bytes", len(buffer))
    5465        if len(buffer) == 0:
    5566            log.debug("size of buffer is zero, returning empty hash")
     
    5970        log.debug("about to iterate options buffer counting nulls")
    6071        length = 0
    61         for c in buffer:
    62             if ord(c) == 0:
    63                 log.debug("found a null at length %d" % length)
     72        for i in range(len(buffer)):
     73            if ord(buffer[i:i+1]) == 0:
     74                log.debug("found a null at length %d", length)
    6475                if length > 0:
    65                     format += "%dsx" % length
     76                    fmt += b"%dsx" % length
    6677                    length = -1
    6778                else:
     
    6980            length += 1
    7081
    71         log.debug("about to unpack, format is: %s" % format)
    72         mystruct = struct.unpack(format, buffer)
     82        log.debug("about to unpack, fmt is: %s", fmt)
     83        mystruct = struct.unpack(fmt, buffer)
    7384
    7485        tftpassert(len(mystruct) % 2 == 0,
     
    7687
    7788        for i in range(0, len(mystruct), 2):
    78             log.debug("setting option %s to %s" % (mystruct[i], mystruct[i+1]))
    79             options[mystruct[i]] = mystruct[i+1]
     89            key = mystruct[i].decode('ascii')
     90            val = mystruct[i+1].decode('ascii')
     91            log.debug("setting option %s to %s", key, val)
     92            log.debug("types are %s and %s", type(key), type(val))
     93            options[key] = val
    8094
    8195        return options
     
    121135        tftpassert(self.mode, "mode required in initial packet")
    122136        # Make sure filename and mode are bytestrings.
    123         self.filename = self.filename.encode('ascii')
    124         self.mode = self.mode.encode('ascii')
     137        filename = self.filename
     138        mode = self.mode
     139        if not isinstance(filename, bytes):
     140            filename = filename.encode('ascii')
     141        if not isinstance(self.mode, bytes):
     142            mode = mode.encode('ascii')
    125143
    126144        ptype = None
    127145        if self.opcode == 1: ptype = "RRQ"
    128146        else:                ptype = "WRQ"
    129         log.debug("Encoding %s packet, filename = %s, mode = %s"
    130                      % (ptype, self.filename, self.mode))
     147        log.debug("Encoding %s packet, filename = %s, mode = %s",
     148            ptype, filename, mode)
    131149        for key in self.options:
    132             log.debug("    Option %s = %s" % (key, self.options[key]))
    133 
    134         format = b"!H"
    135         format += b"%dsx" % len(self.filename)
    136         if self.mode == b"octet":
    137             format += b"5sx"
     150            log.debug("    Option %s = %s", key, self.options[key])
     151
     152        fmt = b"!H"
     153        fmt += b"%dsx" % len(filename)
     154        if mode == b"octet":
     155            fmt += b"5sx"
    138156        else:
    139             raise AssertionError("Unsupported mode: %s" % self.mode)
    140         # Add options.
     157            raise AssertionError("Unsupported mode: %s" % mode)
     158        # Add options. Note that the options list must be bytes.
    141159        options_list = []
    142         if len(self.options.keys()) > 0:
     160        if len(list(self.options.keys())) > 0:
    143161            log.debug("there are options to encode")
    144162            for key in self.options:
    145163                # Populate the option name
    146                 format += b"%dsx" % len(key)
    147                 options_list.append(key.encode('ascii'))
     164                name = key
     165                if not isinstance(name, bytes):
     166                    name = name.encode('ascii')
     167                options_list.append(name)
     168                fmt += b"%dsx" % len(name)
    148169                # Populate the option value
    149                 format += b"%dsx" % len(self.options[key].encode('ascii'))
    150                 options_list.append(self.options[key].encode('ascii'))
    151 
    152         log.debug("format is %s" % format)
    153         log.debug("options_list is %s" % options_list)
    154         log.debug("size of struct is %d" % struct.calcsize(format))
    155 
    156         self.buffer = struct.pack(format,
     170                value = self.options[key]
     171                # Work with all strings.
     172                if isinstance(value, int):
     173                    value = str(value)
     174                if not isinstance(value, bytes):
     175                    value = value.encode('ascii')
     176                options_list.append(value)
     177                fmt += b"%dsx" % len(value)
     178
     179        log.debug("fmt is %s", fmt)
     180        log.debug("options_list is %s", options_list)
     181        log.debug("size of struct is %d", struct.calcsize(fmt))
     182       
     183        self.buffer = struct.pack(fmt,
    157184                                  self.opcode,
    158                                   self.filename,
    159                                   self.mode,
     185                                  filename,
     186                                  mode,
    160187                                  *options_list)
    161188
    162         log.debug("buffer is %s" % repr(self.buffer))
     189        log.debug("buffer is %s", repr(self.buffer))
    163190        return self
    164191
     
    168195        # FIXME - this shares a lot of code with decode_options
    169196        nulls = 0
    170         format = ""
     197        fmt = b""
    171198        nulls = length = tlength = 0
    172199        log.debug("in decode: about to iterate buffer counting nulls")
    173200        subbuf = self.buffer[2:]
    174         for c in subbuf:
    175             if sys.version_info[0] <= 2:
    176                 c = ord(c)
    177             if c == 0:
     201        for i in range(len(subbuf)):
     202            if ord(subbuf[i:i+1]) == 0:
    178203                nulls += 1
    179                 log.debug("found a null at length %d, now have %d"
    180                              % (length, nulls))
    181                 format += "%dsx" % length
     204                log.debug("found a null at length %d, now have %d", length, nulls)
     205                fmt += b"%dsx" % length
    182206                length = -1
    183207                # At 2 nulls, we want to mark that position for decoding.
     
    187211            tlength += 1
    188212
    189         log.debug("hopefully found end of mode at length %d" % tlength)
     213        log.debug("hopefully found end of mode at length %d", tlength)
    190214        # length should now be the end of the mode.
    191215        tftpassert(nulls == 2, "malformed packet")
    192216        shortbuf = subbuf[:tlength+1]
    193         log.debug("about to unpack buffer with format: %s" % format)
    194         log.debug("unpacking buffer: " + repr(shortbuf))
    195         mystruct = struct.unpack(format, shortbuf)
     217        log.debug("about to unpack buffer with fmt: %s", fmt)
     218        log.debug("unpacking buffer: %s", repr(shortbuf))
     219        mystruct = struct.unpack(fmt, shortbuf)
    196220
    197221        tftpassert(len(mystruct) == 2, "malformed packet")
    198         self.filename = mystruct[0]
    199         self.mode = mystruct[1].lower() # force lc - bug 17
    200         log.debug("set filename to %s" % self.filename)
    201         log.debug("set mode to %s" % self.mode)
     222        self.filename = mystruct[0].decode('ascii')
     223        self.mode = mystruct[1].decode('ascii').lower() # force lc - bug 17
     224        log.debug("set filename to %s", self.filename)
     225        log.debug("set mode to %s", self.mode)
    202226
    203227        self.options = self.decode_options(subbuf[tlength+1:])
     228        log.debug("options dict is now %s", self.options)
    204229        return self
    205230
     
    270295        if len(self.data) == 0:
    271296            log.debug("Encoding an empty DAT packet")
    272         format = "!HH%ds" % len(self.data)
    273         self.buffer = struct.pack(format,
     297        data = self.data
     298        if not isinstance(self.data, bytes):
     299            data = self.data.encode('ascii')
     300        fmt = b"!HH%ds" % len(data)
     301        self.buffer = struct.pack(fmt,
    274302                                  self.opcode,
    275303                                  self.blocknumber,
    276                                   self.data)
     304                                  data)
    277305        return self
    278306
     
    282310        # We know the first 2 bytes are the opcode. The second two are the
    283311        # block number.
    284         (self.blocknumber,) = struct.unpack("!H", self.buffer[2:4])
    285         log.debug("decoding DAT packet, block number %d" % self.blocknumber)
    286         log.debug("should be %d bytes in the packet total"
    287                      % len(self.buffer))
     312        (self.blocknumber,) = struct.unpack(str("!H"), self.buffer[2:4])
     313        log.debug("decoding DAT packet, block number %d", self.blocknumber)
     314        log.debug("should be %d bytes in the packet total", len(self.buffer))
    288315        # Everything else is data.
    289316        self.data = self.buffer[4:]
    290         log.debug("found %d bytes of data"
    291                      % len(self.data))
     317        log.debug("found %d bytes of data", len(self.data))
    292318        return self
    293319
     
    310336
    311337    def encode(self):
    312         log.debug("encoding ACK: opcode = %d, block = %d"
    313                      % (self.opcode, self.blocknumber))
    314         self.buffer = struct.pack("!HH", self.opcode, self.blocknumber)
     338        log.debug("encoding ACK: opcode = %d, block = %d",
     339            self.opcode, self.blocknumber)
     340        self.buffer = struct.pack(str("!HH"), self.opcode, self.blocknumber)
    315341        return self
    316342
     
    320346            log.debug("buffer was: %s", repr(self.buffer))
    321347            self.buffer = self.buffer[0:4]
    322         self.opcode, self.blocknumber = struct.unpack("!HH", self.buffer)
    323         log.debug("decoded ACK packet: opcode = %d, block = %d"
    324                      % (self.opcode, self.blocknumber))
     348        self.opcode, self.blocknumber = struct.unpack(str("!HH"), self.buffer)
     349        log.debug("decoded ACK packet: opcode = %d, block = %d",
     350            self.opcode, self.blocknumber)
    325351        return self
    326352
     
    374400        """Encode the DAT packet based on instance variables, populating
    375401        self.buffer, returning self."""
    376         format = "!HH%dsx" % len(self.errmsgs[self.errorcode])
    377         log.debug("encoding ERR packet with format %s" % format)
    378         self.buffer = struct.pack(format,
     402        fmt = b"!HH%dsx" % len(self.errmsgs[self.errorcode])
     403        log.debug("encoding ERR packet with fmt %s", fmt)
     404        self.buffer = struct.pack(fmt,
    379405                                  self.opcode,
    380406                                  self.errorcode,
     
    386412        buflen = len(self.buffer)
    387413        tftpassert(buflen >= 4, "malformed ERR packet, too short")
    388         log.debug("Decoding ERR packet, length %s bytes" % buflen)
     414        log.debug("Decoding ERR packet, length %s bytes", buflen)
    389415        if buflen == 4:
    390416            log.debug("Allowing this affront to the RFC of a 4-byte packet")
    391             format = "!HH"
    392             log.debug("Decoding ERR packet with format: %s" % format)
    393             self.opcode, self.errorcode = struct.unpack(format,
     417            fmt = b"!HH"
     418            log.debug("Decoding ERR packet with fmt: %s", fmt)
     419            self.opcode, self.errorcode = struct.unpack(fmt,
    394420                                                        self.buffer)
    395421        else:
    396422            log.debug("Good ERR packet > 4 bytes")
    397             format = "!HH%dsx" % (len(self.buffer) - 5)
    398             log.debug("Decoding ERR packet with format: %s" % format)
    399             self.opcode, self.errorcode, self.errmsg = struct.unpack(format,
     423            fmt = b"!HH%dsx" % (len(self.buffer) - 5)
     424            log.debug("Decoding ERR packet with fmt: %s", fmt)
     425            self.opcode, self.errorcode, self.errmsg = struct.unpack(fmt,
    400426                                                                     self.buffer)
    401427        log.error("ERR packet - errorcode: %d, message: %s"
     
    420446
    421447    def encode(self):
    422         format = "!H" # opcode
     448        fmt = b"!H" # opcode
    423449        options_list = []
    424450        log.debug("in TftpPacketOACK.encode")
    425451        for key in self.options:
    426             log.debug("looping on option key %s" % key)
    427             log.debug("value is %s" % self.options[key])
    428             format += "%dsx" % len(key)
    429             format += "%dsx" % len(self.options[key])
     452            value = self.options[key]
     453            if isinstance(value, int):
     454                value = str(value)
     455            if not isinstance(key, bytes):
     456                key = key.encode('ascii')
     457            if not isinstance(value, bytes):
     458                value = value.encode('ascii')
     459            log.debug("looping on option key %s", key)
     460            log.debug("value is %s", value)
     461            fmt += b"%dsx" % len(key)
     462            fmt += b"%dsx" % len(value)
    430463            options_list.append(key)
    431             options_list.append(self.options[key])
    432         self.buffer = struct.pack(format, self.opcode, *options_list)
     464            options_list.append(value)
     465        self.buffer = struct.pack(fmt, self.opcode, *options_list)
    433466        return self
    434467
  • tester/rt/tftpy/TftpServer.py

    re058db0 rf24e116  
     1# vim: ts=4 sw=4 et ai:
     2# -*- coding: utf8 -*-
    13"""This module implements the TFTP Server functionality. Instantiate an
    24instance of the server, and then run the listen() method to listen for client
     
    46TftpShared."""
    57
    6 from __future__ import absolute_import, division, print_function, unicode_literals
     8
    79import socket, os, time
    810import select
    911import threading
     12import logging
    1013from errno import EINTR
    1114from .TftpShared import *
     
    1316from .TftpPacketFactory import TftpPacketFactory
    1417from .TftpContexts import TftpContextServer
     18
     19log = logging.getLogger('tftpy.TftpServer')
    1520
    1621class TftpServer(TftpSession):
     
    5459            attr = getattr(self, name)
    5560            if attr and not callable(attr):
    56                 raise TftpException, "%s supplied, but it is not callable." % (
    57                     name,)
     61                raise TftpException("{} supplied, but it is not callable.".format(name))
    5862        if os.path.exists(self.root):
    5963            log.debug("tftproot %s does exist", self.root)
     
    100104            log.debug("shutdown_gracefully is %s" % self.shutdown_gracefully)
    101105            if self.shutdown_immediately:
    102                 log.warn("Shutting down now. Session count: %d" %
     106                log.warning("Shutting down now. Session count: %d" %
    103107                         len(self.sessions))
    104108                self.sock.close()
     
    110114            elif self.shutdown_gracefully:
    111115                if not self.sessions:
    112                     log.warn("In graceful shutdown mode and all "
     116                    log.warning("In graceful shutdown mode and all "
    113117                             "sessions complete.")
    114118                    self.sock.close()
     
    125129            try:
    126130                readyinput, readyoutput, readyspecial = \
    127                         select.select(inputlist, [], [], timeout)
     131                        select.select(inputlist, [], [], SOCK_TIMEOUT)
    128132            except select.error as err:
    129133                if err[0] == EINTR:
     
    146150
    147151                    if self.shutdown_gracefully:
    148                         log.warn("Discarding data on main port, "
     152                        log.warning("Discarding data on main port, "
    149153                                 "in graceful shutdown mode")
    150154                        continue
     
    170174                                      "session %s: %s" % (key, str(err)))
    171175                    else:
    172                         log.warn("received traffic on main socket for "
     176                        log.warning("received traffic on main socket for "
    173177                                 "existing session??")
    174178                    log.info("Currently handling these sessions:")
    175                     for session_key, session in self.sessions.items():
     179                    for session_key, session in list(self.sessions.items()):
    176180                        log.info("    %s" % session)
    177181
     
    235239                    log.debug("Session list is now %s" % self.sessions)
    236240                else:
    237                     log.warn(
     241                    log.warning(
    238242                        "Strange, session %s is not on the deletion list" % key)
    239243
  • tester/rt/tftpy/TftpShared.py

    re058db0 rf24e116  
     1# vim: ts=4 sw=4 et ai:
     2# -*- coding: utf8 -*-
    13"""This module holds all objects shared by all other modules in tftpy."""
    24
    3 from __future__ import absolute_import, division, print_function, unicode_literals
    4 import logging
    5 from logging.handlers import RotatingFileHandler
    65
    7 LOG_LEVEL = logging.NOTSET
     6
    87MIN_BLKSIZE = 8
    98DEF_BLKSIZE = 512
     
    1716DELAY_BLOCK = 0
    1817
    19 # Initialize the logger.
    20 logging.basicConfig()
    21 
    22 # The logger used by this library. Feel free to clobber it with your own, if
    23 # you like, as long as it conforms to Python's logging.
    24 log = logging.getLogger('tftpy')
    25 
    26 def create_streamhandler():
    27     """add create_streamhandler output logging.DEBUG msg to stdout.
    28     """
    29     console = logging.StreamHandler()
    30     console.setLevel(logging.INFO)
    31     formatter = logging.Formatter('%(levelname)-8s %(message)s')
    32     console.setFormatter(formatter)
    33     return console
    34 
    35 def create_rotatingfilehandler(path, maxbytes=10*1024*1024, count=20):
    36     """
    37     add create_rotatingfilehandler record the logging.DEBUG msg to logfile. you can change the maxsize (10*1024*1024)
    38     and amount of the logfiles
    39     """
    40     Rthandler = RotatingFileHandler(path, maxbytes, count)
    41     Rthandler.setLevel(logging.INFO)
    42     formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
    43     Rthandler.setFormatter(formatter)
    44     return Rthandler
    45 
    46 def addHandler(hdlr):
    47     """add handler methods
    48     More details see the page:
    49     https://docs.python.org/2/library/logging.handlers.html#module-logging.handlers
    50     """
    51     log.addHandler(hdlr)
    52 
    5318def tftpassert(condition, msg):
    5419    """This function is a simple utility that will check the condition
     
    5823    if not condition:
    5924        raise TftpException(msg)
    60 
    61 def setLogLevel(level):
    62     """This function is a utility function for setting the internal log level.
    63     The log level defaults to logging.NOTSET, so unwanted output to stdout is
    64     not created."""
    65     log.setLevel(level)
    6625
    6726class TftpErrors(object):
     
    8746    other end."""
    8847    pass
     48
     49class TftpFileNotFoundError(TftpException):
     50    """This class represents an error condition where we received a file
     51    not found error."""
     52    pass
  • tester/rt/tftpy/TftpStates.py

    re058db0 rf24e116  
     1# vim: ts=4 sw=4 et ai:
     2# -*- coding: utf8 -*-
    13"""This module implements all state handling during uploads and downloads, the
    24main interface to which being the TftpState base class.
     
    911error, in which case a TftpException is returned instead."""
    1012
    11 from __future__ import absolute_import, division, print_function, unicode_literals
     13
    1214from .TftpShared import *
    1315from .TftpPacketTypes import *
    1416import os
     17import logging
     18
     19log = logging.getLogger('tftpy.TftpStates')
    1520
    1621###############################################################################
     
    3540        """This method handles an OACK from the server, syncing any accepted
    3641        options."""
    37         if pkt.options.keys() > 0:
     42        if len(pkt.options.keys()) > 0:
    3843            if pkt.match_options(self.context.options):
    3944                log.info("Successful negotiation of options")
     
    127132        errpkt = TftpPacketERR()
    128133        errpkt.errorcode = errorcode
    129         self.context.sock.sendto(errpkt.encode().buffer,
    130                                  (self.context.host,
    131                                   self.context.tidport))
     134        if self.context.tidport == None:
     135            log.debug("Error packet received outside session. Discarding")
     136        else:
     137            self.context.sock.sendto(errpkt.encode().buffer,
     138                                     (self.context.host,
     139                                      self.context.tidport))
    132140        self.context.last_pkt = errpkt
    133141
     
    145153    def resendLast(self):
    146154        "Resend the last sent packet due to a timeout."
    147         log.warn("Resending packet %s on sessions %s"
     155        log.warning("Resending packet %s on sessions %s"
    148156            % (self.context.last_pkt, self))
    149157        self.context.metrics.resent_bytes += len(self.context.last_pkt.buffer)
     
    181189        elif pkt.blocknumber < self.context.next_block:
    182190            if pkt.blocknumber == 0:
    183                 log.warn("There is no block zero!")
     191                log.warning("There is no block zero!")
    184192                self.sendError(TftpErrors.IllegalTftpOp)
    185193                raise TftpException("There is no block zero!")
    186             log.warn("Dropping duplicate block %d" % pkt.blocknumber)
     194            log.warning("Dropping duplicate block %d" % pkt.blocknumber)
    187195            self.context.metrics.add_dup(pkt)
    188196            log.debug("ACKing block %d again, just in case", pkt.blocknumber)
     
    262270        # treat it as absolute (regardless of whether it is ntpath or
    263271        # posixpath module
    264         if pkt.filename.startswith(self.context.root.encode()):
     272        if pkt.filename.startswith(self.context.root):
    265273            full_path = pkt.filename
    266274        else:
    267             full_path = os.path.join(self.context.root, pkt.filename.decode().lstrip('/'))
     275            full_path = os.path.join(self.context.root, pkt.filename.lstrip('/'))
    268276
    269277        # Use abspath to eliminate any remaining relative elements
     
    275283            log.info("requested file is in the server root - good")
    276284        else:
    277             log.warn("requested file is not within the server root - bad")
     285            log.warning("requested file is not within the server root - bad")
    278286            self.sendError(TftpErrors.IllegalTftpOp)
    279287            raise TftpException("bad file path")
     
    308316                raise TftpException("File not found: %s" % path)
    309317        else:
     318            log.warn("File not found: %s", path)
    310319            self.sendError(TftpErrors.FileNotFound)
    311             raise TftpException("File not found: %s" % path)
     320            raise TftpException("File not found: {}".format(path))
    312321
    313322        # Options negotiation.
    314         if sendoack and self.context.options.has_key('tsize'):
     323        if sendoack and 'tsize' in self.context.options:
    315324            # getting the file size for the tsize option. As we handle
    316325            # file-like objects and not only real files, we use this seeking
     
    369378            if f is None:
    370379                self.sendError(TftpErrors.AccessViolation)
    371                 raise TftpException, "Dynamic path %s not permitted" % path
     380                raise TftpException("Dynamic path %s not permitted" % path)
    372381            else:
    373382                self.context.fileobj = f
     
    376385            if os.path.exists(path):
    377386                # FIXME: correct behavior?
    378                 log.warn("File %s exists already, overwriting..." % (
     387                log.warning("File %s exists already, overwriting..." % (
    379388                    self.context.file_to_transfer))
    380389            # FIXME: I think we should upload to a temp file and not overwrite
     
    444453
    445454            elif pkt.blocknumber < self.context.next_block:
    446                 log.warn("Received duplicate ACK for block %d"
     455                log.warning("Received duplicate ACK for block %d"
    447456                    % pkt.blocknumber)
    448457                self.context.metrics.add_dup(pkt)
    449458
    450459            else:
    451                 log.warn("Oooh, time warp. Received ACK to packet we "
     460                log.warning("Oooh, time warp. Received ACK to packet we "
    452461                         "didn't send yet. Discarding.")
    453462                self.context.metrics.errors += 1
     
    457466            raise TftpException("Received ERR packet from peer: %s" % str(pkt))
    458467        else:
    459             log.warn("Discarding unsupported packet: %s" % str(pkt))
     468            log.warning("Discarding unsupported packet: %s" % str(pkt))
    460469            return self
    461470
     
    520529                return TftpStateExpectACK(self.context)
    521530            else:
    522                 log.warn("Discarding ACK to block %s" % pkt.blocknumber)
     531                log.warning("Discarding ACK to block %s" % pkt.blocknumber)
    523532                log.debug("Still waiting for valid response from server")
    524533                return self
     
    589598        elif isinstance(pkt, TftpPacketERR):
    590599            self.sendError(TftpErrors.IllegalTftpOp)
    591             raise TftpException("Received ERR from server: %s" % pkt)
     600            log.debug("Received ERR packet: %s", pkt)
     601            if pkt.errorcode == TftpErrors.FileNotFound:
     602                raise TftpFileNotFoundError("File not found")
     603            else:
     604                raise TftpException("Received ERR from server: {}".format(pkt))
    592605
    593606        else:
  • tester/rt/tftpy/__init__.py

    re058db0 rf24e116  
     1# vim: ts=4 sw=4 et ai:
     2# -*- coding: utf8 -*-
    13"""
    24This library implements the tftp protocol, based on rfc 1350.
     
    911"""
    1012
    11 from __future__ import absolute_import, division, print_function, unicode_literals
     13
    1214import sys
    1315
    14 # Make sure that this is at least Python 2.3
    15 required_version = (2, 3)
     16# Make sure that this is at least Python 2.7
     17required_version = (2, 7)
    1618if sys.version_info < required_version:
    17     raise ImportError("Requires at least Python 2.3")
     19    raise ImportError("Requires at least Python 2.7")
    1820
    1921from .TftpShared import *
    20 from .TftpPacketTypes import *
    21 from .TftpPacketFactory import *
    22 from .TftpClient import *
    23 from .TftpServer import *
    24 from .TftpContexts import *
    25 from .TftpStates import *
    26 
     22from . import TftpPacketTypes
     23from . import TftpPacketFactory
     24from .TftpClient import TftpClient
     25from .TftpServer import TftpServer
     26from . import TftpContexts
     27from . import TftpStates
Note: See TracChangeset for help on using the changeset viewer.