]> code.delx.au - pymsnt/commitdiff
Added auto-reconnect.
authorjamesbunton <jamesbunton@55fbd22a-6204-0410-b2f0-b6c764c7e90a>
Tue, 18 Apr 2006 16:00:25 +0000 (16:00 +0000)
committerjamesbunton <jamesbunton@55fbd22a-6204-0410-b2f0-b6c764c7e90a>
Tue, 18 Apr 2006 16:00:25 +0000 (16:00 +0000)
git-svn-id: http://delx.cjb.net/svn/pymsnt/trunk@141 55fbd22a-6204-0410-b2f0-b6c764c7e90a

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

src/tlib/msn/msn.py
src/tlib/msn/msnw.py
src/tlib/msn/test_msn.py
src/tlib/msn/test_msnw.py

index 96aa587556950bd6759631827f4eac1ba9a6a1e4..d236c66d649fa80f02b393c9a33877a76af9caee 100644 (file)
@@ -99,7 +99,7 @@ import msnp11chl
 # Twisted imports
 from twisted.internet import reactor, task
 from twisted.internet.defer import Deferred
 # Twisted imports
 from twisted.internet import reactor, task
 from twisted.internet.defer import Deferred
-from twisted.internet.protocol import ClientFactory
+from twisted.internet.protocol import ReconnectingClientFactory, ClientFactory
 try:
     from twisted.internet.ssl import ClientContextFactory
 except ImportError:
 try:
     from twisted.internet.ssl import ClientContextFactory
 except ImportError:
@@ -973,6 +973,7 @@ class NotificationClient(MSNEventBase):
         MSNEventBase.connectionMade(self)
         self._setState('CONNECTED')
         self.sendLine("VER %s %s" % (self._nextTransactionID(), MSN_PROTOCOL_VERSION))
         MSNEventBase.connectionMade(self)
         self._setState('CONNECTED')
         self.sendLine("VER %s %s" % (self._nextTransactionID(), MSN_PROTOCOL_VERSION))
+        self.factory.resetDelay()
 
     def connectionLost(self, reason):
         self._setState('DISCONNECTED')
 
     def connectionLost(self, reason):
         self._setState('DISCONNECTED')
@@ -1386,6 +1387,7 @@ class NotificationClient(MSNEventBase):
 
     def handle_OUT(self, params):
         checkParamLen(len(params), 1, 'OUT')
 
     def handle_OUT(self, params):
         checkParamLen(len(params), 1, 'OUT')
+        self.factory.stopTrying()
         if params[0] == "OTH": self.multipleLogin()
         elif params[0] == "SSD": self.serverGoingDown()
         else: raise MSNProtocolError, "Invalid Parameters received for OUT" # debug
         if params[0] == "OTH": self.multipleLogin()
         elif params[0] == "SSD": self.serverGoingDown()
         else: raise MSNProtocolError, "Invalid Parameters received for OUT" # debug
@@ -1991,10 +1993,11 @@ class NotificationClient(MSNEventBase):
         if self.pingCheckTask:
             self.pingCheckTask.stop()
             self.pingCheckTask = None
         if self.pingCheckTask:
             self.pingCheckTask.stop()
             self.pingCheckTask = None
+        self.factory.stopTrying()
         self.sendLine("OUT")
         self.transport.loseConnection()
 
         self.sendLine("OUT")
         self.transport.loseConnection()
 
-class NotificationFactory(ClientFactory):
+class NotificationFactory(ReconnectingClientFactory):
     """
     Factory for the NotificationClient protocol.
     This is basically responsible for keeping
     """
     Factory for the NotificationClient protocol.
     This is basically responsible for keeping
@@ -2017,6 +2020,8 @@ class NotificationFactory(ClientFactory):
                           (the whole URL is required)
     @ivar status: The status of the client -- this is generally kept
                   up to date by the default command handlers
                           (the whole URL is required)
     @ivar status: The status of the client -- this is generally kept
                   up to date by the default command handlers
+    @ivar maxRetries: The number of times the factory will reconnect
+                      if the connection dies because of a network error.
     """
 
     contacts = None
     """
 
     contacts = None
@@ -2026,6 +2031,7 @@ class NotificationFactory(ClientFactory):
     passportServer = 'https://nexus.passport.com/rdr/pprdr.asp'
     status = 'FLN'
     protocol = NotificationClient
     passportServer = 'https://nexus.passport.com/rdr/pprdr.asp'
     status = 'FLN'
     protocol = NotificationClient
+    maxRetries = 5
 
 
 class SwitchboardClient(MSNEventBase):
 
 
 class SwitchboardClient(MSNEventBase):
index cc6774c2966b439fc2b4b221fe926e8038cdbbf1..b0edb3066831e03cb6e99b5afc363fb5b49b7e64 100644 (file)
@@ -78,7 +78,6 @@ class MSNConnection:
        
        def _sendSavedEvents(self):
                self.savedEvents.send(self)
        
        def _sendSavedEvents(self):
                self.savedEvents.send(self)
-               self.savedEvents = None
        
        def _notificationClientReady(self, notificationClient):
                self.notificationClient = notificationClient
        
        def _notificationClientReady(self, notificationClient):
                self.notificationClient = notificationClient
@@ -177,8 +176,8 @@ class MSNConnection:
                if self.notificationClient:
                        LogEvent(INFO, self.ident)
                        self.notificationClient.changeAvatar(imageData, push=True)
                if self.notificationClient:
                        LogEvent(INFO, self.ident)
                        self.notificationClient.changeAvatar(imageData, push=True)
-               else:
-                       self.savedEvents.avatarImageData = imageData
+               # Save the avatar for reuse on disconnection
+               self.savedEvents.avatarImageData = imageData
        
        def changeStatus(self, statusCode, screenName, personal):
                """
        
        def changeStatus(self, statusCode, screenName, personal):
                """
@@ -203,10 +202,10 @@ class MSNConnection:
                        self.notificationClient.changeStatus(statusCode.encode("utf-8")).addCallback(cb)
                        self.notificationClient.changeScreenName(screenName.encode("utf-8")).addCallback(cb)
                        self.notificationClient.changePersonalMessage(personal.encode("utf-8")).addCallback(cb)
                        self.notificationClient.changeStatus(statusCode.encode("utf-8")).addCallback(cb)
                        self.notificationClient.changeScreenName(screenName.encode("utf-8")).addCallback(cb)
                        self.notificationClient.changePersonalMessage(personal.encode("utf-8")).addCallback(cb)
-               else:
-                       self.savedEvents.statusCode = statusCode
-                       self.savedEvents.screenName = screenName
-                       self.savedEvents.personal = personal
+               # Remember the saved status
+               self.savedEvents.statusCode = statusCode
+               self.savedEvents.screenName = screenName
+               self.savedEvents.personal = personal
                                
        def addContact(self, listType, userHandle):
                """ See msn.NotificationClient.addContact """
                                
        def addContact(self, listType, userHandle):
                """ See msn.NotificationClient.addContact """
@@ -376,11 +375,13 @@ class NotificationClient(msn.NotificationClient):
                msn.NotificationClient.logOut(self)
        
        def connectionLost(self, reason):
                msn.NotificationClient.logOut(self)
        
        def connectionLost(self, reason):
+               print "NotificationClient.connectionLost!!!"
                if not self.factory.msncon: return # If we called logOut
                def wait():
                        LogEvent(INFO, self.factory.msncon.ident)
                        msn.NotificationClient.connectionLost(self, reason)
                if not self.factory.msncon: return # If we called logOut
                def wait():
                        LogEvent(INFO, self.factory.msncon.ident)
                        msn.NotificationClient.connectionLost(self, reason)
-                       self.factory.msncon.connectionLost(reason)
+                       if self.factory.maxRetries >= self.factory.retries:
+                               self.factory.msncon.connectionLost(reason)
                # Make sure this event is handled after any others
                reactor.callLater(0, wait)
        
                # Make sure this event is handled after any others
                reactor.callLater(0, wait)
        
index 1fc4ed90b86da00767c76df5b80848a2193e8561..3e716de71dc9be9a3fc6059ab005a5ca237c0c52 100644 (file)
@@ -748,6 +748,8 @@ class NotificationPingTests(unittest.TestCase):
         msn.PINGSPEED = 0.1
         self.client = DummyPingNotificationClient()
         self.server = DummyPingNotificationServer()
         msn.PINGSPEED = 0.1
         self.client = DummyPingNotificationClient()
         self.server = DummyPingNotificationServer()
+        self.client.factory = msn.NotificationFactory()
+        self.server.factory = msn.NotificationFactory()
         self.client.state = 'CONNECTED'
         self.client.count = 0
         self.loop = LoopbackCon(self.client, self.server)
         self.client.state = 'CONNECTED'
         self.client.count = 0
         self.loop = LoopbackCon(self.client, self.server)
index 97579db908d546f966bae9923d7c5cabec21f9b2..cf7a974d6b28584437483c5cc48be9230b239ee5 100644 (file)
@@ -36,19 +36,16 @@ if LOGGING:
        log.startLogging(sys.stdout)
 
 
        log.startLogging(sys.stdout)
 
 
-checkCount = 0 # Uck!
 def clearAccount(msncon):
        """ Clears the contact list of the given MSNConnection. Returns a
        Deferred which fires when the task is complete.
        """
        d = Deferred()
        count = 0
 def clearAccount(msncon):
        """ Clears the contact list of the given MSNConnection. Returns a
        Deferred which fires when the task is complete.
        """
        d = Deferred()
        count = 0
-       global checkCount
-       checkCount = 0
+       checkCount = [0]
        def cb(ignored=None):
        def cb(ignored=None):
-               global checkCount
-               checkCount += 1
-               if checkCount == count:
+               checkCount[0] += 1
+               if checkCount[0] == count:
                        d.callback(None)
 
        for msnContact in msncon.getContacts().contacts.values():
                        d.callback(None)
 
        for msnContact in msncon.getContacts().contacts.values():
@@ -130,7 +127,7 @@ class TestsUtil:
                        self.loop("Adding user1 to user2's allow list.")
 
                        # Check the contacts have seen each other
                        self.loop("Adding user1 to user2's allow list.")
 
                        # Check the contacts have seen each other
-                       reactor.iterate(0.1) # One last chance to notice each other
+                       reactor.iterate(0.5) # One last chance to notice each other
                        self.failUnless((self.user1.contactAdded == USER2 and self.user2.contactAdded == USER1), "Contacts can't see each other.")
 
        def cb(self, ignored=None):
                        self.failUnless((self.user1.contactAdded == USER2 and self.user2.contactAdded == USER1), "Contacts can't see each other.")
 
        def cb(self, ignored=None):
@@ -168,6 +165,14 @@ class BasicTests(unittest.TestCase, TestsUtil):
        def tearDown(self):
                TestsUtil.tearDown(self)
 
        def tearDown(self):
                TestsUtil.tearDown(self)
 
+       def testReconnect(self):
+               self.user1 = MSNConnection(USER1, PASS1, "user1", self)
+               self.loop("Looping user1.", cond="SYNCED")
+               self.user1.notificationClient.transport.loseConnection()
+               self.done = False
+               self.loop("Looping user1.", cond="SYNCED")
+       testReconnect.skip = FTRECEIVETEST or FTSENDTEST
+
        def testConnect(self):
                self.doLogins(both=False)
        testConnect.skip = FTRECEIVETEST or FTSENDTEST
        def testConnect(self):
                self.doLogins(both=False)
        testConnect.skip = FTRECEIVETEST or FTSENDTEST