Ticket #3407: xmpp-router.patch

File xmpp-router.patch, 44.3 KB (added by ralphm, 6 years ago)

Patch bomb resulting in a XMPP router plugin for twistd.

  • twisted/plugins/twisted_words.py

    diff -r 32bd907eefae -r e255d835eef1 twisted/plugins/twisted_words.py
    a b  
    2020    "A modern words server", 
    2121    "words") 
    2222 
     23TwistedXMPPRouter = ServiceMaker( 
     24    "XMPP Router", 
     25    "twisted.words.xmpproutertap", 
     26    "An XMPP Router server", 
     27    "xmpp-router") 
     28 
    2329class RelayChatInterface(object): 
    2430    classProvides(IPlugin, iwords.IProtocolPlugin) 
    2531 
  • twisted/words/protocols/jabber/client.py

    diff -r 32bd907eefae -r e255d835eef1 twisted/words/protocols/jabber/client.py
    a b  
    11# -*- test-case-name: twisted.words.test.test_jabberclient -*- 
    22# 
    3 # Copyright (c) 2001-2005 Twisted Matrix Laboratories. 
     3# Copyright (c) 2001-2008 Twisted Matrix Laboratories. 
    44# See LICENSE for details. 
    55 
    66from twisted.internet import defer 
     
    1717PlaintextAuthQry = xpath.internQuery("/iq/query/password") 
    1818 
    1919def basicClientFactory(jid, secret): 
    20     a = BasicAuthenticator(jid, secret) 
    21     return xmlstream.XmlStreamFactory(a) 
     20    return xmlstream.XmlStreamFactory(BasicAuthenticator, jid, secret) 
    2221 
    2322class IQ(domish.Element): 
    2423    """ 
     
    298297    @return: XML stream factory. 
    299298    @rtype: L{xmlstream.XmlStreamFactory} 
    300299    """ 
    301     a = XMPPAuthenticator(jid, password) 
    302     return xmlstream.XmlStreamFactory(a) 
     300    return xmlstream.XmlStreamFactory(XMPPAuthenticator, jid, password) 
    303301 
    304302 
    305303 
     
    339337 
    340338    namespace = 'jabber:client' 
    341339 
    342     def __init__(self, jid, password): 
    343         xmlstream.ConnectAuthenticator.__init__(self, jid.host) 
     340    def __init__(self, xs, jid, password): 
     341        xmlstream.ConnectAuthenticator.__init__(self, xs, jid.host) 
    344342        self.jid = jid 
    345343        self.password = password 
    346  
    347  
    348     def associateWithStream(self, xs): 
    349         """ 
    350         Register with the XML stream. 
    351  
    352         Populates stream's list of initializers, along with their 
    353         requiredness. This list is used by 
    354         L{ConnectAuthenticator.initializeStream} to perform the initalization 
    355         steps. 
    356         """ 
    357         xmlstream.ConnectAuthenticator.associateWithStream(self, xs) 
    358344 
    359345        xs.initializers = [CheckVersionInitializer(xs)] 
    360346        inits = [ (xmlstream.TLSInitiatingInitializer, False), 
  • twisted/words/protocols/jabber/component.py

    diff -r 32bd907eefae -r e255d835eef1 twisted/words/protocols/jabber/component.py
    a b  
    11# -*- test-case-name: twisted.words.test.test_jabbercomponent -*- 
    22# 
    3 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. 
     3# Copyright (c) 2001-2008 Twisted Matrix Laboratories. 
    44# See LICENSE for details. 
    55 
    66""" 
     
    2121from zope.interface import implements 
    2222 
    2323from twisted.application import service 
    24 from twisted.internet import defer 
     24from twisted.internet import defer, reactor 
     25from twisted.python import log 
    2526from twisted.words.xish import domish 
    26 from twisted.words.protocols.jabber import ijabber, jstrports, xmlstream 
     27from twisted.words.protocols.jabber import error, ijabber, jstrports, xmlstream 
     28from twisted.words.protocols.jabber.jid import internJID as JID 
     29 
     30NS_COMPONENT_ACCEPT = 'jabber:component:accept' 
    2731 
    2832def componentFactory(componentid, password): 
    2933    """ 
     
    3438    @param password: password used to authenticate to the server. 
    3539    @type password: L{str} 
    3640    """ 
    37     a = ConnectComponentAuthenticator(componentid, password) 
    38     return xmlstream.XmlStreamFactory(a) 
     41    return xmlstream.XmlStreamFactory(ConnectComponentAuthenticator, 
     42                                      componentid, password) 
     43 
     44 
    3945 
    4046class ComponentInitiatingInitializer(object): 
    4147    """ 
     
    6874        self.xmlstream.thisEntity = self.xmlstream.otherEntity 
    6975        self._deferred.callback(None) 
    7076 
     77 
     78 
    7179class ConnectComponentAuthenticator(xmlstream.ConnectAuthenticator): 
    7280    """ 
    7381    Authenticator to permit an XmlStream to authenticate against a Jabber 
    7482    server as an external component (where the Authenticator is initiating the 
    7583    stream). 
    7684    """ 
    77     namespace = 'jabber:component:accept' 
     85    namespace = NS_COMPONENT_ACCEPT 
    7886 
    79     def __init__(self, componentjid, password): 
     87    def __init__(self, xs, componentjid, password): 
    8088        """ 
    8189        @type componentjid: L{str} 
    8290        @param componentjid: Jabber ID that this component wishes to bind to. 
     
    8593        @param password: Password/secret this component uses to authenticate. 
    8694        """ 
    8795        # Note that we are sending 'to' our desired component JID. 
    88         xmlstream.ConnectAuthenticator.__init__(self, componentjid) 
     96        xs.version = (0, 0) 
     97        xmlstream.ConnectAuthenticator.__init__(self, xs, componentjid) 
     98        xs.initializers = [ComponentInitiatingInitializer(xs)] 
    8999        self.password = password 
    90100 
    91     def associateWithStream(self, xs): 
     101 
     102 
     103class ListenComponentAuthenticator(xmlstream.ListenAuthenticator): 
     104    """ 
     105    Authenticator for accepting components. 
     106    """ 
     107    namespace = NS_COMPONENT_ACCEPT 
     108 
     109    def __init__(self, xs, secret): 
    92110        xs.version = (0, 0) 
    93         xmlstream.ConnectAuthenticator.associateWithStream(self, xs) 
     111        self.secret = secret 
     112        xmlstream.ListenAuthenticator.__init__(self, xs) 
    94113 
    95         xs.initializers = [ComponentInitiatingInitializer(xs)] 
    96114 
    97 class ListenComponentAuthenticator(xmlstream.Authenticator): 
    98     """ 
    99     Placeholder for listening components. 
    100     """ 
     115    def streamStarted(self, rootElement): 
     116        xmlstream.ListenAuthenticator.streamStarted(self, rootElement) 
     117 
     118        if rootElement.defaultUri != self.namespace: 
     119            exc = error.StreamError('invalid-namespace') 
     120            self.xmlstream.sendStreamError(exc) 
     121            return 
     122 
     123        # self.xmlstream.thisEntity is set to the address the component 
     124        # wants to assume. This should probably be checked. 
     125        if not self.xmlstream.thisEntity: 
     126            exc = error.StreamError('improper-addressing') 
     127            self.xmlstream.sendStreamError(exc) 
     128            return 
     129 
     130        self.xmlstream.sid = 'random' # FIXME 
     131 
     132        self.xmlstream.sendHeader() 
     133        self.xmlstream.addOnetimeObserver('/*', self.onElement) 
     134 
     135 
     136    def onElement(self, element): 
     137        if (element.uri, element.name) == (self.namespace, 'handshake'): 
     138            self.onHandshake(unicode(element)) 
     139        else: 
     140            exc = error.streamError('not-authorized') 
     141            self.xmlstream.sendStreamError(exc) 
     142 
     143 
     144    def onHandshake(self, handshake): 
     145        calculatedHash = xmlstream.hashPassword(self.xmlstream.sid, self.secret) 
     146        if handshake != calculatedHash: 
     147            exc = error.StreamError('not-authorized', text='Invalid hash') 
     148            self.xmlstream.sendStreamError(exc) 
     149        else: 
     150            self.xmlstream.send('<handshake/>') 
     151            self.xmlstream.dispatch(self.xmlstream, 
     152                                    xmlstream.STREAM_AUTHD_EVENT) 
     153 
     154 
    101155 
    102156class Service(service.Service): 
    103157    """ 
     
    227281    client_svc = jstrports.client(strport, svc.getFactory()) 
    228282    client_svc.setServiceParent(svc) 
    229283    return svc 
     284 
     285 
     286 
     287class RouterService(service.Service): 
     288    """ 
     289    XMPP Server's Router Service. 
     290 
     291    This service connects the different components of the XMPP service and 
     292    routes messages between them based on the given routing table. 
     293 
     294    Connected components are trusted to have correct addressing in the 
     295    stanzas they offer for routing. 
     296 
     297    A route destination of C{None} adds a default route. Traffic for which no 
     298    specific route exists, will be routed to this default route. 
     299 
     300    @ivar routes: Routes based on the host part of JIDs. Maps host names to the 
     301                  L{EventDispatcher<utility.EventDispatcher>}s that should 
     302                  receive the traffic. A key of C{None} means the default 
     303                  route. 
     304    @type routes: C{dict} 
     305    """ 
     306 
     307    def __init__(self): 
     308        self.routes = {} 
     309 
     310 
     311    def addRoute(self, destination, xs): 
     312        """ 
     313        Add a new route. 
     314 
     315        The passed XML Stream C{xs} will have an observer for all stanzas 
     316        added to route its outgoing traffic. In turn, traffic for 
     317        C{destination} will be passed to this stream. 
     318 
     319        @param destination: Destination of the route to be added as a host name 
     320                            or C{None} for the default route. 
     321        @type destination: C{str} or C{NoneType}. 
     322        @param xs: XML Stream to register the route for. 
     323        @type xs: L{EventDispatcher<utility.EventDispatcher>}. 
     324        """ 
     325        self.routes[destination] = xs 
     326        xs.addObserver('/*', self.route) 
     327 
     328 
     329    def removeRoute(self, destination, xs): 
     330        """ 
     331        Remove a route. 
     332 
     333        @param destination: Destination of the route that should be removed. 
     334        @type destination: C{str}. 
     335        @param xs: XML Stream to remove the route for. 
     336        @type xs: L{EventDispatcher<utility.EventDispatcher>}. 
     337        """ 
     338        xs.removeObserver('/*', self.route) 
     339        if (xs == self.routes[destination]): 
     340            del self.routes[destination] 
     341 
     342 
     343    def route(self, stanza): 
     344        """ 
     345        Route a stanza. 
     346 
     347        @param stanza: The stanza to be routed. 
     348        @type stanza: L{domish.Element}. 
     349        """ 
     350        if not list(stanza.elements()): 
     351            return 
     352 
     353        destination = JID(stanza['to']) 
     354 
     355        log.msg("Routing to %s: %r" % (destination.full(), stanza.toXml())) 
     356 
     357        if destination.host in self.routes: 
     358            self.routes[destination.host].send(stanza) 
     359        else: 
     360            self.routes[None].send(stanza) 
     361 
     362 
     363 
     364class ComponentServer(service.Service): 
     365    """ 
     366    XMPP Component Server service. 
     367 
     368    This service accepts XMPP external component connections and makes 
     369    the router service route traffic for a component's bound domain 
     370    to that component. 
     371    """ 
     372 
     373    logTraffic = False 
     374 
     375    def __init__(self, router, port=5347, secret='secret'): 
     376        self.router = router 
     377        self.port = port 
     378        self.secret = secret 
     379 
     380        self.factory = xmlstream.XmlStreamServerFactory( 
     381                ListenComponentAuthenticator, self.secret) 
     382        self.factory.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, 
     383                                  self.makeConnection) 
     384        self.factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, 
     385                                  self.connectionInitialized) 
     386 
     387        self.serial = 0 
     388 
     389 
     390    def startService(self): 
     391        service.Service.startService(self) 
     392        reactor.listenTCP(self.port, self.factory) 
     393 
     394 
     395    def makeConnection(self, xs): 
     396        """ 
     397        Called when a component connection was made. 
     398 
     399        This enables traffic debugging on incoming streams. 
     400        """ 
     401        xs.serial = self.serial 
     402        self.serial += 1 
     403 
     404        def logDataIn(buf): 
     405            log.msg("RECV (%d): %r" % (xs.serial, buf)) 
     406 
     407        def logDataOut(buf): 
     408            log.msg("SEND (%d): %r" % (xs.serial, buf)) 
     409 
     410        if self.logTraffic: 
     411            xs.rawDataInFn = logDataIn 
     412            xs.rawDataOutFn = logDataOut 
     413 
     414        xs.addObserver(xmlstream.STREAM_ERROR_EVENT, self.onError) 
     415 
     416 
     417    def connectionInitialized(self, xs): 
     418        """ 
     419        Called when a component has succesfully authenticated. 
     420 
     421        Add the component to the routing table and establish a handler 
     422        for a closed connection. 
     423        """ 
     424        destination = xs.thisEntity.host 
     425 
     426        self.router.addRoute(destination, xs) 
     427        xs.addObserver(xmlstream.STREAM_END_EVENT, self.connectionLost, 0, 
     428                                                   destination, xs) 
     429 
     430 
     431    def onError(self, reason): 
     432        log.err(reason, "Stream Error") 
     433 
     434 
     435    def connectionLost(self, destination, xs, reason): 
     436        self.router.removeRoute(destination, xs) 
  • twisted/words/protocols/jabber/xmlstream.py

    diff -r 32bd907eefae -r e255d835eef1 twisted/words/protocols/jabber/xmlstream.py
    a b  
    1313 
    1414from zope.interface import directlyProvides, implements 
    1515 
    16 from twisted.internet import defer 
     16from twisted.internet import defer, protocol 
    1717from twisted.internet.error import ConnectionLost 
    1818from twisted.python import failure, log 
    1919from twisted.words.protocols.jabber import error, ijabber, jid 
     
    5757    Rules: 
    5858      1. The Authenticator MUST dispatch a L{STREAM_AUTHD_EVENT} when the 
    5959         stream has been completely initialized. 
    60       2. The Authenticator SHOULD reset all state information when 
    61          L{associateWithStream} is called. 
    62       3. The Authenticator SHOULD override L{streamStarted}, and start 
     60      2. The Authenticator SHOULD override L{streamStarted}, and start 
    6361         initialization there. 
    6462 
    6563    @type xmlstream: L{XmlStream} 
     
    7068           of XML stanzas. 
    7169    """ 
    7270 
    73     def __init__(self): 
    74         self.xmlstream = None 
     71    def __init__(self, xs): 
     72        self.xmlstream = xs 
    7573 
    7674 
    7775    def connectionMade(self): 
     
    116114        self.xmlstream.version = min(self.xmlstream.version, version) 
    117115 
    118116 
    119     def associateWithStream(self, xmlstream): 
    120         """ 
    121         Called by the XmlStreamFactory when a connection has been made 
    122         to the requested peer, and an XmlStream object has been 
    123         instantiated. 
    124  
    125         The default implementation just saves a handle to the new 
    126         XmlStream. 
    127  
    128         @type xmlstream: L{XmlStream} 
    129         @param xmlstream: The XmlStream that will be passing events to this 
    130                           Authenticator. 
    131  
    132         """ 
    133         self.xmlstream = xmlstream 
    134  
    135  
    136117 
    137118class ConnectAuthenticator(Authenticator): 
    138119    """ 
     
    141122 
    142123    namespace = None 
    143124 
    144     def __init__(self, otherHost): 
     125    def __init__(self, xs, otherHost): 
     126        Authenticator.__init__(self, xs) 
    145127        self.otherHost = otherHost 
    146128 
    147129 
     
    240222 
    241223    namespace = None 
    242224 
    243     def associateWithStream(self, xmlstream): 
    244         """ 
    245         Called by the XmlStreamFactory when a connection has been made. 
    246  
    247         Extend L{Authenticator.associateWithStream} to set the L{XmlStream} 
    248         to be non-initiating. 
    249         """ 
    250         Authenticator.associateWithStream(self, xmlstream) 
    251         self.xmlstream.initiating = False 
     225    def __init__(self, xs): 
     226        xs.initiating = False 
     227        Authenticator.__init__(self, xs) 
    252228 
    253229 
    254230    def streamStarted(self, rootElement): 
     
    475451 
    476452    _headerSent = False     # True if the stream header has been sent 
    477453 
    478     def __init__(self, authenticator): 
     454    def __init__(self, authenticatorClass, *args, **kwargs): 
    479455        xmlstream.XmlStream.__init__(self) 
    480456 
    481457        self.prefixes = {NS_STREAMS: 'stream'} 
    482         self.authenticator = authenticator 
    483458        self.initializers = [] 
    484459        self.features = {} 
    485  
    486         # Reset the authenticator 
    487         authenticator.associateWithStream(self) 
     460        self.authenticator = authenticatorClass(self, *args, **kwargs) 
    488461 
    489462 
    490463    def _callLater(self, *args, **kwargs): 
     
    639612class XmlStreamFactory(xmlstream.XmlStreamFactory): 
    640613    """ 
    641614    Factory for Jabber XmlStream objects as a reconnecting client. 
    642  
    643     Note that this differs from L{xmlstream.XmlStreamFactory} in that 
    644     it generates Jabber specific L{XmlStream} instances that have 
    645     authenticators. 
    646615    """ 
    647616 
    648617    protocol = XmlStream 
    649618 
    650     def __init__(self, authenticator): 
    651         xmlstream.XmlStreamFactory.__init__(self, authenticator) 
    652         self.authenticator = authenticator 
     619 
     620 
     621class XmlStreamServerFactory(xmlstream.XmlStreamFactoryMixin, 
     622                             protocol.ServerFactory): 
     623    """ 
     624    Factory for Jabber XmlStream objects as a server. 
     625    """ 
     626 
     627    protocol = XmlStream 
    653628 
    654629 
    655630 
  • twisted/words/test/test_jabberclient.py

    diff -r 32bd907eefae -r e255d835eef1 twisted/words/test/test_jabberclient.py
    a b  
    1 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. 
     1# Copyright (c) 2001-2008 Twisted Matrix Laboratories. 
    22# See LICENSE for details. 
    33 
    44""" 
     
    1212 
    1313class CheckVersionInitializerTest(unittest.TestCase): 
    1414    def setUp(self): 
    15         a = xmlstream.Authenticator() 
    16         xs = xmlstream.XmlStream(a) 
     15        xs = xmlstream.XmlStream(xmlstream.Authenticator) 
    1716        self.init = client.CheckVersionInitializer(xs) 
    1817 
    1918    def testSupported(self): 
     
    3534class InitiatingInitializerHarness(object): 
    3635    def setUp(self): 
    3736        self.output = [] 
    38         self.authenticator = xmlstream.ConnectAuthenticator('example.org') 
    39         self.xmlstream = xmlstream.XmlStream(self.authenticator) 
     37        self.xmlstream = xmlstream.XmlStream(xmlstream.ConnectAuthenticator, 
     38                                             'example.org') 
    4039        self.xmlstream.send = self.output.append 
    4140        self.xmlstream.connectionMade() 
    4241        self.xmlstream.dataReceived("<stream:stream xmlns='jabber:client' " 
     
    4847    def setUp(self): 
    4948        super(IQAuthInitializerTest, self).setUp() 
    5049        self.init = client.IQAuthInitializer(self.xmlstream) 
    51         self.authenticator.jid = jid.JID('user@example.com/resource') 
    52         self.authenticator.password = 'secret' 
     50        self.xmlstream.authenticator.jid = jid.JID('user@example.com/resource') 
     51        self.xmlstream.authenticator.password = 'secret' 
    5352 
    5453    def testBasic(self): 
    5554        """ 
     
    158157    def setUp(self): 
    159158        super(BindInitializerTest, self).setUp() 
    160159        self.init = client.BindInitializer(self.xmlstream) 
    161         self.authenticator.jid = jid.JID('user@example.com/resource') 
     160        self.xmlstream.authenticator.jid = jid.JID('user@example.com/resource') 
    162161 
    163162    def testBasic(self): 
    164163        """ 
     
    168167        """ 
    169168        def cb(result): 
    170169            self.assertEquals(jid.JID('user@example.com/other resource'), 
    171                               self.authenticator.jid) 
     170                              self.xmlstream.authenticator.jid) 
    172171 
    173172        d = self.init.start().addCallback(cb) 
    174173        iq = self.output[-1] 
  • twisted/words/test/test_jabbercomponent.py

    diff -r 32bd907eefae -r e255d835eef1 twisted/words/test/test_jabbercomponent.py
    a b  
    1 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. 
     1# Copyright (c) 2001-2008 Twisted Matrix Laboratories. 
    22# See LICENSE for details. 
    33 
    44""" 
     
    66""" 
    77 
    88import sha 
     9 
     10from twisted.python import failure 
     11from twisted.test import proto_helpers 
    912from twisted.trial import unittest 
    10  
    11 from twisted.words.protocols.jabber import component 
    12 from twisted.words.protocols import jabber 
    13 from twisted.words.protocols.jabber import xmlstream 
     13from twisted.words.protocols.jabber import component, xmlstream 
     14from twisted.words.protocols.jabber.jid import JID 
     15from twisted.words.xish import domish 
     16from twisted.words.xish.utility import XmlPipe 
    1417 
    1518class DummyTransport: 
    1619    def __init__(self, list): 
     
    2326    def setUp(self): 
    2427        self.output = [] 
    2528 
    26         self.authenticator = xmlstream.Authenticator() 
    27         self.authenticator.password = 'secret' 
    28         self.xmlstream = xmlstream.XmlStream(self.authenticator) 
     29        self.xmlstream = xmlstream.XmlStream(xmlstream.Authenticator) 
     30        self.xmlstream.authenticator.password = 'secret' 
    2931        self.xmlstream.namespace = 'test:component' 
    3032        self.xmlstream.send = self.output.append 
    3133        self.xmlstream.connectionMade() 
     
    6668        self.authComplete = False 
    6769        outlist = [] 
    6870 
    69         ca = component.ConnectComponentAuthenticator("cjid", "secret") 
    70         xs = xmlstream.XmlStream(ca) 
     71        xs = xmlstream.XmlStream(component.ConnectComponentAuthenticator, 
     72                                 "cjid", "secret") 
    7173        xs.transport = DummyTransport(outlist) 
    7274 
    7375        xs.addObserver(xmlstream.STREAM_AUTHD_EVENT, 
     
    8789        self.assertEquals(self.authComplete, True) 
    8890 
    8991 
    90 class JabberServiceHarness(jabber.component.Service): 
     92class JabberServiceHarness(component.Service): 
    9193    def __init__(self): 
    9294        self.componentConnectedFlag = False 
    9395        self.componentDisconnectedFlag = False 
     
    106108class TestJabberServiceManager(unittest.TestCase): 
    107109    def testSM(self): 
    108110        # Setup service manager and test harnes 
    109         sm = jabber.component.ServiceManager("foo", "password") 
     111        sm = component.ServiceManager("foo", "password") 
    110112        svc = JabberServiceHarness() 
    111113        svc.setServiceParent(sm) 
    112114 
     
    135137 
    136138        # Ensure the test service harness got notified 
    137139        self.assertEquals(True, svc.componentDisconnectedFlag) 
     140 
     141 
     142 
     143class RouterServiceTest(unittest.TestCase): 
     144    """ 
     145    Tests for L{component.RouterService}. 
     146    """ 
     147 
     148    def test_addRoute(self): 
     149        """ 
     150        Test route registration and routing on incoming stanzas. 
     151        """ 
     152        router = component.RouterService() 
     153        routed = [] 
     154        router.route = lambda element: routed.append(element) 
     155 
     156        pipe = XmlPipe() 
     157        router.addRoute('example.org', pipe.sink) 
     158        self.assertEquals(1, len(router.routes)) 
     159        self.assertEquals(pipe.sink, router.routes['example.org']) 
     160 
     161        element = domish.Element(('testns', 'test')) 
     162        pipe.source.send(element) 
     163        self.assertEquals([element], routed) 
     164 
     165 
     166    def test_route(self): 
     167        """ 
     168        Test routing of a message. 
     169        """ 
     170        component1 = XmlPipe() 
     171        component2 = XmlPipe() 
     172        router = component.RouterService() 
     173        router.addRoute('component1.example.org', component1.sink) 
     174        router.addRoute('component2.example.org', component2.sink) 
     175 
     176        outgoing = [] 
     177        component2.source.addObserver('/*', 
     178                                      lambda element: outgoing.append(element)) 
     179        stanza = domish.Element((None, 'route')) 
     180        stanza['from'] = 'component1.example.org' 
     181        stanza['to'] = 'component2.example.org' 
     182        stanza.addElement('presence') 
     183        component1.source.send(stanza) 
     184        self.assertEquals([stanza], outgoing) 
     185 
     186 
     187    def test_routeDefault(self): 
     188        """ 
     189        Test routing of a message using the default route. 
     190 
     191        The default route is the one with C{None} as its key in the 
     192        routing table. It is taken when there is no more specific route 
     193        in the routing table that matches the stanza's destination. 
     194        """ 
     195        component1 = XmlPipe() 
     196        s2s = XmlPipe() 
     197        router = component.RouterService() 
     198        router.addRoute('component1.example.org', component1.sink) 
     199        router.addRoute(None, s2s.sink) 
     200 
     201        outgoing = [] 
     202        s2s.source.addObserver('/*', lambda element: outgoing.append(element)) 
     203        stanza = domish.Element((None, 'route')) 
     204        stanza['from'] = 'component1.example.org' 
     205        stanza['to'] = 'example.com' 
     206        stanza.addElement('presence') 
     207        component1.source.send(stanza) 
     208        self.assertEquals([stanza], outgoing) 
     209 
     210 
     211 
     212class ListenComponentAuthenticatorTest(unittest.TestCase): 
     213    """ 
     214    Tests for L{component.ListenComponentAuthenticator}. 
     215    """ 
     216 
     217    def setUp(self): 
     218        self.output = [] 
     219        authenticator = component.ListenComponentAuthenticator 
     220        self.xmlstream = xmlstream.XmlStream(authenticator, 'secret') 
     221        self.xmlstream.send = self.output.append 
     222 
     223 
     224    def loseConnection(self): 
     225        """ 
     226        Stub loseConnection because we are a transport. 
     227        """ 
     228        self.xmlstream.connectionLost("no reason") 
     229 
     230 
     231    def test_streamStarted(self): 
     232        observers = [] 
     233 
     234        def addOnetimeObserver(event, observerfn): 
     235            observers.append((event, observerfn)) 
     236 
     237        xs = self.xmlstream 
     238        xs.addOnetimeObserver = addOnetimeObserver 
     239 
     240        xs.makeConnection(self) 
     241        self.assertIdentical(None, xs.sid) 
     242        self.assertFalse(xs._headerSent) 
     243 
     244        xs.dataReceived("<stream:stream xmlns='jabber:component:accept' " 
     245                         "xmlns:stream='http://etherx.jabber.org/streams' " 
     246                         "to='component.example.org'>") 
     247        self.assertEqual((0, 0), xs.version) 
     248        self.assertNotIdentical(None, xs.sid) 
     249        self.assertTrue(xs._headerSent) 
     250        self.assertEquals(('/*', xs.authenticator.onElement), observers[-1]) 
     251 
     252 
     253    def test_streamStartedWrongNamespace(self): 
     254        """ 
     255        The received stream header should have a correct namespace. 
     256        """ 
     257        streamErrors = [] 
     258 
     259        xs = self.xmlstream 
     260        xs.sendStreamError = streamErrors.append 
     261        xs.makeConnection(self) 
     262        xs.dataReceived("<stream:stream xmlns='jabber:client' " 
     263                         "xmlns:stream='http://etherx.jabber.org/streams' " 
     264                         "to='component.example.org'>") 
     265        self.assertEquals(1, len(streamErrors)) 
     266        self.assertEquals('invalid-namespace', streamErrors[-1].condition) 
     267 
     268 
     269    def test_streamStartedNoTo(self): 
     270        streamErrors = [] 
     271 
     272        xs = self.xmlstream 
     273        xs.sendStreamError = streamErrors.append 
     274        xs.makeConnection(self) 
     275        xs.dataReceived("<stream:stream xmlns='jabber:component:accept' " 
     276                         "xmlns:stream='http://etherx.jabber.org/streams'>") 
     277        self.assertEquals(1, len(streamErrors)) 
     278        self.assertEquals('improper-addressing', streamErrors[-1].condition) 
     279 
     280 
     281    def test_onElement(self): 
     282        """ 
     283        We expect a handshake element with a hash. 
     284        """ 
     285        handshakes = [] 
     286 
     287        xs = self.xmlstream 
     288        xs.authenticator.onHandshake = handshakes.append 
     289 
     290        handshake = domish.Element(('jabber:component:accept', 'handshake')) 
     291        handshake.addContent('1234') 
     292        xs.authenticator.onElement(handshake) 
     293        self.assertEqual('1234', handshakes[-1]) 
     294 
     295    def test_onHandshake(self): 
     296        xs = self.xmlstream 
     297        xs.sid = '1234' 
     298        theHash = '32532c0f7dbf1253c095b18b18e36d38d94c1256' 
     299        xs.authenticator.onHandshake(theHash) 
     300        self.assertEqual('<handshake/>', self.output[-1]) 
     301 
     302 
     303    def test_onHandshakeWrongHash(self): 
     304        streamErrors = [] 
     305        authd = [] 
     306 
     307        def authenticated(self, xs): 
     308            authd.append(xs) 
     309 
     310        xs = self.xmlstream 
     311        xs.addOnetimeObserver(xmlstream.STREAM_AUTHD_EVENT, authenticated) 
     312        xs.sendStreamError = streamErrors.append 
     313 
     314        xs.sid = '1234' 
     315        theHash = '1234' 
     316        xs.authenticator.onHandshake(theHash) 
     317        self.assertEquals('not-authorized', streamErrors[-1].condition) 
     318        self.assertEquals(0, len(authd)) 
     319 
     320 
     321 
     322class ComponentServerTest(unittest.TestCase): 
     323    """ 
     324    Tests for L{component.ComponentServer}. 
     325    """ 
     326 
     327    def setUp(self): 
     328        self.router = component.RouterService() 
     329        self.server = component.ComponentServer(self.router) 
     330        self.xmlstream = self.server.factory.buildProtocol(None) 
     331        self.xmlstream.thisEntity = JID('component.example.org') 
     332 
     333 
     334    def test_makeConnection(self): 
     335        """ 
     336        A new connection increases the stream serial count. No logs by default. 
     337        """ 
     338        self.xmlstream.dispatch(self.xmlstream, 
     339                                xmlstream.STREAM_CONNECTED_EVENT) 
     340        self.assertEqual(0, self.xmlstream.serial) 
     341        self.assertEqual(1, self.server.serial) 
     342        self.assertIdentical(None, self.xmlstream.rawDataInFn) 
     343        self.assertIdentical(None, self.xmlstream.rawDataOutFn) 
     344 
     345 
     346    def test_makeConnectionLogTraffic(self): 
     347        """ 
     348        Setting logTraffic should set up raw data loggers. 
     349        """ 
     350        self.server.logTraffic = True 
     351        self.xmlstream.dispatch(self.xmlstream, 
     352                                xmlstream.STREAM_CONNECTED_EVENT) 
     353        self.assertNotIdentical(None, self.xmlstream.rawDataInFn) 
     354        self.assertNotIdentical(None, self.xmlstream.rawDataOutFn) 
     355 
     356 
     357    def test_onError(self): 
     358        """ 
     359        An observer for stream errors should trigger onError to log it. 
     360        """ 
     361        self.xmlstream.dispatch(self.xmlstream, 
     362                                xmlstream.STREAM_CONNECTED_EVENT) 
     363 
     364        class TestError(Exception): 
     365            pass 
     366 
     367        reason = failure.Failure(TestError()) 
     368        self.xmlstream.dispatch(reason, xmlstream.STREAM_ERROR_EVENT) 
     369        self.assertEqual(1, len(self.flushLoggedErrors(TestError))) 
     370 
     371 
     372    def test_connectionInitialized(self): 
     373        """ 
     374        Make sure a new stream is added to the routing table. 
     375        """ 
     376        self.xmlstream.dispatch(self.xmlstream, xmlstream.STREAM_AUTHD_EVENT) 
     377        self.assertIn('component.example.org', self.router.routes) 
     378        self.assertIdentical(self.xmlstream, 
     379                             self.router.routes['component.example.org']) 
     380 
     381 
     382    def test_connectionLost(self): 
     383        """ 
     384        Make sure a stream is removed from the routing table on disconnect. 
     385        """ 
     386        self.xmlstream.dispatch(self.xmlstream, xmlstream.STREAM_AUTHD_EVENT) 
     387        self.xmlstream.dispatch(None, xmlstream.STREAM_END_EVENT) 
     388        self.assertNotIn('component.example.org', self.router.routes) 
  • twisted/words/test/test_jabbersasl.py

    diff -r 32bd907eefae -r e255d835eef1 twisted/words/test/test_jabbersasl.py
    a b  
    1 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. 
     1# Copyright (c) 2001-2008 Twisted Matrix Laboratories. 
    22# See LICENSE for details. 
    33 
    44from zope.interface import implements 
     
    6060    def setUp(self): 
    6161        self.output = [] 
    6262 
    63         self.authenticator = xmlstream.Authenticator() 
    64         self.xmlstream = xmlstream.XmlStream(self.authenticator) 
     63        self.xmlstream = xmlstream.XmlStream(xmlstream.Authenticator) 
    6564        self.xmlstream.send = self.output.append 
    6665        self.xmlstream.connectionMade() 
    6766        self.xmlstream.dataReceived("<stream:stream xmlns='jabber:client' " 
  • twisted/words/test/test_jabberxmlstream.py

    diff -r 32bd907eefae -r e255d835eef1 twisted/words/test/test_jabberxmlstream.py
    a b  
    2727    """ 
    2828 
    2929    def setUp(self): 
    30         authenticator = xmlstream.ConnectAuthenticator('otherhost') 
    31         authenticator.namespace = 'testns' 
    32         self.xmlstream = xmlstream.XmlStream(authenticator) 
     30        self.xmlstream = xmlstream.XmlStream(xmlstream.ConnectAuthenticator, 
     31                                             'otherhost') 
    3332        self.clock = task.Clock() 
     33        self.xmlstream.authenticator.namespace = 'testns' 
    3434        self.xmlstream._callLater = self.clock.callLater 
    3535        self.xmlstream.makeConnection(proto_helpers.StringTransport()) 
    3636        self.xmlstream.dataReceived( 
     
    206206        self.gotStreamStart = False 
    207207        self.gotStreamEnd = False 
    208208        self.gotStreamError = False 
    209         xs = xmlstream.XmlStream(xmlstream.Authenticator()) 
     209        xs = xmlstream.XmlStream(xmlstream.Authenticator) 
    210210        xs.addObserver('//event/stream/start', self.onStreamStart) 
    211211        xs.addObserver('//event/stream/end', self.onStreamEnd) 
    212212        xs.addObserver('//event/stream/error', self.onStreamError) 
     
    395395        streamStartedCalls = [] 
    396396        associateWithStreamCalls = [] 
    397397 
    398         class TestAuthenticator: 
     398        class TestAuthenticator(xmlstream.Authenticator): 
    399399            def connectionMade(self): 
    400400                connectionMadeCalls.append(None) 
    401401 
    402402            def streamStarted(self, rootElement): 
    403403                streamStartedCalls.append(rootElement) 
    404404 
    405             def associateWithStream(self, xs): 
    406                 associateWithStreamCalls.append(xs) 
    407  
    408         a = TestAuthenticator() 
    409         xs = xmlstream.XmlStream(a) 
    410         self.assertEqual([xs], associateWithStreamCalls) 
     405        xs = xmlstream.XmlStream(TestAuthenticator) 
    411406        xs.connectionMade() 
    412407        self.assertEqual([None], connectionMadeCalls) 
    413408        xs.dataReceived("<stream:stream xmlns='jabber:client' " 
     
    426421 
    427422class AuthenticatorTest(unittest.TestCase): 
    428423    def setUp(self): 
    429         self.authenticator = xmlstream.ListenAuthenticator() 
    430         self.xmlstream = xmlstream.XmlStream(self.authenticator) 
     424        self.xmlstream = xmlstream.XmlStream(xmlstream.ListenAuthenticator) 
    431425 
    432426 
    433427    def test_streamStart(self): 
     
    493487    def setUp(self): 
    494488        self.gotAuthenticated = False 
    495489        self.initFailure = None 
    496         self.authenticator = xmlstream.ConnectAuthenticator('otherHost') 
    497         self.xmlstream = xmlstream.XmlStream(self.authenticator) 
     490        self.xmlstream = xmlstream.XmlStream(xmlstream.ConnectAuthenticator, 
     491                                             'otherHost') 
    498492        self.xmlstream.addObserver('//event/stream/authd', self.onAuthenticated) 
    499493        self.xmlstream.addObserver('//event/xmpp/initfailed', self.onInitFailed) 
    500494 
     
    518512        init = Initializer() 
    519513        self.xmlstream.initializers = [init] 
    520514 
    521         self.authenticator.initializeStream() 
     515        self.xmlstream.authenticator.initializeStream() 
    522516        self.assertEqual([], self.xmlstream.initializers) 
    523517        self.assertTrue(self.gotAuthenticated) 
    524518 
     
    534528        init = Initializer() 
    535529        self.xmlstream.initializers = [init] 
    536530 
    537         self.authenticator.initializeStream() 
     531        self.xmlstream.authenticator.initializeStream() 
    538532        self.assertEqual([init], self.xmlstream.initializers) 
    539533        self.assertFalse(self.gotAuthenticated) 
    540534        self.assertNotIdentical(None, self.initFailure) 
     
    546540        Test streamStart to fill the appropriate attributes from the 
    547541        stream header. 
    548542        """ 
    549         self.authenticator.namespace = 'testns' 
     543        self.xmlstream.authenticator.namespace = 'testns' 
    550544        xs = self.xmlstream 
    551545        xs.makeConnection(proto_helpers.StringTransport()) 
    552546        xs.dataReceived("<stream:stream xmlns='jabber:client' " 
     
    569563 
    570564class ListenAuthenticatorTest(unittest.TestCase): 
    571565    def setUp(self): 
    572         self.authenticator = xmlstream.ListenAuthenticator() 
    573         self.xmlstream = xmlstream.XmlStream(self.authenticator) 
     566        self.xmlstream = xmlstream.XmlStream(xmlstream.ListenAuthenticator) 
    574567 
    575568 
    576569    def test_streamStart(self): 
     
    599592 
    600593        self.savedSSL = xmlstream.ssl 
    601594 
    602         self.authenticator = xmlstream.Authenticator() 
    603         self.xmlstream = xmlstream.XmlStream(self.authenticator) 
     595        self.xmlstream = xmlstream.XmlStream(xmlstream.Authenticator) 
    604596        self.xmlstream.send = self.output.append 
    605597        self.xmlstream.connectionMade() 
    606598        self.xmlstream.dataReceived("<stream:stream xmlns='jabber:client' " 
     
    720712class BaseFeatureInitiatingInitializerTest(unittest.TestCase): 
    721713 
    722714    def setUp(self): 
    723         self.xmlstream = xmlstream.XmlStream(xmlstream.Authenticator()) 
     715        self.xmlstream = xmlstream.XmlStream(xmlstream.Authenticator) 
    724716        self.init = TestFeatureInitializer(self.xmlstream) 
    725717 
    726718 
     
    894886                self.doneMade = True 
    895887 
    896888        handler = TestXMPPHandler() 
    897         xs = xmlstream.XmlStream(xmlstream.Authenticator()) 
     889        xs = xmlstream.XmlStream(xmlstream.Authenticator) 
    898890        handler.makeConnection(xs) 
    899891        self.assertTrue(handler.doneMade) 
    900892        self.assertIdentical(xs, handler.xmlstream) 
     
    905897        Test that connectionLost forgets the XML stream. 
    906898        """ 
    907899        handler = xmlstream.XMPPHandler() 
    908         xs = xmlstream.XmlStream(xmlstream.Authenticator()) 
     900        xs = xmlstream.XmlStream(xmlstream.Authenticator) 
    909901        handler.makeConnection(xs) 
    910902        handler.connectionLost(Exception()) 
    911903        self.assertIdentical(None, handler.xmlstream) 
     
    985977        sm = self.streamManager 
    986978        handler = DummyXMPPHandler() 
    987979        handler.setHandlerParent(sm) 
    988         xs = xmlstream.XmlStream(xmlstream.Authenticator()) 
     980        xs = xmlstream.XmlStream(xmlstream.Authenticator) 
    989981        sm._connected(xs) 
    990982        self.assertEquals(1, handler.doneMade) 
    991983        self.assertEquals(0, handler.doneInitialized) 
     
    999991        sm = self.streamManager 
    1000992        handler = DummyXMPPHandler() 
    1001993        handler.setHandlerParent(sm) 
    1002         xs = xmlstream.XmlStream(xmlstream.Authenticator()) 
     994        xs = xmlstream.XmlStream(xmlstream.Authenticator) 
    1003995        sm._connected(xs) 
    1004996        self.assertIdentical(None, xs.rawDataInFn) 
    1005997        self.assertIdentical(None, xs.rawDataOutFn) 
     
    10131005        sm.logTraffic = True 
    10141006        handler = DummyXMPPHandler() 
    10151007        handler.setHandlerParent(sm) 
    1016         xs = xmlstream.XmlStream(xmlstream.Authenticator()) 
     1008        xs = xmlstream.XmlStream(xmlstream.Authenticator) 
    10171009        sm._connected(xs) 
    10181010        self.assertNotIdentical(None, xs.rawDataInFn) 
    10191011        self.assertNotIdentical(None, xs.rawDataOutFn) 
     
    10271019        sm = self.streamManager 
    10281020        handler = DummyXMPPHandler() 
    10291021        handler.setHandlerParent(sm) 
    1030         xs = xmlstream.XmlStream(xmlstream.Authenticator()) 
     1022        xs = xmlstream.XmlStream(xmlstream.Authenticator) 
    10311023        sm._authd(xs) 
    10321024        self.assertEquals(0, handler.doneMade) 
    10331025        self.assertEquals(1, handler.doneInitialized) 
     
    10421034        sm = self.streamManager 
    10431035        handler = DummyXMPPHandler() 
    10441036        handler.setHandlerParent(sm) 
    1045         xs = xmlstream.XmlStream(xmlstream.Authenticator()) 
     1037        xs = xmlstream.XmlStream(xmlstream.Authenticator) 
    10461038        sm._disconnected(xs) 
    10471039        self.assertEquals(0, handler.doneMade) 
    10481040        self.assertEquals(0, handler.doneInitialized) 
     
    10721064        called. 
    10731065        """ 
    10741066        sm = self.streamManager 
    1075         xs = xmlstream.XmlStream(xmlstream.Authenticator()) 
     1067        xs = xmlstream.XmlStream(xmlstream.Authenticator) 
    10761068        sm._connected(xs) 
    10771069        sm._authd(xs) 
    10781070        handler = DummyXMPPHandler() 
     
    10891081 
    10901082        The data should be sent directly over the XML stream. 
    10911083        """ 
    1092         factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator()) 
     1084        factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator) 
    10931085        sm = xmlstream.StreamManager(factory) 
    10941086        xs = factory.buildProtocol(None) 
    10951087        xs.transport = proto_helpers.StringTransport() 
     
    11091101        The data should be cached until an XML stream has been established and 
    11101102        initialized. 
    11111103        """ 
    1112         factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator()) 
     1104        factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator) 
    11131105        sm = xmlstream.StreamManager(factory) 
    11141106        handler = DummyXMPPHandler() 
    11151107        sm.addHandler(handler) 
     
    11391131 
    11401132        The data should be cached until the XML stream has been initialized. 
    11411133        """ 
    1142         factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator()) 
     1134        factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator) 
    11431135        sm = xmlstream.StreamManager(factory) 
    11441136        xs = factory.buildProtocol(None) 
    11451137        xs.transport = proto_helpers.StringTransport() 
     
    11591151        The data should be cached until a new XML stream has been established 
    11601152        and initialized. 
    11611153        """ 
    1162         factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator()) 
     1154        factory = xmlstream.XmlStreamFactory(xmlstream.Authenticator) 
    11631155        sm = xmlstream.StreamManager(factory) 
    11641156        handler = DummyXMPPHandler() 
    11651157        sm.addHandler(handler) 
  • twisted/words/test/test_xmlstream.py

    diff -r 32bd907eefae -r e255d835eef1 twisted/words/test/test_xmlstream.py
    a b  
    1 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. 
     1# Copyright (c) 2001-2008 Twisted Matrix Laboratories. 
    22# See LICENSE for details. 
    33 
    44""" 
     
    77 
    88from twisted.internet import defer, protocol 
    99from twisted.trial import unittest 
    10 from twisted.words.xish import utility, xmlstream 
     10from twisted.words.xish import domish, utility, xmlstream 
    1111 
    1212class XmlStreamTest(unittest.TestCase): 
    1313    def setUp(self): 
    14         self.errorOccurred = False 
    15         self.streamStarted = False 
    16         self.streamEnded = False 
    1714        self.outlist = [] 
    1815        self.xmlstream = xmlstream.XmlStream() 
    1916        self.xmlstream.transport = self 
    2017        self.xmlstream.transport.write = self.outlist.append 
    2118 
    22     # Auxilary methods 
     19 
    2320    def loseConnection(self): 
     21        """ 
     22        Stub loseConnection because we are a transport. 
     23        """ 
    2424        self.xmlstream.connectionLost("no reason") 
    2525 
    26     def streamStartEvent(self, rootelem): 
    27         self.streamStarted = True 
    2826 
    29     def streamErrorEvent(self, errelem): 
    30         self.errorOccurred = True 
    31  
    32     def streamEndEvent(self, _): 
    33         self.streamEnded = True 
    34  
    35     def testBasicOp(self): 
    36         xs = self.xmlstream 
    37         xs.addObserver(xmlstream.STREAM_START_EVENT, 
    38                        self.streamStartEvent) 
    39         xs.addObserver(xmlstream.STREAM_ERROR_EVENT, 
    40                        self.streamErrorEvent) 
    41         xs.addObserver(xmlstream.STREAM_END_EVENT, 
    42                        self.streamEndEvent) 
    43  
    44         # Go... 
    45         xs.connectionMade() 
    46         xs.send("<root>") 
     27    def test_send(self): 
     28        """ 
     29        Sending data should result into it being written to the transport. 
     30        """ 
     31        self.xmlstream.connectionMade() 
     32        self.xmlstream.send("<root>") 
    4733        self.assertEquals(self.outlist[0], "<root>") 
    4834 
    49         xs.dataReceived("<root>") 
    50         self.assertEquals(self.streamStarted, True) 
    5135 
    52         self.assertEquals(self.errorOccurred, False) 
    53         self.assertEquals(self.streamEnded, False) 
    54         xs.dataReceived("<child><unclosed></child>") 
    55         self.assertEquals(self.errorOccurred, True) 
    56         self.assertEquals(self.streamEnded, True) 
     36    def test_receiveRoot(self): 
     37        """ 
     38        Receiving the starttag of the root element results in stream start. 
     39        """ 
     40        streamStarted = [] 
     41 
     42        def streamStartEvent(rootelem): 
     43            streamStarted.append(None) 
     44 
     45        self.xmlstream.addObserver(xmlstream.STREAM_START_EVENT, 
     46                                   streamStartEvent) 
     47        self.xmlstream.connectionMade() 
     48        self.xmlstream.dataReceived("<root>") 
     49        self.assertEquals(1, len(streamStarted)) 
     50 
     51 
     52    def test_receiveBadXML(self): 
     53        """ 
     54        Receiving malformed XML should result in in error. 
     55        """ 
     56        streamError = [] 
     57        streamEnd = [] 
     58 
     59        def streamErrorEvent(reason): 
     60            streamError.append(reason) 
     61 
     62        def streamEndEvent(_): 
     63            streamEnd.append(None) 
     64 
     65        self.xmlstream.addObserver(xmlstream.STREAM_ERROR_EVENT, 
     66                                   streamErrorEvent) 
     67        self.xmlstream.addObserver(xmlstream.STREAM_END_EVENT, 
     68                                   streamEndEvent) 
     69        self.xmlstream.connectionMade() 
     70 
     71        self.xmlstream.dataReceived("<root>") 
     72        self.assertEquals(0, len(streamError)) 
     73        self.assertEquals(0, len(streamEnd)) 
     74 
     75        self.xmlstream.dataReceived("<child><unclosed></child>") 
     76        self.assertEquals(1, len(streamError)) 
     77        self.assertTrue(streamError[0].check(domish.ParserError)) 
     78        self.assertEquals(1, len(streamEnd)) 
     79 
    5780 
    5881 
    5982class DummyProtocol(protocol.Protocol, utility.EventDispatcher): 
  • twisted/words/xish/xmlstream.py

    diff -r 32bd907eefae -r e255d835eef1 twisted/words/xish/xmlstream.py
    a b  
    11# -*- test-case-name: twisted.words.test.test_xmlstream -*- 
    22# 
    3 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. 
     3# Copyright (c) 2001-2008 Twisted Matrix Laboratories. 
    44# See LICENSE for details. 
    55 
    66""" 
     
    1616Maintainer: Ralph Meijer 
    1717""" 
    1818 
     19from twisted.python import failure 
    1920from twisted.internet import protocol 
    2021from twisted.words.xish import domish, utility 
    2122 
     
    7374                self.rawDataInFn(data) 
    7475            self.stream.parse(data) 
    7576        except domish.ParserError: 
    76             self.dispatch(self, STREAM_ERROR_EVENT) 
     77            self.dispatch(failure.Failure(), STREAM_ERROR_EVENT) 
    7778            self.transport.loseConnection() 
    7879 
    7980    def connectionLost(self, reason):