Changeset 39:a9e354f69018


Ignore:
Timestamp:
Oct 11, 2008, 10:41:03 PM (13 years ago)
Author:
Ralph Meijer <ralphm@…>
Branch:
default
Convert:
svn:b33ecbfc-034c-dc11-8662-000475d9059e/trunk@106
Message:

Add Internal Component service that connects to a router in-process.

Author: ralphm.
Fixes #31.

Location:
wokkel
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • wokkel/component.py

    r35 r39  
    1515from twisted.words.xish import domish
    1616
     17from wokkel.generic import XmlPipe
    1718from wokkel.subprotocols import StreamManager
    1819
     
    6364    def _getConnection(self):
    6465        return reactor.connectTCP(self.host, self.port, self.factory)
     66
     67
     68
     69class InternalComponent(xmlstream.XMPPHandlerCollection, service.Service):
     70    """
     71    Component service that connects directly to a router.
     72
     73    Instead of opening a socket to connect to a router, like L{Component},
     74    components of this type connect to a router in the same process. This
     75    allows for one-process XMPP servers.
     76    """
     77
     78    def __init__(self, router, domain):
     79        xmlstream.XMPPHandlerCollection.__init__(self)
     80        self.router = router
     81        self.domain = domain
     82
     83        self.xmlstream = None
     84
     85    def startService(self):
     86        """
     87        Create a XML pipe, connect to the router and setup handlers.
     88        """
     89        service.Service.startService(self)
     90
     91        self.pipe = XmlPipe()
     92        self.xmlstream = self.pipe.source
     93        self.router.addRoute(self.domain, self.pipe.sink)
     94
     95        for e in self:
     96            e.makeConnection(self.xmlstream)
     97            e.connectionInitialized()
     98
     99
     100    def stopService(self):
     101        """
     102        Disconnect from the router and handlers.
     103        """
     104        service.Service.stopService(self)
     105
     106        self.router.removeRoute(self.domain, self.pipe.sink)
     107        self.pipe = None
     108        self.xmlstream = None
     109
     110        for e in self:
     111            e.connectionLost(None)
     112
     113
     114    def addHandler(self, handler):
     115        """
     116        Add a new handler and connect it to the stream.
     117        """
     118        xmlstream.XMPPHandlerCollection.addHandler(self, handler)
     119
     120        if self.xmlstream:
     121            handler.makeConnection(self.xmlstream)
     122            handler.connectionInitialized()
     123
     124
     125    def send(self, obj):
     126        """
     127        Send data to the XML stream, so it ends up at the router.
     128        """
     129        self.xmlstream.send(obj)
    65130
    66131
  • wokkel/test/test_component.py

    r35 r39  
    66"""
    77
     8from zope.interface.verify import verifyObject
     9
     10from twisted.internet import defer
    811from twisted.python import failure
    912from twisted.trial import unittest
    10 from twisted.words.protocols.jabber import xmlstream
     13from twisted.words.protocols.jabber import ijabber, xmlstream
    1114from twisted.words.protocols.jabber.jid import JID
    1215from twisted.words.xish import domish
     
    1417from wokkel import component
    1518from wokkel.generic import XmlPipe
     19
     20class InternalComponentTest(unittest.TestCase):
     21    """
     22    Tests for L{component.InternalComponent}.
     23    """
     24
     25    def setUp(self):
     26        self.router = component.RouterService()
     27        self.component = component.InternalComponent(self.router, 'component')
     28
     29
     30    def test_interface(self):
     31        """
     32        L{component.InternalComponent} implements
     33        L{ijabber.IXMPPHandlerCollection}.
     34        """
     35        verifyObject(ijabber.IXMPPHandlerCollection, self.component)
     36
     37
     38    def test_startService(self):
     39        """
     40        Starting the service creates a new route and hooks up handlers.
     41        """
     42
     43        events = []
     44
     45        class TestHandler(xmlstream.XMPPHandler):
     46
     47            def connectionInitialized(self):
     48                fn = lambda obj: events.append(obj)
     49                self.xmlstream.addObserver('//event/test', fn)
     50
     51        TestHandler().setHandlerParent(self.component)
     52
     53        self.assertFalse(self.component.running)
     54
     55        self.component.startService()
     56
     57        self.assertTrue(self.component.running)
     58        self.assertIn('component', self.router.routes)
     59
     60        self.assertEquals([], events)
     61        self.component.xmlstream.dispatch(None, '//event/test')
     62        self.assertEquals([None], events)
     63
     64
     65    def test_stopService(self):
     66        """
     67        Stopping the service removes the route and disconnects handlers.
     68        """
     69
     70        events = []
     71
     72        class TestHandler(xmlstream.XMPPHandler):
     73
     74            def connectionLost(self, reason):
     75                events.append(reason)
     76
     77        TestHandler().setHandlerParent(self.component)
     78
     79        self.component.startService()
     80        self.component.stopService()
     81
     82        self.assertFalse(self.component.running)
     83        self.assertEquals(1, len(events))
     84        self.assertNotIn('component', self.router.routes)
     85
     86
     87    def test_addHandler(self):
     88        """
     89        Adding a handler connects it to the stream.
     90        """
     91        events = []
     92
     93        class TestHandler(xmlstream.XMPPHandler):
     94
     95            def connectionInitialized(self):
     96                fn = lambda obj: events.append(obj)
     97                self.xmlstream.addObserver('//event/test', fn)
     98
     99        self.component.startService()
     100        self.component.xmlstream.dispatch(None, '//event/test')
     101        self.assertEquals([], events)
     102
     103        TestHandler().setHandlerParent(self.component)
     104        self.component.xmlstream.dispatch(None, '//event/test')
     105        self.assertEquals([None], events)
     106
     107
     108    def test_send(self):
     109        """
     110        A message sent from the component ends up at the router.
     111        """
     112        events = []
     113        fn = lambda obj: events.append(obj)
     114        message = domish.Element((None, 'message'))
     115
     116        self.component.startService()
     117        self.router.routes['component'].addObserver('/message', fn)
     118        self.component.send(message)
     119
     120        self.assertEquals([message], events)
     121
     122
    16123
    17124class RouterServiceTest(unittest.TestCase):
Note: See TracChangeset for help on using the changeset viewer.