]> code.delx.au - pymsnt/commitdiff
msnp2p file not needed any longer
authorjamesbunton <jamesbunton@55fbd22a-6204-0410-b2f0-b6c764c7e90a>
Tue, 6 Dec 2005 12:52:02 +0000 (12:52 +0000)
committerjamesbunton <jamesbunton@55fbd22a-6204-0410-b2f0-b6c764c7e90a>
Tue, 6 Dec 2005 12:52:02 +0000 (12:52 +0000)
git-svn-id: http://delx.cjb.net/svn/pymsnt/trunk@40 55fbd22a-6204-0410-b2f0-b6c764c7e90a

committer: jamesbunton <jamesbunton@55fbd22a-6204-0410-b2f0-b6c764c7e90a>

src/tlib/msn/msnp2p.py [deleted file]

diff --git a/src/tlib/msn/msnp2p.py b/src/tlib/msn/msnp2p.py
deleted file mode 100644 (file)
index 04874e8..0000000
+++ /dev/null
@@ -1,937 +0,0 @@
-# Copyright 2005 James Bunton <james@delx.cjb.net>
-# Licensed for distribution under the GPL version 2, check COPYING for details
-
-import struct
-import random
-import sha
-import base64
-import sys
-
-from tlib import xmlw
-
-MSNP2P_DEBUG = False
-
-def b64enc(s):
-       return base64.encodestring(s).replace("\n", "")
-
-def random_guid():
-       format = "{%4X%4X-%4X-%4X-%4X-%4X%4X%4X}"
-       data = []
-       for x in xrange(8):
-               data.append(random.random() * 0xAAFF + 0x1111)
-       data = tuple(data)
-
-       return format % data
-
-
-class MSNOBJ:
-       def __init__(self, s=""):
-               self.creator = ""
-               self.imageData = ""
-               self.size = 0
-               self.type = 0
-               self.location = ""
-               self.friendly = ""
-               self.sha1d = ""
-               self.text = ""
-               if s:
-                       self.parse(s)
-       
-       def setData(self, creator, imageData):
-               self.creator = creator
-               self.imageData = imageData
-               self.size = len(imageData)
-               self.type = 3
-               self.location = "TMP" + str(random.randint(1000,9999))
-               self.friendly = "AAA="
-               self.sha1d = b64enc(sha.sha(imageData).digest())
-               self.makeText()
-       
-       def setNull(self):
-               self.creator = ""
-               self.imageData = ""
-               self.size = 0
-               self.type = 0
-               self.location = ""
-               self.friendly = ""
-               self.sha1d = ""
-               self.text = ""
-       
-       def makeText(self):
-               h = []
-               h.append("Creator")
-               h.append(self.creator)
-               h.append("Size")
-               h.append(str(self.size))
-               h.append("Type")
-               h.append(str(self.type))
-               h.append("Location")
-               h.append(self.location)
-               h.append("Friendly")
-               h.append(self.friendly)
-               h.append("SHA1D")
-               h.append(self.sha1d)
-               sha1c = b64enc(sha.sha("".join(h)).digest())
-               self.text = '<msnobj Creator="%s" Size="%s" Type="%s" Location="%s" Friendly="%s" SHA1D="%s" SHA1C="%s"/>' % (self.creator, str(self.size), str(self.type), self.location, self.friendly, self.sha1d, sha1c)
-       
-       def parse(self, s):
-               e = xmlw.parseText(s, True)
-               self.creator = e.getAttribute("Creator")
-               self.size = int(e.getAttribute("Size"))
-               self.type = int(e.getAttribute("Type"))
-               self.location = e.getAttribute("Location")
-               self.friendly = e.getAttribute("Friendly")
-               self.sha1d = e.getAttribute("SHA1D")
-               self.text = s
-
-
-
-class BinaryFields:
-       ACK = 0x02
-       WAIT = 0x04
-       ERR = 0x08
-       DATA = 0x20
-       BYEGOT = 0x40
-       BYESENT = 0x80
-       DATAFT = 0x1000030
-
-       def __init__(self, fields=None, packet=None):
-               if fields:
-                       self.fields = fields
-               else:
-                       self.fields = [0] * 10
-                       if packet:
-                               self.unpackFields(packet)
-       
-       def __getitem__(self, key):
-               return self.fields[key]
-       
-       def __setitem__(self, key, value):
-               self.fields[key] = value
-       
-       def unpackFields(self, packet):
-               self.fields = struct.unpack("<LLQQLLLLQ", packet[0:48])
-               self.fields += struct.unpack(">L", packet[len(packet)-4:])
-               if MSNP2P_DEBUG:
-                       print "Unpacked fields:",
-                       for i in self.fields:
-                               print hex(i),
-                       print
-       
-       def packHeaders(self):
-               f = tuple(self.fields)
-               if MSNP2P_DEBUG:
-                       print "Packed fields:",
-                       for i in self.fields:
-                               print hex(i),
-                       print
-               return struct.pack("<LLQQLLLLQ", f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8])
-       
-       def packFooter(self):
-               return struct.pack(">L", self.fields[9])
-
-
-class MSNSLPMessage:
-       def __init__(self, packet=None):
-               self.method = ""
-               self.status = ""
-               self.to = ""
-               self.fro = ""
-               self.cseq = 0
-               self.sessionGuid = ""
-               self.sessionID = None
-               self.euf_guid = ""
-               self.data = "\r\n" + chr(0)
-               if packet:
-                       self.parse(packet)
-
-       def create(self, method=None, status=None, to=None, fro=None, cseq=0, sessionGuid=None, data=None):
-               self.method = method
-               self.status = status
-               self.to = to
-               self.fro = fro
-               self.cseq = cseq
-               self.sessionGuid = sessionGuid
-               if data: self.data = data
-       
-       def setData(self, sessionID=None, appID=None, guid=None, context=None):
-               s = []
-               if guid:          s.append("EUF-GUID: %s\r\n" % guid)
-               if sessionID: s.append("SessionID: %s\r\n" % sessionID)
-               if appID:         s.append("AppID: %s\r\n" % appID)
-               if context:   s.append("Context: %s\r\n\r\n" % context)
-               s.append(chr(0))
-               
-               self.data = "".join(s)
-       
-       def parse(self, s):
-               s = s[48:len(s)-4:]
-               if s.find("MSNSLP/1.0") < 0: return
-
-               lines = s.split("\r\n")
-               
-               # Get the MSNSLP method or status
-               msnslp = lines[0].split(" ")
-               if MSNP2P_DEBUG: print "Parsing MSNSLPMessage", s, len(s)
-               if(msnslp[0] in ("INVITE", "BYE")):
-                       self.method = msnslp[0].strip()
-               else:
-                       self.status = msnslp[1].strip()
-
-               lines.remove(lines[0])
-               
-               for line in lines:
-                       line = line.split(":")
-                       if(len(line) > 1):
-                               if(len(line) > 2 and line[0] == "To"):
-                                       self.to = line[2][:line[2].find('>')]
-                               elif(len(line) > 2 and line[0] == "From"):
-                                       self.fro = line[2][:line[2].find('>')]
-                               elif(line[0] == "Call-ID"):
-                                       self.sessionGuid = line[1].strip()
-                               elif(line[0] == "CSeq"):
-                                       self.cseq = int(line[1].strip())
-                               elif(line[0] == "SessionID"):
-                                       self.sessionID = int(line[1].strip())
-                               elif(line[0] == "EUF-GUID"):
-                                       self.euf_guid = line[1].strip()
-
-       def __str__(self):
-               s = []
-               if(self.method):
-                       s.append("%s MSNMSGR:%s MSNSLP/1.0\r\n" % (self.method, self.to))
-               else:
-                       s.append("MSNSLP/1.0 %s\r\n" % self.status)
-               s.append("To: <msnmsgr:%s>\r\n" % self.to)
-               s.append("From: <msnmsgr:%s>\r\n" % self.fro)
-               s.append("Via: MSNSLP/1.0/TLP ;branch=%s\r\n" % random_guid())
-               s.append("CSeq: %s \r\n" % str(self.cseq))
-               s.append("Call-ID: %s\r\n" % self.sessionGuid)
-               s.append("Max-Forwards: 0\r\n")
-               if(self.method == "BYE"):
-                       s.append("Content-Type: application/x-msnmsgr-sessionclosebody\r\n")
-               else:
-                       s.append("Content-Type: application/x-msnmsgr-sessionreqbody\r\n")
-               s.append("Content-Length: %s\r\n\r\n" % len(self.data))
-               s.append(self.data)
-               return "".join(s)
-
-
-class BaseID:
-       def __init__(self, baseID=None, sender=False):
-               if(baseID):
-                       self.baseID = baseID
-               else:
-                       self.baseID = random.randint(4, 2**30)
-               self.sender = sender
-               if(self.sender):
-                       self.pos = -1
-               else:
-                       self.pos = 0
-       
-       def get(self):
-               if self.pos == -1:
-                       return self.baseID
-               else:
-                       return self.baseID + self.pos - 3
-       
-       def next(self):
-               self.pos += 1
-               if self.pos == 3 and self.sender:
-                       self.pos += 1
-               return self.get()
-
-class MSNP2P_Avatar:
-       TRANSFER_COUNT = 0
-       ERROR_COUNT = 0
-
-       EUF_GUID = "{A4268EEC-FEC5-49E5-95C3-F126696BDBF6}"
-       ERROR = -1
-
-       def __init__(self):
-               raise "NotImplemented"
-
-       def getImage(self):
-               return False
-       
-       def isFinished(self):
-               if self.state >= self.FINISHED:
-                       MSNP2P_Avatar.TRANSFER_COUNT += 1
-                       return True
-               elif self.state < 0:
-                       MSNP2P_Avatar.ERROR_COUNT += 1
-                       return True
-               else:
-                       return False
-       
-       def setError(self, text):
-               if MSNP2P_DEBUG:
-                       print "ERROR in avatar transfer: ", self, text, "in state:", self.state
-               self.state = self.ERROR
-       
-       def warn(self, text):
-               if MSNP2P_DEBUG:
-                       print "Warning in avatar transfer: ", self, text, "in state:", self.state
-       
-
-class MSNP2P_Avatar_Send(MSNP2P_Avatar):
-       # Avatar_Send states
-       WAIT_REQUEST            = 0
-       SEND_REQACK             = 1
-       SEND_200OK              = 2
-       WAIT_200OK_ACK          = 3
-       SEND_DATAPREP           = 4
-       WAIT_DATAPREP_ACK       = 5
-       SEND_DATA               = 6
-       WAIT_BYE                = 7
-       SEND_BYE_ACK            = 8
-       FINISHED                = 9
-
-       def __init__(self, to, fro, msnobj):
-               self.to = to
-               self.fro = fro
-               self.msnobj = msnobj
-               self.fileOffset = 0 # The amount already sent
-               self.sessionID = 0
-               self.baseID = BaseID(sender=True)
-               self.state = self.WAIT_REQUEST
-               self.lastFields = BinaryFields()
-               self.lastSentFields = BinaryFields()
-       
-       def processPacket(self, packet):
-               if MSNP2P_DEBUG:
-                       print "processPacket", self.to, self.fro, self.state
-               if(self.state == self.WAIT_REQUEST):
-                       message = MSNSLPMessage()
-                       message.parse(packet)
-                       if(message.method != "INVITE"):
-                               self.setError("method" + message.method)
-                               return
-                       if(message.cseq != 0):
-                               self.setError("cseq" + str(message.cseq))
-                               return
-                       if(message.euf_guid != self.EUF_GUID):
-                               self.setError("guid" + message.euf_guid)
-                               return
-
-                       binaryFields = BinaryFields()
-                       binaryFields.unpackFields(packet)
-               
-                       self.sguid = message.sessionGuid
-                       self.sessionID = message.sessionID
-
-                       self.lastFields = binaryFields
-                       self.state = self.SEND_REQACK
-                       return
-
-               if(self.state == self.WAIT_200OK_ACK):
-                       binaryFields = BinaryFields()
-                       binaryFields.unpackFields(packet)
-
-                       if(binaryFields[6] != self.lastSentFields[1]):
-                               self.warn("field6," + str(binaryFields[6]) + "," + str(self.lastSentFields[1]))
-                               return
-                       if(binaryFields[3] != self.lastSentFields[3]):
-                               self.setError("field3," + str(binaryFields[3]) + "," + str(self.lastSentFields[3]))
-                               return
-                       if(binaryFields[8] != self.lastSentFields[3]):
-                               self.setError("field8," + str(binaryFields[8]) + "," + str(self.lastSentFields[3]))
-                               return
-                       if(binaryFields[5] != BinaryFields.ACK):
-                               self.setError("field5," + str(binaryFields[5]))
-                               return
-
-                       self.lastFields = binaryFields
-                       self.state = self.SEND_DATAPREP
-                       return
-
-               if(self.state == self.WAIT_DATAPREP_ACK):
-                       binaryFields = BinaryFields()
-                       binaryFields.unpackFields(packet)
-
-                       if(binaryFields[0] != self.sessionID):
-                               self.warn("field0," + str(binaryFields[0]) + "," + str(self.sessionID))
-                               return
-                       if(binaryFields[3] != self.lastSentFields[3]):
-                               self.setError("field3," + str(binaryFields[3]) + "," + str(self.lastSentFields[3]))
-                               return
-                       if(binaryFields[8] != self.lastSentFields[3]):
-                               self.setError("field8," + str(binaryFields[8]) + "," + str(self.lastSentFields[3]))
-                               return
-                       if(binaryFields[5] != BinaryFields.ACK):
-                               self.setError("field5," + str(binaryFields[5]))
-                               return
-                       if(binaryFields[6] != self.lastSentFields[1]):
-                               self.setError("field6," + str(binaryFields[6]) + "," + str(self.lastSentFields[1]))
-                               return
-                       if(binaryFields[7] != self.lastSentFields[6]):
-                               self.setError("field7," + str(binaryFields[7]) + "," + str(self.lastSentFields[6]))
-                               return
-
-                       self.lastFields = binaryFields
-                       self.baseID.next()
-                       self.state = self.SEND_DATA
-                       return
-
-               if(self.state == self.WAIT_BYE):
-                       binaryFields = BinaryFields()
-                       binaryFields.unpackFields(packet)
-                       
-                       # BYE message
-                       message = MSNSLPMessage()
-                       message.parse(packet)
-                       if(message.sessionGuid != self.sguid):
-                               self.warn("sessionGuid" + message.sessionGuid)
-                               return
-                       if(message.method != "BYE"):
-                               self.setError("method " + message.method)
-                               return
-                       if(message.cseq != 0):
-                               self.setError("cseq" + str(message.cseq))
-                               return
-       
-                       self.lastFields = binaryFields
-                       self.state = self.SEND_BYE_ACK # I don't really care about receiving the data ack
-                       return
-       
-
-       def getNextPacket(self):
-               if MSNP2P_DEBUG:
-                       print "getNextPacket (Avatar_Send)", self.to, self.fro, self.state
-               if(self.state == self.SEND_REQACK):
-                       binaryFields = BinaryFields()
-                       binaryFields[1] = self.baseID.get()
-                       binaryFields[3] = self.lastFields[3]
-                       binaryFields[5] = BinaryFields.ACK
-                       binaryFields[6] = self.lastFields[1]
-                       binaryFields[7] = self.lastFields[6]
-                       binaryFields[8] = self.lastFields[3]
-
-                       packet = binaryFields.packHeaders() + binaryFields.packFooter()
-
-                       self.state = self.SEND_200OK
-                       self.lastSentFields = binaryFields
-                       return packet
-
-               if(self.state == self.SEND_200OK):
-                       msg = MSNSLPMessage()
-                       msg.create(status="200 OK", to=self.to, fro=self.fro, cseq=1, sessionGuid=self.sguid)
-                       msg.setData(sessionID=self.sessionID)
-                       msgStr = str(msg)
-
-                       binaryFields = BinaryFields()
-                       binaryFields[1] = self.baseID.next()
-                       binaryFields[3] = len(msgStr)
-                       binaryFields[4] = len(msgStr)
-                       binaryFields[6] = random.randint(0, 2**30)
-
-                       packet = binaryFields.packHeaders() + msgStr + binaryFields.packFooter()
-                       
-                       self.state = self.WAIT_200OK_ACK
-                       self.lastSentFields = binaryFields
-                       return packet
-
-               if(self.state == self.SEND_DATAPREP):
-                       binaryFields = BinaryFields()
-                       binaryFields[0] = self.sessionID
-                       binaryFields[1] = self.baseID.next()
-                       binaryFields[3] = 4
-                       binaryFields[4] = 4
-                       binaryFields[6] = random.randint(0, 2**30)
-                       binaryFields[9] = 1
-
-                       packet = binaryFields.packHeaders() + chr(0) * 4 + binaryFields.packFooter()
-
-                       self.state = self.WAIT_DATAPREP_ACK
-                       self.lastSentFields = binaryFields
-                       return packet
-
-               if(self.state == self.SEND_DATA):
-                       binaryFields = BinaryFields()
-                       binaryFields[0] = self.sessionID
-                       binaryFields[1] = self.baseID.get()
-                       binaryFields[2] = self.fileOffset
-                       binaryFields[3] = len(self.msnobj.imageData)
-                       binaryFields[5] = BinaryFields.DATA
-                       binaryFields[6] = random.randint(0, 2**30)
-                       binaryFields[9] = 1
-
-                       # Work out what part of the file we're sending
-                       length = len(self.msnobj.imageData) - self.fileOffset
-                       if(length > 1202):
-                               # Max amount per message is 1202
-                               length = 1202
-                       else:
-                               # Last packet!
-                               self.state = self.WAIT_BYE
-                               self.lastSentFields = binaryFields
-                       binaryFields[4] = length
-                       chunk = self.msnobj.imageData[self.fileOffset : self.fileOffset + length]
-                       self.fileOffset += length
-
-                       packet = binaryFields.packHeaders() + chunk + binaryFields.packFooter()
-                       return packet
-
-               if(self.state == self.SEND_BYE_ACK):
-                       binaryFields = BinaryFields()
-                       binaryFields[1] = self.baseID.next()
-                       binaryFields[3] = self.lastFields[3]
-                       binaryFields[5] = BinaryFields.BYEGOT
-                       binaryFields[6] = self.lastFields[1]
-                       binaryFields[7] = self.lastFields[6]
-                       binaryFields[8] = self.lastFields[3]
-
-                       packet = binaryFields.packHeaders() + binaryFields.packFooter()
-
-                       self.state = self.FINISHED
-                       self.lastSentFields = binaryFields
-                       return packet
-
-
-
-
-class MSNP2P_Avatar_Receive(MSNP2P_Avatar):
-       # Avatar_Receive states
-       SEND_REQUEST            = 0     # Send the request
-       WAIT_REQACK_200OK       = 1     # Wait for REQACK and 200OK message
-       # Skip one value so we know both of the above have been done
-       SEND_200OK_ACK          = 3     # Received both of the above
-       WAIT_DATAPREP           = 4     # Wait for DATAPREP
-       SEND_DATAPREP_ACK       = 5     # Send ACK to above
-       WAIT_DATA               = 6     # Wait for all data messages and send DATA_ACK
-       SEND_DATA_ACK           = 7     # Then send BYE
-       SEND_BYE                = 8
-       FINISHED                = 9
-       
-       def __init__(self, to, fro, msnobj):
-               self.to = to
-               self.fro = fro
-               self.msnobj = msnobj
-               self.sessionID = random.randint(0, 2**30)
-               self.sguid = random_guid()
-               self.baseID = BaseID()
-               self.state = self.SEND_REQUEST
-               self.lastFields = BinaryFields()
-               self.lastSentFields = BinaryFields()
-               self.fileData = None
-       
-       def getImage(self):
-               if(self.state >= self.SEND_BYE):
-                       return self.fileData.data
-       
-       def processPacket(self, packet):
-               if MSNP2P_DEBUG:
-                       print "processPacket", self.to, self.fro, self.state
-               if(self.state == self.WAIT_REQACK_200OK or self.state == self.WAIT_REQACK_200OK + 1):
-                       binaryFields = BinaryFields()
-                       binaryFields.unpackFields(packet)
-                       
-                       if(binaryFields[5] == BinaryFields.ACK):
-                               # REQUESTACK!
-                               if(binaryFields[6] != self.lastSentFields[1]):
-                                       self.warn("field6," + str(binaryFields[6]) + "," + str(self.lastSentFields[1]))
-                                       return
-                               if(binaryFields[3] != self.lastSentFields[3]):
-                                       self.setError("field3," + str(binaryFields[3]) + "," + str(self.lastSentFields[3]))
-                                       return
-                               if(binaryFields[7] != self.lastSentFields[6]):
-                                       self.setError("field7," + str(binaryFields[7]) + "," + str(self.lastSentFields[6]))
-                                       return
-                               if(binaryFields[8] != self.lastSentFields[3]):
-                                       self.setError("field8," + str(binaryFields[8]) + "," + str(self.lastSentFields[3]))
-                                       return
-
-                               self.state += 1
-                               return
-
-                       elif(binaryFields[5] == 0):
-                               # 200OK
-                               message = MSNSLPMessage()
-                               message.parse(packet)
-                               if(message.sessionID != self.sessionID):
-                                       self.warn("sessionID" + str(message.sessionID) + "," + str(self.sessionID))
-                                       return
-                               if(message.status != "200"):
-                                       self.setError("status" + message.status)
-                                       return
-                               if(message.cseq != 1):
-                                       self.setError("cseq" + str(message.cseq))
-                                       return
-                               if(message.sessionGuid != self.sguid):
-                                       self.setError("sessionGuid" + message.sessionGuid + "," + self.sguid)
-                                       return
-
-                               self.lastFields = binaryFields
-                               self.state += 1
-                               return
-
-                       else:
-                               self.warn("Packet discarded," + str(binaryFields[5]))
-               
-               if(self.state == self.WAIT_DATAPREP):
-                       binaryFields = BinaryFields()
-                       binaryFields.unpackFields(packet)
-
-                       if(binaryFields[0] != self.sessionID):
-                               self.warn("field0," + str(binaryFields[0]) + "," + str(self.sessionID))
-                               return
-                       if(binaryFields[3] != 4):
-                               self.setError("field3," + str(binaryFields[3]))
-                               return
-                       if(binaryFields[4] != 4):
-                               self.setError("field4," + str(binaryFields[4]))
-                               return
-                       if(binaryFields[9] != 1):
-                               self.warn("field9," + str(binaryFields[9]))
-                       #       return
-
-                       self.lastFields = binaryFields
-                       self.state = self.SEND_DATAPREP_ACK
-                       return
-
-               if(self.state == self.WAIT_DATA):
-                       binaryFields = BinaryFields()
-                       binaryFields.unpackFields(packet)
-                       if(binaryFields[0] != self.sessionID):
-                               self.warn("field0," + str(binaryFields[0]) + "," + str(self.sessionID))
-                               return
-                       if(binaryFields[5] != BinaryFields.DATA):
-                               self.setError("field5," + str(binaryFields[5]))
-                               return
-                       if(binaryFields[9] != 1):
-                               self.warn("field9," + str(binaryFields[9]))
-                       #       return
-                       offset = binaryFields[2]
-                       total = binaryFields[3]
-                       length = binaryFields[4]
-                       if(not self.fileData):
-                               self.fileData = FileData(binaryFields[3])
-
-                       data = packet[48:len(packet)-4]
-                       self.fileData.put(offset, packet[48:len(packet)-4])
-
-                       if self.fileData.finished():
-                               self.state = self.SEND_DATA_ACK
-
-                       self.lastFields = binaryFields
-
-                       return
-
-       def getNextPacket(self):
-               if MSNP2P_DEBUG:
-                       print "getNextPacket (Avatar_Receive)", self.to, self.fro, self.state
-               if(self.state == self.SEND_REQUEST):
-                       msg = MSNSLPMessage()
-                       msg.create(method="INVITE", to=self.to, fro=self.fro, cseq=0, sessionGuid=self.sguid)
-                       msg.setData(sessionID=self.sessionID, appID="1", guid=self.EUF_GUID, context=b64enc(self.msnobj.text + chr(0)))
-                       msgStr = str(msg)
-
-                       binaryFields = BinaryFields()
-                       binaryFields[1] = self.baseID.get()
-                       binaryFields[6] = random.randint(0, 2**30)
-                       binaryFields[3] = len(msgStr)
-                       binaryFields[4] = len(msgStr)
-
-                       packet = binaryFields.packHeaders() + msgStr + binaryFields.packFooter()
-                       
-                       self.state = self.WAIT_REQACK_200OK
-                       self.lastSentFields = binaryFields
-                       return packet
-               
-               if(self.state == self.SEND_200OK_ACK):
-                       binaryFields = BinaryFields()
-                       binaryFields[1] = self.baseID.next()
-                       binaryFields[3] = self.lastFields[3]
-                       binaryFields[8] = self.lastFields[3]
-                       binaryFields[5] = BinaryFields.ACK
-                       binaryFields[6] = self.lastFields[1]
-                       binaryFields[7] = self.lastFields[6]
-
-                       packet = binaryFields.packHeaders() + binaryFields.packFooter()
-
-                       self.state = self.WAIT_DATAPREP
-                       self.lastSentFields = binaryFields
-                       return packet
-
-               if(self.state == self.SEND_DATAPREP_ACK):
-                       binaryFields = BinaryFields()
-                       binaryFields[0] = self.sessionID
-                       binaryFields[1] = self.baseID.next()
-                       binaryFields[3] = 4
-                       binaryFields[8] = 4
-                       binaryFields[5] = BinaryFields.ACK
-                       binaryFields[6] = self.lastFields[1]
-                       binaryFields[7] = self.lastFields[6]
-
-                       packet = binaryFields.packHeaders() + binaryFields.packFooter()
-
-                       self.state = self.WAIT_DATA
-                       self.lastSentFields = binaryFields
-                       return packet
-
-               if(self.state == self.SEND_DATA_ACK):
-                       # FIXME Check hash!
-                       binaryFields = BinaryFields()
-                       binaryFields[0] = self.sessionID
-                       binaryFields[1] = self.baseID.next()
-                       binaryFields[3] = self.lastFields[3]
-                       binaryFields[8] = self.lastFields[3]
-                       binaryFields[5] = BinaryFields.ACK
-                       binaryFields[6] = self.lastFields[1]
-                       binaryFields[7] = self.lastFields[6]
-
-                       packet = binaryFields.packHeaders() + binaryFields.packFooter()
-
-                       self.state = self.SEND_BYE
-                       self.lastSentFields = binaryFields
-                       return packet
-
-               if(self.state == self.SEND_BYE):
-                       msg = MSNSLPMessage()
-                       msg.create(method="BYE", to=self.to, fro=self.fro, cseq=0, sessionGuid=self.sguid)
-                       msgStr = str(msg)
-
-                       binaryFields = BinaryFields()
-                       binaryFields[1] = self.baseID.next()
-                       binaryFields[3] = len(msgStr)
-                       binaryFields[4] = len(msgStr)
-                       binaryFields[5] = BinaryFields.BYESENT
-                       binaryFields[6] = random.randint(0, 2**30)
-
-                       packet = binaryFields.packHeaders() + msgStr + binaryFields.packFooter()
-                       
-                       self.state = self.FINISHED
-                       self.lastSentFields = binaryFields
-                       return packet
-
-
-
-class SLPLink:
-       def __init__(self, remoteUser, switchboard, sessionID, sessionGuid):
-               if not sessionID:
-                       sessionID = random.randint(1000, sys.maxint)
-               if not sessionGuid:
-                       sessionGuid = random_guid()
-               self.remoteUser = remoteUser
-               self.switchboard = switchboard
-               self.sessionID = sessionID
-               self.sessionGuid = sessionGuid
-
-       def setError(self, text):
-               if MSNP2P_DEBUG:
-                       print "ERROR in avatar transfer: ", self, text, "in state:", self.state
-               self.state = self.ERROR
-       
-       def warn(self, text):
-               if MSNP2P_DEBUG:
-                       print "Warning in avatar transfer: ", self, text, "in state:", self.state
-       
-
-class SLPLink_Send(SLPLink):
-       def __init__(self, remoteUser, switchboard, length, sessionID=None, sessionGuid=None):
-               SLPLink.__init__(self, remoteUser, switchboard, sessionID, sessionGuid)
-               self.handlePacket = None
-               self.offset = 0
-               self.length = length
-               self.data = ""
-               # Send dataprep
-               self.send_dataprep()
-       
-       def send_dataprep(self):
-               binaryFields = BinaryFields()
-               binaryFields[0] = self.sessionID
-               binaryFields[1] = self.baseID.next()
-               binaryFields[3] = 4
-               binaryFields[4] = 4
-               binaryFields[6] = random.randint(0, sys.maxint)
-               binaryFields[9] = 1
-
-               self.switchboard._sendP2PMessage(binaryFields, chr(0) * 4)
-
-       def write(self, data):
-               i = 0
-               length = len(data)
-               while i < length:
-                       if i + 1202 < length:
-                               self._writeChunk(data[i:i+1202])
-                               i += 1202
-                       else:
-                               self.data += data
-                               if len(self.data) >= 1202:
-                                       data = self.data
-                                       self.data = ""
-                                       self.write(data)
-                               return
-
-       def _writeChunk(self, chunk):
-               binaryFields = BinaryFields()
-               binaryFields[0] = self.sessionID
-               binaryFields[1] = self.baseID.get()
-               binaryFields[2] = self.fileOffset
-               binaryFields[3] = len(chunk)
-               binaryFields[4] = self.length
-               binaryFields[5] = BinaryFields.DATA
-               binaryFields[6] = random.randint(0, 2**30)
-               binaryFields[9] = 1
-
-               self.offset += len(chunk)
-               self.switchboard._sendP2PMessage(binaryFields, chunk)
-       
-       def finish(self):
-               self._writeChunk(self.data)
-               # FIXME Now tell the switchboard
-       
-       def error(self):
-               pass
-               # Same as above?
-
-
-class SLPLink_Receive(SLPLink):
-       def __init__(self, remoteUser, switchboard, consumer, sessionID=None, sessionGuid=None):
-               SLPLink.__init__(self, remoteUser, switchboard, sessionID, sessionGuid)
-               self.consumer = consumer
-               self.pos = 0
-
-               self.handlePacket = wait_dataprep
-       
-       def wait_dataprep(self, packet):
-               binaryFields = BinaryFields()
-               binaryFields.unpackFields(packet)
-
-               if binaryFields[0] != self.sessionID:
-                       self.warn("field0," + str(binaryFields[0]) + "," + str(self.sessionID))
-                       return
-               if binaryFields[3] != 4:
-                       self.setError("field3," + str(binaryFields[3]))
-                       return
-               if binaryFields[4] != 4:
-                       self.setError("field4," + str(binaryFields[4]))
-                       return
-               if binaryFields[9] != 1:
-                       self.warn("field9," + str(binaryFields[9]))
-               #       return
-
-               self.switchboard._sendP2PACK(self, binaryFields)
-               self.handlePacket = self.wait_data
-
-       def wait_data(self, packet):
-               binaryFields = BinaryFields()
-               binaryFields.unpackFields(packet)
-               if binaryFields[0] != self.sessionID:
-                       self.warn("field0," + str(binaryFields[0]) + "," + str(self.sessionID))
-                       return
-               if binaryFields[5] != BinaryFields.DATA:
-                       self.setError("field5," + str(binaryFields[5]))
-                       return
-               if binaryFields[9] != 1):
-                       self.warn("field9," + str(binaryFields[9]))
-               #       return
-               offset = binaryFields[2]
-               total = binaryFields[3]
-               length = binaryFields[4]
-
-               data = packet[48:-4]
-               if offset != self.pos:
-                       self.setError("Received packet out of order")
-                       self.consumer.error()
-                       return
-               if len(data) != length:
-                       self.setError("Received bad length of slp")
-                       self.consumer.error()
-                       return
-               
-               self.pos += length
-
-               self.consumer.write(data)
-
-               if self.pos == total:
-                       self.switchboard._sendP2PACK(self, binaryFields)
-                       self.consumer.finish()
-                       self.switchboard.gotAvatarImage(self.remoteUser, self.fileData.data)
-                       self.handlePacket = None
-                       del self.switchboard.slpLinks[self.sessionID]
-
-
-
-
-class SwitchboardP2PMixin:
-       def handleP2PMessage(self, message, cTypes):
-               """ helper method for msnslp messages (file transfer & avatars) """
-               packet = message.message
-               binaryFields = msnp2p.BinaryFields(packet=packet)
-               if binaryFields[0] != 0:
-                       slpLink = self.slpLinks[binaryFields[0]]
-                       if slpLink.remoteUser == message.userHandle:
-                               slpLink.handlePacket(packet)
-               elif binaryFields[5] == BinaryFields.ACK or binaryFields[5] == BinaryFields.BYEGOT:
-                       pass # Ignore the ACKs
-               else:
-                       slpMessage = msnp2p.MSNSLPMessage(packet)
-                       slpLink = None
-                       if slpMessage.method == "INVITE":
-                               if slpMessage.euf_guid == MSN_MSNFTP_GUID:
-                                       slpLink = msnp2p.SLPLink_Receive(slpMessage.fro, slpMessage.sessionID, slpMessage.sessionGuid)
-                                       context = msnp2p.FileContext(slpMessage.context)
-                                       fileReceive = msnft.MSNP2P_Receive(context.filename, context.filesize, slpMessage.fro)
-                               elif slpMessage.euf_guid == MSN_AVATAR_GUID:
-                                       slpLink = msnp2p.SLPLink_Send(slpMessage.fro, slpMessage.sessionID, slpMessage.sessionGuid)
-                                       self._sendMSNSLPResponse(slpLink, "200 OK")
-                               if slpLink:
-                                       self.slpLinks[slpMessage.sessionID] = slpLink
-                       else:
-                               if slpMessage.status != "200":
-                                       for slpLink in self.slpLinks:
-                                               if slpLink.sessionGuid == slpMessage.sessionGuid:
-                                                       del self.slpLinks[slpLink.sessionID]
-                                       if slpMessage.method != "BYE":
-                                               # Must be an error. If its a file transfer we need to signal that it failed
-                                               slpLink.transferError()
-                               else:
-                                       slpLink = self.slpLinks[slpMessage.sessionID]
-                                       slpLink.transferReady()
-                       if slpLink:
-                               # Always need to ACK these packets if we can
-                               self._sendP2PACK(self, slpLink, binaryHeaders)
-
-
-       def _sendP2PACK(self, slpLink, ackHeaders):
-               binaryFields = msnp2p.BinaryFields()
-               binaryFields[1] = slpLink.nextBaseID()
-               binaryFields[3] = ackHeaders[3]
-               binaryFields[5] = BinaryFields.ACK
-               binaryFields[6] = ackHeaders[1]
-               binaryFields[7] = ackHeaders[6]
-               binaryFields[8] = ackHeaders[3]
-               self._sendP2PMessage(binaryFields, "")
-
-       def _sendMSNSLPCommand(self, command, slpLink, guid, context):
-               msg = msnp2p.MSNSLP_Message()
-               msg.create(method=command, to=slpLink.remoteUser, fro=self.userHandle, cseq=0, sessionGuid=slpLink.sessionGuid)
-               msg.setData(sessionID=slpLink.sessionID, appID="1", guid=guid, context=msnp2p.b64enc(context + chr(0)))
-               self._sendMSNSLPMessage(slpLink, msg)
-
-       def _sendMSNSLPResponse(self, slpLink, response):
-               msg = msnp2p.MSNSLPMessage()
-               msg.create(status=response, to=slpLink.remoteUser, fro=self.userHandle, cseq=1, sessionGuid=slpLink.sessionGuid)
-               msg.setData(sessionID=slpLink.sessionID)
-               self._sendMSNSLPMessage(slpLink, msg)
-
-       def _sendMSNSLPMessage(self, slpLink, msnSlpMessage):
-               msgStr = str(msg)
-               binaryFields = msnp2p.BinaryFields()
-               binaryFields[1] = slpLink.nextBaseID()
-               binaryFields[3] = len(msgStr)
-               binaryFields[4] = binaryFields[3]
-               binaryFields[6] = random.randint(0, sys.maxint)
-               self._sendP2PMessage(binaryFields, msgStr)
-
-       def _sendP2PMessage(self, binaryFields, msgStr):
-               packet = binaryFields.packHeaders() + msgStr + binaryFields.packFooter()
-
-               message = MSNMessage(message=packet)
-               message.setHeader("Content-Type", "application/x-msnmsgrp2p")
-               message.setHeader("P2P-Dest", handler.to)
-               message.ack = MSNMessage.MESSAGE_ACK_FAT
-               self.sendMessage(message)
-
-