]> code.delx.au - pymsnt/commitdiff
Fixed FT protocol.
authorjamesbunton <jamesbunton@55fbd22a-6204-0410-b2f0-b6c764c7e90a>
Sun, 11 Dec 2005 03:18:14 +0000 (03:18 +0000)
committerjamesbunton <jamesbunton@55fbd22a-6204-0410-b2f0-b6c764c7e90a>
Sun, 11 Dec 2005 03:18:14 +0000 (03:18 +0000)
git-svn-id: http://delx.cjb.net/svn/pymsnt/trunk@48 55fbd22a-6204-0410-b2f0-b6c764c7e90a

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

src/tlib/msn/msn.py

index db75850bd4ac0f0a9f095e2db6201b511c482d09..c951f77805a94b2094ad431ad0e95d735c2f2e91 100644 (file)
@@ -149,8 +149,6 @@ STATUS_BRB     = 'BRB'
 STATUS_PHONE   = 'PHN'
 STATUS_LUNCH   = 'LUN'
 
-CR = "\r"
-LF = "\n"
 PINGSPEED = 50.0
 
 DEBUGALL = False
@@ -754,7 +752,7 @@ class MSNEventBase(LineReceiver):
     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())
@@ -2065,15 +2063,25 @@ class SwitchboardClient(MSNEventBase):
         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
@@ -2090,10 +2098,6 @@ class SwitchboardClient(MSNEventBase):
                         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)
@@ -2277,7 +2281,7 @@ class SwitchboardClient(MSNEventBase):
         # 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
@@ -2531,13 +2535,16 @@ class MSNSLPMessage:
         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)
     
@@ -2549,7 +2556,7 @@ class MSNSLPMessage:
         
         # 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:
@@ -2572,6 +2579,8 @@ class MSNSLPMessage:
                     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])
 
@@ -2580,17 +2589,16 @@ class MSNSLPMessage:
         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)
@@ -2667,20 +2675,14 @@ class SLPLink:
         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)
@@ -2766,13 +2768,26 @@ class SLPLink_FileSend(SLPLink_Send):
         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,))
@@ -2782,13 +2797,13 @@ class SLPLink_FileSend(SLPLink_Send):
     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):
@@ -2869,17 +2884,23 @@ class SLPLink_FileReceive(SLPLink_Receive, FileReceive):
 
     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
@@ -2887,7 +2908,11 @@ class SLPLink_FileReceive(SLPLink_Receive, FileReceive):
 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":
@@ -2897,7 +2922,7 @@ class SLPLink_AvatarReceive(SLPLink_Receive):
             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 = {