pythonalgorithmtftp

is the logic behind my trivial tftp client flawed?


I'm still a student so I might have missed something really obvious.

So I am stressing out about this so much.

But anyway here's my TFTP python code, all it does is downloading a text-file from our lecturer's server.

The file generated by it looks like this: http://pastebin.com/TP8hngxM

And the original file like this: http://pastebin.com/xDMjkABp

And if you run it through a difference checker, the difference is miniscule and in only 1 specific spot and it's really difficult for me to figure out why is this happening.

The downloaded file has a few extra words.

If you have spare 5 minutes, could you please check out my nested while loop (everything else was provided by the lecturer and can't be changed) to see if there's anything wrong with it?

The worst thing is that I've already had it working, but I lost my memory stick and I lost the most up-to-date version of the program that was running 100% fine.

So as I said, it's only about the nested while loop, I' not allowed to change anything above it.

    #!/usr/bin/python

import struct
import sys
import os
import select
import glamnetsim
from socket import *

serverHost  = 'mcgreg.comp.glam.ac.uk'
serverPort  = 69
timeoutSecs =  5
debugging   = False
RRQ, WRQ, DATA, ACK, ERROR = range(1, 6)
codeDescriptions = {RRQ:"RRQ", WRQ:"WRQ", DATA:"DATA", ACK:"ACK", ERROR:"ERROR"}

def printf (format, *args):
    print str(format) % args,

def finish ():

    printf("you should see\n1e951df315d433aa4df2065a1ad31311\n")
    os.system("md5sum newfile.txt")
    sys.exit(0)

def sendPacket (packet, port):
    global sock, debugging
    global serverIp
    if debugging:
        for i in packet:
            print ('%02x' % ord(i)),
        print ''
    sock.sendto(packet, (serverIp, port))

def sendReadRequest (filename, mode):
    global serverPort
    format = "!H%ds" % (len(filename)+1)
    format += "%ds" % (len(mode)+1)
    s = struct.pack(format, 1, filename, mode)
    sendPacket(s, serverPort)

def sendRealAck(blockno, port):
    s = struct.pack("!H", 4)
    s += struct.pack("!H", blockno)
    sendPacket(s, port)

def sendACK (blockno, port):
    print " -> ACK:%d\n" % blockno
    if blockno == 0:
        sendReadRequest("the_machine_stops.txt", "octet")
    else:
        sendRealAck(blockno, port)

def stripPacket (s):
    if len(s)>3:
        code = struct.unpack("!H", s[:2])[0]
        blockno = struct.unpack("!H", s[2:4])[0]
        data = s[4:]
        code, data = glamnetsim.simulatePossibleError (code, data)
        return code,blockno,data
    else:
        debugPrint("corrupt packet")
        return -1,-1,""

        def debugPrint (s):
    global debugging
    if debugging:
        print s

def getDesc (c):
    global codeDescriptions
    return codeDescriptions[c]

sock = socket(AF_INET, SOCK_DGRAM)
serverIp = gethostbyname(serverHost)
sock.setblocking(1)
sendReadRequest("the_machine_stops.txt", "netascii")
lastblock = 0
blockno = 0
port = serverPort
f = open("newfile.txt", "w")

while True:
    while True:

        if blockno == lastblock+1:
                break

        r, w, x = select.select([sock], [], [], 5.0)

        if r == []:
            sendACK(lastblock, port)

        else:

            (packet, (address, port)) = sock.recvfrom(512+4)
            code, newblock, text = stripPacket(packet)
            print code, blockno         

            if code is 3:
                blockno = newblock
                sendACK(blockno, port)

            if code is 5:
                sendACK(lastblock, port)

            print "Bn: " + str(blockno) + " Lb: " + str(lastblock)
    lastblock = blockno
    f.write(text)
    print "OK"
    if len(text) < 512:
        break
f.close()
finish()

Solution

  • f.write(text)

    That line is run with a stale value if blockno == lastblock+1. It probably should be within the inner loop.