STATUS_PHONE = 'PHN'
STATUS_LUNCH = 'LUN'
-CR = "\r"
-LF = "\n"
PINGSPEED = 50.0
DEBUGALL = False
def lineReceived(self, line):
if LINEDEBUG: log.msg("<< " + line)
if self.currentMessage:
- self.currentMessage.readPos += len(line+CR+LF)
+ self.currentMessage.readPos += len(line+"\r\n")
try:
header, value = line.split(':')
self.currentMessage.setHeader(header, unquote(value).lstrip())
if binaryFields[0] != 0:
slpLink = self.slpLinks[binaryFields[0]]
if slpLink.remoteUser == message.userHandle:
+ if MSNP2PDEBUG: print "Calling handlePacket", slpLink.__class__
slpLink.handlePacket(packet)
elif binaryFields[5] == BinaryFields.ACK or binaryFields[5] == BinaryFields.BYEGOT:
pass # Ignore the ACKs
else:
slpMessage = MSNSLPMessage(packet)
slpLink = None
- if slpMessage.method == "INVITE":
+ # Always try and give a slpMessage to a slpLink first.
+ # If none can be found, and it was INVITE, then create
+ # one to handle the session.
+ for slpLink in self.slpLinks.values():
+ if slpLink.sessionGuid == slpMessage.sessionGuid:
+ slpLink.handleSLPMessage(slpMessage)
+ break
+ else:
+ slpLink = None # Was not handled
+
+ if not slpLink and slpMessage.method == "INVITE":
if slpMessage.euf_guid == MSN_MSNFTP_GUID:
- #FIXME!
context = FileContext(slpMessage.context)
slpLink = SLPLink_FileReceive(remoteUser=slpMessage.fro, switchboard=self, filename=context.filename, filesize=context.filesize, sessionID=slpMessage.sessionID, sessionGuid=slpMessage.sessionGuid)
self.slpLinks[slpMessage.sessionID] = slpLink
pass
if slpLink:
self.slpLinks[slpMessage.sessionID] = slpLink
- else:
- for slpLink in self.slpLinks.values():
- if slpLink.sessionGuid == slpMessage.sessionGuid:
- slpLink.handleSLPMessage(slpMessage)
if slpLink:
# Always need to ACK these packets if we can
slpLink.sendP2PACK(binaryFields)
# send the rest of the headers
for header in [h for h in message.headers.items() if h[0].lower() not in ('mime-version','content-type')]:
self.sendLine("%s: %s" % (header[0], header[1]))
- self.transport.write(CR+LF)
+ self.transport.write("\r\n")
self.transport.write(message.message)
if MESSAGEDEBUG: log.msg(message.message)
return d
self.sessionGuid = sessionGuid
if data: self.data = data
- def setData(self, sessionID=None, appID=None, guid=None, context=None):
+ def setData(self, ctype, data):
+ self.ctype = ctype
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))
+ order = ["EUF-GUID", "SessionID", "AppID", "Context", "Bridge", "Listening","Bridges", "NetID", "Conn-Type", "UPnPNat", "ICF", "Hashed-Nonce"]
+ for key in order:
+ if key == "Context" and data.has_key(key):
+ s.append("Context: %s\r\n" % b64enc(data[key]))
+ elif data.has_key(key):
+ s.append("%s: %s\r\n" % (key, str(data[key])))
+ s.append("\r\n"+chr(0))
self.data = "".join(s)
# Get the MSNSLP method or status
msnslp = lines[0].split(" ")
- if MSNP2PDEBUG: print "Parsing MSNSLPMessage", s, len(s)
+ if MSNP2PDEBUG: print "Parsing MSNSLPMessage", len(s), s
if msnslp[0] in ("INVITE", "BYE"):
self.method = msnslp[0].strip()
else:
self.sessionID = int(line[1].strip())
elif line[0] == "EUF-GUID":
self.euf_guid = line[1].strip()
+ elif line[0] == "Content-Type":
+ self.ctype = line[1].strip()
elif line[0] == "Context":
self.context = base64.decodestring(line[1])
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)
+ if self.status == "200": status = "200 OK"
+ elif self.status == "603": status = "603 Decline"
+ s.append("MSNSLP/1.0 %s\r\n" % 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-Type: %s\r\n" % self.ctype)
s.append("Content-Length: %s\r\n\r\n" % len(self.data))
s.append(self.data)
return "".join(s)
binaryFields[8] = ackHeaders[3]
self.sendP2PMessage(binaryFields, "")
- def sendMSNSLPCommand(self, command, guid, context):
- msg = MSNSLPMessage()
- msg.create(method=command, to=self.remoteUser, fro=self.switchboard.userHandle, cseq=0, sessionGuid=self.sessionGuid)
- msg.setData(sessionID=self.sessionID, appID="1", guid=guid, context=b64enc(context + chr(0)))
- self.sendMSNSLPMessage(msg)
-
- def sendMSNSLPResponse(self, response):
+ def sendSLPMessage(self, cmd, ctype, data):
msg = MSNSLPMessage()
- msg.create(status=response, to=self.remoteUser, fro=self.switchboard.userHandle, cseq=1, sessionGuid=self.sessionGuid)
- msg.setData(sessionID=self.sessionID)
- self.sendMSNSLPMessage(msg)
-
- def sendMSNSLPMessage(self, msnSLPMessage):
- msgStr = str(msnSLPMessage)
+ if cmd.isdigit():
+ msg.create(status=cmd, to=self.remoteUser, fro=self.switchboard.userHandle, cseq=1, sessionGuid=self.sessionGuid)
+ else:
+ msg.create(method=cmd, to=self.remoteUser, fro=self.switchboard.userHandle, cseq=0, sessionGuid=self.sessionGuid)
+ msg.setData(ctype, data)
+ msgStr = str(msg)
binaryFields = BinaryFields()
binaryFields[1] = self.seqID.next()
binaryFields[3] = len(msgStr)
context = FileContext()
context.filename = filename
context.filesize = filesize
- self.sendMSNSLPCommand("INVITE", MSN_MSNFTP_GUID, context.pack())
+ 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":
- self.send_dataprep()
- self.acceptDeferred.callback((True,))
+ if slpMessage.ctype == "application/x-msnmsgr-sessionreqbody":
+ data = {"Bridges" : "TRUDPv1 TCPv1",\
+ "NetID" : "-123657987",\
+ "Conn-Type" : "Restrict-NAT",\
+ "UPnPNat" : "false",\
+ "ICF" : "false",\
+ "Hashed-Nonce": random_guid()}
+ self.sendSLPMessage("INVITE", "application/x-msnmsgr-transreqbody", data)
+ elif slpMessage.ctype == "application/x-msnmsgr-transrespbody":
+ self.send_dataprep()
+ self.acceptDeferred.callback((True,))
else:
if slpMessage.status == "603":
self.acceptDeferred.callback((False,))
def close(self):
SLPLink_Send.close(self)
# FIXME, check whether we should wait for a BYE or send one
- self.sendMSNSLPCommand("BYE", MSN_AVATAR_GUID, "\0")
+ self.sendSLPMessage("BYE", "application/x-msnmsgr-sessionclosebody", {})
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.sendMSNSLPResponse("200 OK")
+ self.sendSLPMessage("200", "application/x-msnmsgr-sessionreqbody", {"SessionID":self.sessionID})
self.send_dataprep()
def close(self):
def reject(self):
# Send a 603 decline
- self.sendMSNSLPResponse("603 Decline")
+ self.sendSLPMessage("603", "application/x-msnmsgr-sessionreqbody", {"SessionID":self.sessionID})
self.killLink()
def accept(self, consumer):
FileReceive.accept(self, consumer)
- self.sendMSNSLPResponse("200 OK")
- self.handlePacket = self.wait_dataprep
+ self.sendSLPMessage("200", "application/x-msnmsgr-sessionreqbody", {"SessionID":self.sessionID})
def handleSLPMessage(self, slpMessage):
- # FIXME, do some error handling if it was an error
- self.killLink() # It's either a BYE or an error
+ 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)
+ self.handlePacket = self.wait_dataprep
+ else:
+ self.killLink() # It's either a BYE or an error
+ # FIXME, do some error handling if it was an error
def doFinished(self):
pass # Link is kept around waiting for a BYE
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.sendMSNSLPCommand("INVITE", MSN_AVATAR_GUID, context)
+ data = {"EUF-GUID" : MSN_AVATAR_GUID,\
+ "SessionID": self.sessionID,\
+ "AppID" : 1,\
+ "Context" : context}
+ self.sendSLPMessage("INVITE", "application/x-msnmsgr-sessionreqbody", data)
def handleSLPMessage(self, slpMessage):
if slpMessage.status == "200":
self.killLink()
def doFinished(self):
- self.sendMSNSLPCommand("BYE", MSN_AVATAR_GUID, "\0")
+ self.sendSLPMessage("BYE", "application/x-msnmsgr-sessionclosebody", {})
# mapping of error codes to error messages
errorCodes = {