source: ralphm-patches/session_manager.patch @ 57:0d8b6cf41728

Last change on this file since 57:0d8b6cf41728 was 57:0d8b6cf41728, checked in by Ralph Meijer <ralphm@…>, 9 years ago

Wokkel 0.7.0 release, clean up various patches.

File size: 4.4 KB
  • wokkel/client.py

    # HG changeset patch
    # Parent 4e25d6deb8beeb732cadb38349ee820f0dc98b3a
    
    diff -r 4e25d6deb8be wokkel/client.py
    a b  
    1313import base64
    1414
    1515from twisted.application import service
    16 from twisted.internet import reactor
    17 from twisted.python import log
     16from twisted.internet import defer, reactor
     17from twisted.python import log, randbytes
    1818from twisted.names.srvconnect import SRVConnector
    1919from twisted.words.protocols.jabber import client, error, sasl, xmlstream
    20 from twisted.words.xish import domish
     20from twisted.words.protocols.jabber.jid import JID, internJID
     21from twisted.words.xish import domish, utility
    2122
    2223from wokkel import generic
    2324from wokkel.compat import XmlStreamServerFactory
    24 from wokkel.subprotocols import StreamManager
     25from wokkel.subprotocols import StreamManager, XMPPHandler
    2526
    2627NS_CLIENT = 'jabber:client'
    2728
     
    443444        else:
    444445            raise RecipientUnavailable(u"There is no connection for %s" %
    445446                                       recipient.full())
     447
     448
     449class Session(object):
     450    def __init__(self, entity):
     451        self.entity = entity
     452        self.connected = False
     453        self.interested = False
     454        self.presence = None
     455
     456
     457
     458class SessionManager(XMPPHandler):
     459
     460    """
     461    Session Manager.
     462
     463    @ivar xmlstream: XML Stream to inject incoming stanzas from client
     464        connections into. Stanzas where the C{'to'} attribute is not set
     465        or is directed at the local domain are injected as if received on
     466        the XML Stream (using C{dispatch}), other stanzas are injected as if
     467        they were sent from the XML Stream (using C{send}).
     468    """
     469
     470    def __init__(self, domain, accounts):
     471        XMPPHandler.__init__(self)
     472        self.domain = domain
     473        self.accounts = accounts
     474
     475        self.connectionManager = None
     476        self.sessions = {}
     477        self.clientStream = utility.EventDispatcher()
     478        self.clientStream.addObserver('/*', self.routeOrDeliver, -1)
     479
     480
     481    def bindResource(self, localpart, domain, resource):
     482        if domain != self.domain:
     483            raise Exception("I don't host this domain!")
     484
     485        try:
     486            userSessions = self.sessions[localpart]
     487        except KeyError:
     488            userSessions = self.sessions[localpart] = {}
     489
     490        if resource is None:
     491            resource = randbytes.secureRandom(8).encode('hex')
     492        elif resource in self.userSessions:
     493            resource = resource + ' ' + randbytes.secureRandom(8).encode('hex')
     494
     495        entity = JID(tuple=(localpart, domain, resource))
     496        session = Session(entity)
     497        session.connected = True
     498        userSessions[resource] = session
     499
     500        return defer.succeed(entity)
     501
     502
     503    def unbindResource(self, localpart, domain, resource, reason=None):
     504        try:
     505            session = self.sessions[localpart][resource]
     506        except KeyError:
     507            pass
     508        else:
     509            session.connected = False
     510            del self.sessions[localpart][resource]
     511            if not self.sessions[localpart]:
     512                del self.sessions[localpart]
     513
     514        return defer.succeed(None)
     515
     516
     517    def onElement(self, element, sender):
     518        # Make sure each stanza has a sender address
     519        if (element.name == 'presence' and
     520            element.getAttribute('type') in ('subscribe', 'subscribed',
     521                                             'unsubscribe', 'unsubscribed')):
     522            element['from'] = sender.userhost()
     523        else:
     524            element['from'] = sender.full()
     525
     526        self.clientStream.dispatch(element)
     527
     528
     529    def routeOrDeliver(self, element):
     530        if element.handled:
     531            return
     532
     533        if (not element.hasAttribute('to') or
     534            internJID(element['to']).host == self.domain):
     535            # This stanza is for local delivery
     536            log.msg("Delivering locally: %r" % element.toXml())
     537            self.xmlstream.dispatch(element)
     538        else:
     539            # This stanza is for remote routing
     540            log.msg("Routing remotely: %r" % element.toXml())
     541            self.xmlstream.send(element)
     542
     543
     544    def deliverStanza(self, element, recipient):
     545        if self.connectionManager:
     546            self.connectionManager.deliverStanza(element, recipient)
     547        else:
     548            raise Exception("No connection manager set")
Note: See TracBrowser for help on using the repository browser.