Started on the server

git-svn-id: https://tftpy.svn.sourceforge.net/svnroot/tftpy/trunk@37 63283fd4-ec1e-0410-9879-cb7f675518da
This commit is contained in:
msoulier 2006-12-10 19:12:43 +00:00
parent aece5aaf2e
commit fc2a587641
3 changed files with 79 additions and 3 deletions

2
README
View file

@ -26,7 +26,7 @@ client and server classes, with sample implementations. Hooks are included for
easy inclusion in a UI for populating progress indicators. It supports RFCs
1350, 2347 and 2348.
This library was developed against Python 2.4.1.
This library was developed against Python 2.3.
Project page: http://sourceforge.net/projects/tftpy/

View file

@ -2,7 +2,11 @@
import sys, logging, os
from optparse import OptionParser
import tftpy
try:
import tftpy
except ImportError, err:
sys.path.append('../lib')
import tftpy
def main():
usage=""

View file

@ -18,6 +18,7 @@ MAX_BLKSIZE = 65536
SOCK_TIMEOUT = 5
MAX_DUPS = 20
TIMEOUT_RETRIES = 5
DEF_TFTP_PORT = 69
# Initialize the logger.
logging.basicConfig(
@ -484,13 +485,84 @@ class TftpState(object):
class TftpSession(object):
"""This class is the base class for the tftp client and server. Any shared
code should be in this class."""
def __init__(self):
"Class constructor. Note that the state property must be a TftpState object."
"Class constructor. Note that the state property must be a TftpState
object."
self.options = None
self.state = TftpState()
self.dups = 0
self.errors = 0
class TftpServer(object):
"""This class implements a tftp server object."""
def __init__(self):
"Class constructor."
self.listenip = None
self.listenport = None
self.sock = None
# A dict of handlers, where each session is keyed by a string like
# ip:tid for the remote end.
self.handlers = {}
def listen(self,
listenip=socket.INADDR_ANY,
listenport=DEF_TFTP_PORT,
timeout=SOCK_TIMEOUT):
"""Start a server listening on the supplied interface and port. This
defaults to INADDR_ANY (all interfaces) and UDP port 69. You can also
supply a different socket timeout value, if desired."""
logger.info("Server requested on ip %s, port %s" % (listenip, listenport))
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
logger.info("Starting receive loop...")
while True:
(buffer, (raddress, rport)) = self.sock.recvfrom(MAX_BLKSIZE)
recvpkt = tftp_factory.parse(buffer)
key = "%s:%s" % (raddress, rport)
if isinstance(recvpkt, TftpPacketRRQ):
logger.debug("RRQ packet from %s:%s" % (raddress, rport))
if not self.handlers.has_key(key):
logger.debug("New download request, session key = %s" % key)
self.handlers[key] = TftpServerHandler(key)
self.handlers[key].handle(recvpkt)
elif isinstance(recvpkt, TftpPacketWRQ):
logger.error("Write requests not implemented at this time.")
errpkt = TftpPacketERR()
errpkt.errorcode = 4
self.sock.sendto(errpkt.encode().buffer, (raddress, rport))
continue
if not self.handlers.has_key(key):
logger.error("No existing session with key %s" % key)
errpkt = TftpPacketERR()
errpkt.errorcode = 5
self.sock.sendto(errpkt.encode().buffer, (raddress, rport))
continue
else:
self.handlers[key].handle(recvpkt)
class TftpServerHandler(TftpSession):
"""This class implements a handler for a given server session, handling
the work for one download."""
def __init__(self, key):
TftpSession.__init__(self)
self.key = key
self.sock = self.gensock()
def handle(self, pkt):
logger.debug("Handler %s requested to handle packet %s"
% (self.key, pkt))
def gensock(self):
"""This method generates a new UDP socket, whose listening port must
be randomly generated, and not conflict with any already in use. For
now, let the OS do this."""
return socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
class TftpClient(TftpSession):
"""This class is an implementation of a tftp client."""
def __init__(self, host, port, options={}):