Binary data transfer issue

MRAB python at mrabarnett.plus.com
Tue Mar 16 04:07:37 CET 2010


Jordan Apgar wrote:
> Hi all,
> 
> I'm trying to transfer a binary file over xmlrpclib.   My test file is
> a .jpeg file.  I can transfer all the data over but when I go to open
> the .jpeg I get "Error interpreting JPEG image file (Invalid JPEG file
> structure: SOS before SOF)"
> 
> here's the code:
> 
> ===========Various Shared Functions========
> #EncodeAES takes a Cipher c and encrypts a String s
> EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
> 
> #DecodeAES takes a Cipher C and decrypts the cyphertext e
>     #then removes the padding from the decrypted string
> DecodeAES = lambda c, e:
> c.decrypt(base64.b64decode(e)).rstrip(PADDING)
> 
> 
> CIPHER = AES.new("KEY")
> 
> 
> # method to change strings back into tuples
> def stringToTuple(string):
>     if string[0] + string[-1] == "()":
>         items = string[1:-1]
>         items = items.split(',')
>         return items
>     else:
>         raise ValueError("Badly formatted string (missing brackets).")
> 
> ======client=================
>  def Download(self, FileName, Data_Size=1024):
>         ErrorCount = 0
>         Pkt_Num = -1
>         OldPkt_Num = Pkt_Num
>         localFile = open("files/"+FileName, "wb")
>         print
>         print "Requesting First Packet"
>         packet = self.client.download(EncodeAES(CIPHER, str(Pkt_Num)))
>         if packet[0] == "False":
>             print packet[1]
>             return False
>         packet = stringToTuple(DecodeAES(CIPHER, packet))
>         if int(packet[0]) == -3:
>             print "Received Error Packet"
>         else:
>             print "Received Packet: ", int(packet[0])
> 
>         print "packet[1], ", packet[2:-1]
> 
>         Pkt_Num = int(packet[0])
> 
>         while Pkt_Num >= 0 and ErrorCount <= 10:
>             if (OldPkt_Num +1) == Pkt_Num:
>                 OldPkt_Num = OldPkt_Num +1
>                 localFile.write(binascii.
>                                 a2b_base64(packet[1][2:-1]))
> #<<<<!!!!!<<< writing to the file on the client
>                 ErrorCount == 0
>             else:
>                 ErrorCount = ErrorCount +1
>                 Pkt_Num = OldPkt_Num
> 
>             print "Requesting Packet: ", Pkt_Num +1
>             packet = self.client.download(EncodeAES(CIPHER,
> str(Pkt_Num)))
>             packet = stringToTuple(DecodeAES(CIPHER, packet))
>             Pkt_Num = int(packet[0])
>             if int(packet[0]) == -3:
>                 print "Received Error Packet"
>             elif int(packet[0]) == -2:
>                 print "Received EOF"
>             else:
>                 print "Received Packet: ", int(packet[0])
> 
>         localFile.close()
> 
>         if Pkt_Num == -2:
>             print packet[1][2:-1]
>             return True
>         elif Pkt_Num == -3:
>             os.remove("files/"+FileName)
>             print packet[1][2:-1]
>             return False
>         else:
>             os.remove("files/"+FileName)
>             print "Unexpected Packet: File Transfer Stopped"
>             return False
> 
> 
> ==========Server Method=============
>     def download(self, Pkt_Num):
> 
>         Old_Pkt_Num = self.PKT
>         DataRate = self.DATA
>         Pkt_Num = int(DecodeAES(CIPHER,Pkt_Num))
>         if Pkt_Num == -1 and Old_Pkt_Num == -1:
>             Pkt_Num = 0
>             try:
>                 f = open("files/"+self.usr_dict[client][FILENAME],
> "rb")
>             except IOError:
>                 return EncodeAES(CIPHER,
>                                  str((-3, "File Could Not be
> opened")))
>              data = binascii.b2a_base64(f.read((Pkt_Num+1 *
> DataRate)))     #<<<<<<!!!!!!!<<<<<<<< reading from file

I don't understand what you're trying to do when you're reading from
the file. For a start:

     Pkt_Num+1 * DataRate

is the same as:

     Pkt_Num + (1 * DataRate)

or:

     Pkt_Num + DataRate

and that's how many bytes you're reading.

>             f.close()
>             self.usr_dict[client][PKT] = Pkt_Num
>             return EncodeAES(CIPHER,
>                              str((Pkt_Num, data)))
> 
>         elif Pkt_Num == Old_Pkt_Num:
>             if Pkt_Num * DataRate >=
> os.path.getsize("files/"+self.usr_dict[client][FILENAME]):
>                 return EncodeAES(CIPHER,
>                              str((-2, "File Transfer Complete")))
>             try:
>                 f = open("files/"+self.usr_dict[client][FILENAME],
> "rb")
>             except IOError:
>                return EncodeAES(CIPHER,
>                              str((-3, "File Could Not be opened")))
>             data = f.read((Pkt_Num+1 * DataRate))

Here you're reading:

     Pkt_Num + DataRate

bytes again,

>             data = None

discarding what you've just read,

>             data = binascii.b2a_base64(f.read(DataRate))
> #<<<<<<<<!!!!!!!<<<<<<< reading from file

and then reading:

     DataRate

more bytes.

I think what you meant to do is .seek to the position in the file and
then read some bytes:

     f.seek(Pkt_Num * DataRate)
     data = f.read(DataRate)

ie, send the contents of the file in chunks which are DataRate bytes
long (the last chunk will be shorter if the file size isn't a multiple
of DataRate bytes).

>             f.close()
>             self.usr_dict[client][PKT] = Pkt_Num +1
> 
>             return EncodeAES(CIPHER,
>                             str((Pkt_Num+1, data)))
> 
>       else:
> 
>             return EncodeAES(CIPHER,
>                              str((-3, "Incorrect Packet Requested")))
> 
> 
> 
> Thank you all for the help,  I know there are better ways and transfer
> protocol modules to but I'd like to do this without them.
> 
I'm not surprised that the transfer is failing! :-)



More information about the Python-list mailing list