source: ralphm-patches/addHandler-48.patch @ 47:f6d222b68f1c

Last change on this file since 47:f6d222b68f1c was 47:f6d222b68f1c, checked in by Ralph Meijer <ralphm@…>, 11 years ago

Many new patches, upstreamed affiliations and worked on pubsub item.
Upstreamed pubsub_manage_affiliations

File size: 5.7 KB
  • wokkel/subprotocols.py

    # HG changeset patch
    # Parent bcf4497abc14816955c62dc9429a8d61f0cfe703
    Fix race condition and nesting errors when adding a new subprotocol handler.
    
    This fixes two related issues with adding a new subprotocol handler:
    
     * Adding a handler when the stream is not yet initialized (authenticated)
       does not cause `connectionMade` to be called.
     * Adding a handler in `connectionMade`, `connectionInitialized`, or
       `connectionLost` modifies the lists of handlers iterated over, causing
       some methods being called too often.
    
    Author: ff, kandaurovoleg, ralphm.
    Fixes: #48.
    
    diff -r bcf4497abc14 wokkel/subprotocols.py
    a b  
    185185
    186186        # get protocol handler up to speed when a connection has already
    187187        # been established
    188         if self.xmlstream and self._initialized:
     188        if self.xmlstream:
    189189            handler.makeConnection(self.xmlstream)
     190        if self._initialized:
    190191            handler.connectionInitialized()
    191192
    192193
     
    210211
    211212        self.xmlstream = xs
    212213
    213         for e in self:
     214        for e in list(self):
    214215            e.makeConnection(xs)
    215216
    216217
     
    229230
    230231        # Notify all child services which implement
    231232        # the IService interface
    232         for e in self:
     233        for e in list(self):
    233234            e.connectionInitialized()
    234235
    235236
     
    264265
    265266        # Notify all child services which implement
    266267        # the IService interface
    267         for e in self:
     268        for e in list(self):
    268269            e.connectionLost(reason)
    269270
    270271
  • wokkel/test/test_subprotocols.py

    diff -r bcf4497abc14 wokkel/test/test_subprotocols.py
    a b  
    286286        self.assertEquals(0, handler.doneLost)
    287287
    288288
     289    def test_addHandlerConnected(self):
     290        """
     291        Adding a handler when connected doesn't call connectionInitialized.
     292        """
     293        sm = self.streamManager
     294        xs = xmlstream.XmlStream(xmlstream.Authenticator())
     295        sm._connected(xs)
     296        handler = DummyXMPPHandler()
     297        handler.setHandlerParent(sm)
     298
     299        self.assertEquals(1, handler.doneMade)
     300        self.assertEquals(0, handler.doneInitialized)
     301        self.assertEquals(0, handler.doneLost)
     302
     303
     304    def test_addHandlerConnectedNested(self):
     305        """
     306        Adding a handler in connectionMade doesn't cause 2nd call.
     307        """
     308        class NestingHandler(DummyXMPPHandler):
     309            nestedHandler = None
     310
     311            def connectionMade(self):
     312                DummyXMPPHandler.connectionMade(self)
     313                self.nestedHandler = DummyXMPPHandler()
     314                self.nestedHandler.setHandlerParent(self.parent)
     315
     316        sm = self.streamManager
     317        xs = xmlstream.XmlStream(xmlstream.Authenticator())
     318        handler = NestingHandler()
     319        handler.setHandlerParent(sm)
     320        sm._connected(xs)
     321
     322        self.assertEquals(1, handler.doneMade)
     323        self.assertEquals(0, handler.doneInitialized)
     324        self.assertEquals(0, handler.doneLost)
     325
     326        self.assertEquals(1, handler.nestedHandler.doneMade)
     327        self.assertEquals(0, handler.nestedHandler.doneInitialized)
     328        self.assertEquals(0, handler.nestedHandler.doneLost)
     329
     330
     331
    289332    def test_addHandlerInitialized(self):
    290333        """
    291334        Test the addition of a protocol handler after the stream
     
    306349        self.assertEquals(1, handler.doneInitialized)
    307350        self.assertEquals(0, handler.doneLost)
    308351
     352
     353    def test_addHandlerInitializedNested(self):
     354        """
     355        Adding a handler in connectionInitialized doesn't cause 2nd call.
     356        """
     357        class NestingHandler(DummyXMPPHandler):
     358            nestedHandler = None
     359
     360            def connectionInitialized(self):
     361                DummyXMPPHandler.connectionInitialized(self)
     362                self.nestedHandler = DummyXMPPHandler()
     363                self.nestedHandler.setHandlerParent(self.parent)
     364
     365        sm = self.streamManager
     366        xs = xmlstream.XmlStream(xmlstream.Authenticator())
     367        handler = NestingHandler()
     368        handler.setHandlerParent(sm)
     369        sm._connected(xs)
     370        sm._authd(xs)
     371
     372        self.assertEquals(1, handler.doneMade)
     373        self.assertEquals(1, handler.doneInitialized)
     374        self.assertEquals(0, handler.doneLost)
     375
     376        self.assertEquals(1, handler.nestedHandler.doneMade)
     377        self.assertEquals(1, handler.nestedHandler.doneInitialized)
     378        self.assertEquals(0, handler.nestedHandler.doneLost)
     379
     380
     381    def test_addHandlerConnectionLostNested(self):
     382        """
     383        Adding a handler in connectionLost doesn't call connectionLost there.
     384        """
     385        class NestingHandler(DummyXMPPHandler):
     386            nestedHandler = None
     387
     388            def connectionLost(self, reason):
     389                DummyXMPPHandler.connectionLost(self, reason)
     390                self.nestedHandler = DummyXMPPHandler()
     391                self.nestedHandler.setHandlerParent(self.parent)
     392
     393        sm = self.streamManager
     394        xs = xmlstream.XmlStream(xmlstream.Authenticator())
     395        handler = NestingHandler()
     396        handler.setHandlerParent(sm)
     397        sm._connected(xs)
     398        sm._authd(xs)
     399        sm._disconnected(xs)
     400
     401        self.assertEquals(1, handler.doneMade)
     402        self.assertEquals(1, handler.doneInitialized)
     403        self.assertEquals(1, handler.doneLost)
     404
     405        self.assertEquals(0, handler.nestedHandler.doneMade)
     406        self.assertEquals(0, handler.nestedHandler.doneInitialized)
     407        self.assertEquals(0, handler.nestedHandler.doneLost)
     408
     409
    309410    def test_removeHandler(self):
    310411        """
    311412        Test removal of protocol handler.
Note: See TracBrowser for help on using the repository browser.