+ def _writeChunk(self, chunk):
+ if MSNP2PDEBUG: log.msg("writing chunk")
+ binaryFields = BinaryFields()
+ binaryFields[0] = self.sessionID
+ if self.offset == 0:
+ binaryFields[1] = self.seqID.next()
+ else:
+ binaryFields[1] = self.seqID.get()
+ binaryFields[2] = self.offset
+ binaryFields[3] = self.filesize
+ binaryFields[4] = len(chunk)
+ binaryFields[5] = self.dataFlag
+ binaryFields[6] = random.randint(1000, sys.maxint)
+ binaryFields[9] = 1
+ self.offset += len(chunk)
+ self.sendP2PMessage(binaryFields, chunk)
+
+ def close(self):
+ if self.data:
+ self._writeChunk(self.data)
+ #self.killLink()
+
+ def error(self):
+ pass
+ # FIXME, should send 601 or something
+
+class SLPLink_FileSend(SLPLink_Send):
+ def __init__(self, remoteUser, switchboard, filename, filesize):
+ SLPLink_Send.__init__(self, remoteUser=remoteUser, switchboard=switchboard, filesize=filesize)
+ self.dataFlag = BinaryFields.DATAFT
+ # Send invite & wait for 200OK before sending dataprep
+ context = FileContext()
+ context.filename = filename
+ context.filesize = filesize
+ data = {"EUF-GUID" : MSN_MSNFTP_GUID,\
+ "SessionID": self.sessionID,\
+ "AppID" : 2,\
+ "Context" : context.pack() }
+ self.sendSLPMessage("INVITE", "application/x-msnmsgr-sessionreqbody", data)
+ self.acceptDeferred = Deferred()
+
+ def handleSLPMessage(self, slpMessage):
+ if slpMessage.status == "200":
+ if slpMessage.ctype == "application/x-msnmsgr-sessionreqbody":
+ data = {"Bridges" : "TRUDPv1 TCPv1",\
+ "NetID" : "0",\
+ "Conn-Type" : "Firewall",\
+ "UPnPNat" : "false",\
+ "ICF" : "true",}
+ #"Hashed-Nonce": random_guid()}
+ self.sendSLPMessage("INVITE", "application/x-msnmsgr-transreqbody", data)
+ elif slpMessage.ctype == "application/x-msnmsgr-transrespbody":
+ self.acceptDeferred.callback((True,))
+ self.handlePacket = self.wait_data_ack
+ else:
+ if slpMessage.status == "603":
+ self.acceptDeferred.callback((False,))
+ if MSNP2PDEBUG: log.msg("SLPLink is over due to decline, error or BYE")
+ self.killLink()
+
+ def wait_data_ack(self, packet):
+ if MSNP2PDEBUG: log.msg("wait_data_ack")
+ binaryFields = BinaryFields()
+ binaryFields.unpackFields(packet)
+
+ if binaryFields[5] != BinaryFields.ACK:
+ self.warn("field5," + str(binaryFields[5]))
+ return
+
+ self.sendSLPMessage("BYE", "application/x-msnmsgr-sessionclosebody", {})
+ self.handlePacket = None
+
+ def close(self):
+ self.handlePacket = self.wait_data_ack
+ SLPLink_Send.close(self)
+
+
+class SLPLink_AvatarSend(SLPLink_Send):
+ def __init__(self, remoteUser, switchboard, filesize, sessionID=None, sessionGuid=None):
+ SLPLink_Send.__init__(self, remoteUser=remoteUser, switchboard=switchboard, filesize=filesize, sessionID=sessionID, sessionGuid=sessionGuid)
+ self.dataFlag = BinaryFields.DATA
+ self.sendSLPMessage("200", "application/x-msnmsgr-sessionreqbody", {"SessionID":self.sessionID})
+ self.send_dataprep()
+ self.handlePacket = lambda packet: None
+
+ def handleSLPMessage(self, slpMessage):
+ if MSNP2PDEBUG: log.msg("BYE or error")
+ self.killLink()
+
+ def close(self):
+ SLPLink_Send.close(self)
+ # Keep the link open to wait for a BYE
+
+class SLPLink_Receive(SLPLink):
+ def __init__(self, remoteUser, switchboard, consumer, context=None, sessionID=None, sessionGuid=None):
+ SLPLink.__init__(self, remoteUser, switchboard, sessionID, sessionGuid)
+ self.handlePacket = None
+ self.consumer = consumer
+ self.pos = 0
+
+ def wait_dataprep(self, packet):
+ if MSNP2PDEBUG: log.msg("wait_dataprep")
+ binaryFields = BinaryFields()
+ binaryFields.unpackFields(packet)
+
+ if binaryFields[3] != 4:
+ self.warn("field3," + str(binaryFields[3]))
+ return
+ if binaryFields[4] != 4:
+ self.warn("field4," + str(binaryFields[4]))
+ return
+ # Just ignore the footer
+ #if binaryFields[9] != 1:
+ # self.warn("field9," + str(binaryFields[9]))
+ # return
+
+ self.sendP2PACK(binaryFields)
+ self.handlePacket = self.wait_data
+
+ def wait_data(self, packet):
+ if MSNP2PDEBUG: log.msg("wait_data")
+ binaryFields = BinaryFields()
+ binaryFields.unpackFields(packet)
+
+ if binaryFields[5] != self.dataFlag:
+ self.warn("field5," + str(binaryFields[5]))
+ return
+ # Just ignore the footer
+ #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.warn("Received packet out of order")
+ self.consumer.error()
+ return
+ if len(data) != length:
+ self.warn("Received bad length of slp")
+ self.consumer.error()
+ return
+
+ self.pos += length
+
+ self.consumer.write(str(data))
+
+ if self.pos == total:
+ self.sendP2PACK(binaryFields)
+ self.consumer.close()
+ self.handlePacket = None
+ self.doFinished()
+
+ def doFinished(self):
+ raise NotImplementedError
+
+
+class SLPLink_FileReceive(SLPLink_Receive, FileReceive):
+ def __init__(self, remoteUser, switchboard, filename, filesize, sessionID, sessionGuid, branch):
+ SLPLink_Receive.__init__(self, remoteUser=remoteUser, switchboard=switchboard, consumer=self, sessionID=sessionID, sessionGuid=sessionGuid)
+ self.dataFlag = BinaryFields.DATAFT
+ self.initialBranch = branch
+ FileReceive.__init__(self, filename, filesize, remoteUser)
+
+ def reject(self):
+ # Send a 603 decline
+ if not self.switchboard: return
+ self.sendSLPMessage("603", "application/x-msnmsgr-sessionreqbody", {"SessionID":self.sessionID}, branch=self.initialBranch)
+ self.killLink()
+
+ def accept(self, consumer):
+ FileReceive.accept(self, consumer)
+ if not self.switchboard: return
+ self.sendSLPMessage("200", "application/x-msnmsgr-sessionreqbody", {"SessionID":self.sessionID}, branch=self.initialBranch)
+ self.handlePacket = self.wait_data # Moved here because sometimes the second INVITE seems to be skipped
+
+ def handleSLPMessage(self, slpMessage):
+ if slpMessage.method == "INVITE": # The second invite
+ data = {"Bridge" : "TCPv1",\
+ "Listening" : "false",\
+ "Hashed-Nonce": "{00000000-0000-0000-0000-000000000000}"}
+ self.sendSLPMessage("200", "application/x-msnmsgr-transrespbody", data, branch=slpMessage.branch)
+# self.handlePacket = self.wait_data # Moved up
+ else:
+ if MSNP2PDEBUG: log.msg("It's either a BYE or an error")
+ self.killLink()
+ # FIXME, do some error handling if it was an error
+
+ def doFinished(self):
+ #self.sendSLPMessage("BYE", "application/x-msnmsgr-sessionclosebody", {})
+ #self.killLink()
+ # Wait for BYE? #FIXME
+ pass
+
+class SLPLink_AvatarReceive(SLPLink_Receive):
+ def __init__(self, remoteUser, switchboard, consumer, context):
+ SLPLink_Receive.__init__(self, remoteUser=remoteUser, switchboard=switchboard, consumer=consumer, context=context)
+ self.dataFlag = BinaryFields.DATA
+ data = {"EUF-GUID" : MSN_AVATAR_GUID,\
+ "SessionID": self.sessionID,\
+ "AppID" : 1,\
+ "Context" : context}
+ self.sendSLPMessage("INVITE", "application/x-msnmsgr-sessionreqbody", data)
+ self.handlePacket = self.wait_dataprep
+
+ def handleSLPMessage(self, slpMessage):
+ if slpMessage.status == "200":
+ pass
+ #self.handlePacket = self.wait_dataprep # Moved upwards