Example #1
0
    def render_GET(self, request):
        log.debug("request from %s: %s" % (self.userid, request.args))
        if 'f' in request.args:
            fn = request.args['f'][0]
            info = self.fileserver.storage.get(fn, False)
            if info:
                filename, mime, md5sum = info
                log.debug("sending file type %s, path %s, md5sum %s" % (mime, filename, md5sum))
                genfilename = util.generate_filename(mime)
                request.setHeader('content-type', mime)
                request.setHeader('content-length', os.path.getsize(filename))
                request.setHeader('content-disposition', 'attachment; filename="%s"' % (genfilename))
                request.setHeader('x-md5sum', md5sum)

                # stream file to the client
                fp = open(filename, 'rb')
                d = FileSender().beginFileTransfer(fp, request)
                def finished(ignored):
                    fp.close()
                    request.finish()
                d.addErrback(log.error).addCallback(finished)
                return server.NOT_DONE_YET

            # file not found in extra storage
            else:
                return self._quick_response(request, 404, 'not found')

        return self._quick_response(request, 400, 'bad request')
Example #2
0
        def _presence(stanza, callback, timeout, buf):
            # presence probe error - finish here
            if stanza.getAttribute('type') == 'error':
                # TODO duplicated code
                self.xmlstream.removeObserver("/presence/group[@id='%s']" % (stanza['id'], ), _presence)
                self.xmlstream.removeObserver("/presence[@type='error'][@id='%s']" % (stanza['id'], ), _presence)
                if not callback.called:
                    # cancel timeout
                    timeout.cancel()
                    # fire deferred
                    callback.callback(buf)
                return

            sender = jid.JID(stanza['from'])
            log.debug("JID %s found!" % (sender.full(), ))
            stanza.consumed = True
            buf.append(sender)

            chain = stanza.group
            # end of presence chain!!!
            if not chain or int(chain['count']) == len(buf):
                # TODO duplicated code
                self.xmlstream.removeObserver("/presence/group[@id='%s']" % (stanza['id'], ), _presence)
                self.xmlstream.removeObserver("/presence[@type='error'][@id='%s']" % (stanza['id'], ), _presence)
                if not callback.called:
                    # cancel timeout
                    timeout.cancel()
                    # fire deferred
                    callback.callback(buf)
Example #3
0
    def initiateOutgoingStream(self, otherHost):
        """
        Initiate an outgoing XMPP server-to-server connection.
        """
        def resetConnecting(_):
            self._outgoingConnecting.remove(otherHost)

        def bounceError(_):
            resetConnecting(None)
            log.debug("unable to connect to remote server")

        if otherHost in self._outgoingConnecting:
            log.debug("pending connection found to %s - aborting" % otherHost)
            return

        log.debug("connecting to %s" % otherHost)
        authenticator = XMPPNetConnectAuthenticator(self.defaultDomain,
                                                    otherHost, self.keyring)
        factory = server.DeferredS2SClientFactory(authenticator)
        factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT,
                             self.outgoingInitialized)
        factory.logTraffic = self.logTraffic

        self._outgoingConnecting.add(otherHost)

        d = initiateNet(factory, self.credentials)
        d.addCallback(resetConnecting)
        d.addErrback(bounceError)
        return d
Example #4
0
    def bind(self, stanza, xs):
        log.debug("binding component %s" % (stanza.toXml().encode('utf-8'), ))
        stanza.consumed = True

        if stanza.default:
            route = None
        else:
            try:
                route = stanza['name']
            except:
                xs.send(
                    domish.Element((None, 'bind'),
                                   attribs={'error': 'bad-request'}))
                xs.transport.loseConnection()

        if route not in self.routes:
            self.routes[route] = xs
            xs.send(domish.Element((None, 'bind')))

            if stanza.log:
                self.logs.add(xs)
        else:
            xs.send(
                domish.Element((None, 'bind'), attribs={'error': 'conflict'}))
            xs.transport.loseConnection()
Example #5
0
    def onConnectionLost(self, xs, reason):
        thisHost = xs.thisEntity.host
        otherHost = xs.otherEntity.host

        log.debug("Incoming connection %d from %s to %s disconnected" %
                  (xs.serial, otherHost, thisHost))
        self.service.invalidateConnection(xs)
Example #6
0
    def render_GET(self, request):
        log.debug("request from %s: %s" % (self.userid, request.args))
        if "f" in request.args:
            fn = request.args["f"][0]
            info = self.fileserver.storage.get(fn, False)
            if info:
                filename, mime, md5sum = info
                log.debug("sending file type %s, path %s, md5sum %s" % (mime, filename, md5sum))
                genfilename = util.generate_filename(mime)
                request.setHeader("content-type", mime)
                request.setHeader("content-length", os.path.getsize(filename))
                request.setHeader("content-disposition", 'attachment; filename="%s"' % (genfilename))
                request.setHeader("x-md5sum", md5sum)

                # stream file to the client
                fp = open(filename, "rb")
                d = FileSender().beginFileTransfer(fp, request)

                def finished(ignored):
                    fp.close()
                    request.finish()

                d.addErrback(log.error).addCallback(finished)
                return server.NOT_DONE_YET

            # file not found in extra storage
            else:
                return self._quick_response(request, 404, "not found")

        return self._quick_response(request, 400, "bad request")
Example #7
0
    def onSubscribed(self, stanza):
        if stanza.consumed:
            return

        log.debug("user %s accepted subscription by %s" %
                  (self.xmlstream.otherEntity, stanza['to']))
        stanza.consumed = True
        jid_to = jid.JID(stanza['to'])

        jid_from = self.xmlstream.otherEntity.userhostJID()

        # add "to" user to whitelist of "from" user
        self.parent.router.add_whitelist(jid_from, jid_to)

        log.debug("SUBSCRIPTION SUCCESSFUL")

        if self.parent.router.cache.jid_available(jid_from):
            # send subscription accepted immediately and subscribe
            # TODO this is wrong, but do it for the moment until we find a way to handle this case
            self.parent.router.doSubscribe(jid_from,
                                           jid_to,
                                           stanza.getAttribute('id'),
                                           response_only=False)

            # blindly try to deliver offline storage
            # this will process any pending message
            self.parent.router.deliver_offline_storage(jid_from)
Example #8
0
 def error(self, stanza, condition='service-unavailable', errtype='cancel', text=None):
     if not stanza.consumed:
         log.debug("error %s" % (stanza.toXml(), ))
         stanza.consumed = True
         util.resetNamespace(stanza, self.namespace)
         e = error.StanzaError(condition, errtype, text)
         self.send(e.toResponse(stanza), True)
Example #9
0
    def onVCardSet(self, stanza, sender=None):
        """
        Handle vCards set IQs.
        This simply takes care of importing the key in the keyring for future
        signature verification. Actual key verification is done by c2s when
        accepting vCards coming from clients.
        WARNING/1 does this mean that we bindly accept keys from components? --
         YES blindly :P c2s will filter invalid requests
        WARNING/2 importing the key means that keys coming from local c2s are
        imported twice because the keyring is the same. Unless we want to make
        a separated keyring only for resolver? -- YES USING .gnupg-cache
        """
        # TODO parse vcard for interesting sections

        if stanza.vcard.key is not None:
            # we do this because of the uri member in domish.Element
            keydata = stanza.vcard.key.firstChildElement()
            if keydata.name == 'uri':
                keydata = str(keydata)

                if keydata.startswith(xmlstream2.DATA_PGP_PREFIX):
                    keydata = base64.b64decode(keydata[len(xmlstream2.DATA_PGP_PREFIX):])
                    # import into cache keyring
                    userid = util.jid_user(stanza['from'])
                    # this chould take a lot of time (up to 500ms)
                    if self.parent.keyring.check_user_key(keydata, userid):
                        log.debug("key cached successfully")
                    else:
                        log.warn("invalid key")
Example #10
0
    def register(self, stanza):
        """This is actually used for key regeneration."""
        log.debug("client requested key regeneration: %s" % (stanza.toXml(), ))
        stanza.consumed = True
        fields = stanza.query.x.elements(uri='jabber:x:data', name='field')
        var_pkey = None
        var_revoked = None

        for f in fields:
            if f['var'] == 'publickey':
                var_pkey = f
            elif f['var'] == 'revoked':
                var_revoked = f

        # FIXME maybe some stuff here should go to c2s?

        if var_pkey:
            userid = self.parent.xmlstream.otherEntity.user

            # check if user has already a key
            # this is used for users coming from version 2.x (no key back then)
            d = self.parent.router.presencedb.get(userid)
            d.addCallback(self._register_continue, userid, var_pkey,
                          var_revoked, stanza)

        else:
            # bad request
            stanza.consumed = False
            self.parent.error(stanza, 'bad-request')
Example #11
0
    def send_user_presence(self, gid, sender, recipient):
        stub = self.lookup(recipient)
        log.debug("onProbe(%s): found %r" % (gid, stub, ))
        if stub:
            data = stub.presence()
            i = len(data)
            for x in data:
                presence = deepcopy(x)
                presence.consumed = True
                presence['to'] = sender.full()

                try:
                    # add fingerprint
                    fpr = self.parent.keyring.get_fingerprint(recipient.user)
                    if fpr:
                        pubkey = presence.addElement(('urn:xmpp:pubkey:2', 'pubkey'))
                        fprint = pubkey.addElement((None, 'print'))
                        fprint.addContent(fpr)
                except keyring.KeyNotFoundException:
                    log.warn("key not found for user %s" % (recipient, ))

                if gid:
                    # FIXME this will duplicate group elements - actually in storage there should be no group element!!!
                    group = presence.addElement((xmlstream2.NS_XMPP_STANZA_GROUP, 'group'))
                    group['id'] = gid
                    group['count'] = str(i)
                    i -= 1

                self.send(presence)
                return True

        # no such user
        return False
Example #12
0
 def _abort(stanzaId, callback, data):
     log.debug("iq/last broadcast request timed out!")
     self.xmlstream.removeObserver(
         "/iq[@id='%s']" % stanza['id'], find_latest)
     if not callback.called:
         #callback.errback(failure.Failure(internet_error.TimeoutError()))
         callback.callback(data['latest'])
Example #13
0
    def onProbe(self, stanza):
        """Handle presence probes."""

        if stanza.consumed:
            return

        log.debug("probe request: %s" % (stanza.toXml(), ))
        stanza.consumed = True
        to = jid.JID(stanza['to'])
        sender = jid.JID(stanza['from'])

        # are we probing a user we have blocked?
        if self.parent.is_presence_allowed(to, sender) == -1:
            log.debug("probing blocked user, bouncing error")
            e = error.StanzaError('not-acceptable', 'cancel')
            errstanza = e.toResponse(stanza)
            errstanza.error.addElement((xmlstream2.NS_IQ_BLOCKING_ERRORS, 'blocked'))
            self.send(errstanza)

        elif self.parent.is_presence_allowed(sender, to) == 1:
            gid = stanza.getAttribute('id')
            if not self.send_user_presence(gid, sender, to):
                response = xmlstream.toResponse(stanza, 'error')
                # TODO include error cause?
                self.send(response)
Example #14
0
    def send(self, stanza):
        """
        Send stanza to the proper XML Stream.

        This uses addressing embedded in the stanza to find the correct stream
        to forward the stanza to.
        """

        otherHost = jid.internJID(stanza["to"]).host
        stanzaFrom = jid.JID(stanza['from'])

        if stanzaFrom.host != self.defaultDomain:
            stanzaFrom.host = self.defaultDomain
            stanza['origin'] = stanza['from']
            stanza['from'] = stanzaFrom.full()

        log.debug("sending data to %s [%r]" % (otherHost, self._outgoingStreams, ))
        if otherHost not in self._outgoingStreams:
            # There is no connection with the destination (yet). Cache the
            # outgoing stanza until the connection has been established.
            # XXX: If the connection cannot be established, the queue should
            #      be emptied at some point.
            if otherHost not in self._outgoingQueues:
                self._outgoingQueues[otherHost] = []
            self._outgoingQueues[otherHost].append(stanza)
            self.initiateOutgoingStream(otherHost)
        else:
            self._outgoingStreams[otherHost].send(stanza)
Example #15
0
 def onPresenceUnavailable(self, xs, stanza):
     # if component (i.e. no user part of JID) unbind name from router
     stanzaFrom = jid.internJID(stanza['from'])
     if not stanzaFrom.user and stanzaFrom.host.endswith(xs.otherEntity.full()):
         stanza.handled = True
         log.debug("unbinding name %s" % (stanzaFrom.host, ))
         self.router.unbind(stanzaFrom.host)
Example #16
0
 def check_conflict(self, _jid):
     """Checks for local conflict and disconnects the conflicting local resource."""
     if _jid.user and _jid.host in self.router.keyring.hostlist():
         if _jid.user in self.streams and _jid.resource in self.streams[
                 _jid.user]:
             log.debug("network resource conflict for %s" % (_jid.full(), ))
             self.streams[_jid.user][_jid.resource].conflict()
Example #17
0
    def last_activity(self, stanza):
        log.debug("local last activity request: %s" % (stanza.toXml(), ))
        stanza.consumed = True

        def _db(presence, stanza):
            log.debug("iq/last: presence=%r" % (presence, ))
            if type(presence) == list and len(presence) > 0:
                user = presence[0]

                response = xmlstream.toResponse(stanza, 'result')
                response_from = util.userid_to_jid(user['userid'], self.xmlstream.thisEntity.host)
                response['from'] = response_from.userhost()

                query = response.addElement((xmlstream2.NS_IQ_LAST, 'query'))
                if self.parent.sfactory.client_connected(response_from):
                    query['seconds'] = '0'
                else:
                    latest = None
                    for user in presence:
                        if latest is None or latest['timestamp'] > user['timestamp']:
                            latest = user
                    # TODO timediff from latest
                    #log.debug("max timestamp: %r" % (max, ))
                    query['seconds'] = '123456'

                self.send(response)
                log.debug("iq/last result sent: %s" % (response.toXml().encode('utf-8'), ))

            else:
                # TODO return error?
                log.debug("iq/last: user not found")

        userid = util.jid_user(stanza['to'])
        d = self.parent.presencedb.get(userid)
        d.addCallback(_db, stanza)
Example #18
0
    def initiateOutgoingStream(self, otherHost):
        """
        Initiate an outgoing XMPP server-to-server connection.
        """

        def resetConnecting(_):
            self._outgoingConnecting.remove(otherHost)

        def bounceError(_):
            resetConnecting(None)
            log.debug("unable to connect to remote server")

        if otherHost in self._outgoingConnecting:
            log.debug("pending connection found to %s - aborting" % otherHost)
            return

        log.debug("connecting to %s" % otherHost)
        authenticator = XMPPNetConnectAuthenticator(self.defaultDomain, otherHost, self.keyring)
        factory = server.DeferredS2SClientFactory(authenticator)
        factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT,
                             self.outgoingInitialized)
        factory.logTraffic = self.logTraffic

        self._outgoingConnecting.add(otherHost)

        d = initiateNet(factory, self.credentials)
        d.addCallback(resetConnecting)
        d.addErrback(bounceError)
        return d
Example #19
0
    def onConnectionLost(self, xs, reason):
        thisHost = xs.thisEntity.host
        otherHost = xs.otherEntity.host

        log.debug("Incoming connection %d from %s to %s disconnected" %
                (xs.serial, otherHost, thisHost))
        self.service.invalidateConnection(xs)
Example #20
0
    def handle(self, stanza):
        # enforce sender
        stanza['from'] = self.resolveJID(self.xmlstream.otherEntity).full()

        to = stanza.getAttribute('to')
        if to is not None:
            try:
                to = jid.JID(to)
            except:
                # invalid destination, consume stanza and return error
                stanza.consumed = True
                log.debug("invalid address: %s" % (to, ))
                e = error.StanzaError('jid-malformed', 'modify')
                self.send(e.toResponse(stanza))
                return

            # stanza is for us
            if to.host == self.network:
                # sending to full JID, forward to router
                if to.user is not None and to.resource is not None:
                    self.forward(stanza)

            # stanza is not intended to component either
            elif to.host != util.component_jid(self.servername,
                                               util.COMPONENT_C2S):
                self.forward(stanza)
Example #21
0
    def outgoingInitialized(self, xs):
        thisHost = xs.thisEntity.host
        otherHost = xs.otherEntity.host

        log.debug("Outgoing connection %d from %s to %s established" %
                (xs.serial, thisHost, otherHost))

        self._outgoingStreams[otherHost] = xs
        xs.addObserver(xmlstream.STREAM_END_EVENT,
                       lambda _: self.outgoingDisconnected(xs))
        xs.addObserver('/*', self.onElement, 0, xs)

        """
        Here we introduce ourselves to remote c2s, so it will reply with
        all presence. We are faking resolver identity using 'origin' so the
        reply will go directly to it.
        """
        p = domish.Element((None, 'presence'))
        p['from'] = self.defaultDomain
        # TRANSLATED BY OBSERVER p['origin'] = self.network
        p['to'] = otherHost
        xs.send(p)

        if otherHost in self._outgoingQueues:
            for element in self._outgoingQueues[otherHost]:
                xs.send(element)
            del self._outgoingQueues[otherHost]
Example #22
0
    def message(self, stanza):
        if not stanza.consumed:
            jid_from = self.parent.resolveJID(self.xmlstream.otherEntity)
            stanza["from"] = jid_from.full()

            # no destination - use sender bare JID
            if not stanza.hasAttribute("to"):
                jid_to = jid_from
                stanza["to"] = jid_to.userhost()
            else:
                jid_to = jid.JID(stanza["to"])

            # are we sending a message to a user we have blocked?
            if self.parent.router.is_presence_allowed(jid_to, jid_from) == -1:
                log.debug("sending message to blocked user, bouncing error")
                e = error.StanzaError("not-acceptable", "cancel")
                errstanza = e.toResponse(stanza)
                errstanza.error.addElement((xmlstream2.NS_IQ_BLOCKING_ERRORS, "blocked"))
                self.parent.send(errstanza)

            else:

                # check for permission
                allowed = self.parent.router.is_presence_allowed(jid_from, jid_to)
                if allowed == -1:
                    # user is blocked!
                    log.debug("not allowed to send messages, sending fake response to %s" % (stanza["from"],))
                    if stanza.getAttribute("type") == "chat" and xmlstream2.extract_receipt(stanza, "request"):
                        self.send_fake_receipt(stanza)
                else:
                    # send to c2s hub (without implicitly consuming)
                    self.parent.router.send(stanza, force_delivery=True, hold=(allowed != 1))

            # we have now consumed the stanza
            stanza.consumed = True
Example #23
0
    def register(self, stanza):
        """This is actually used for key regeneration."""
        log.debug("client requested key regeneration: %s" % (stanza.toXml(),))
        stanza.consumed = True
        fields = stanza.query.x.elements(uri="jabber:x:data", name="field")
        var_pkey = None
        var_revoked = None

        for f in fields:
            if f["var"] == "publickey":
                var_pkey = f
            elif f["var"] == "revoked":
                var_revoked = f

        # FIXME maybe some stuff here should go to c2s?

        if var_pkey:
            userid = self.parent.xmlstream.otherEntity.user

            # check if user has already a key
            # this is used for users coming from version 2.x (no key back then)
            d = self.parent.router.presencedb.get(userid)
            d.addCallback(self._register_continue, userid, var_pkey, var_revoked, stanza)

        else:
            # bad request
            stanza.consumed = False
            self.parent.error(stanza, "bad-request")
Example #24
0
 def error(self, stanza, condition='service-unavailable', errtype='cancel', text=None):
     if not stanza.consumed:
         log.debug("error %s" % (stanza.toXml(), ))
         stanza.consumed = True
         util.resetNamespace(stanza, self.namespace)
         e = error.StanzaError(condition, errtype, text)
         self.send(e.toResponse(stanza), True)
Example #25
0
 def onPresenceUnavailable(self, xs, stanza):
     # if component (i.e. no user part of JID) unbind name from router
     stanzaFrom = jid.internJID(stanza['from'])
     if not stanzaFrom.user and stanzaFrom.host.endswith(
             xs.otherEntity.full()):
         stanza.handled = True
         log.debug("unbinding name %s" % (stanzaFrom.host, ))
         self.router.unbind(stanzaFrom.host)
Example #26
0
 def push_regid(self, stanza):
     for child in stanza.children:
         if child.name == 'c' and child.uri == xmlstream2.NS_PRESENCE_PUSH:
             regid = str(child)
             provider = child.getAttribute('provider')
             if regid and provider:
                 log.debug("registering %s using %s with %s" % (self.xmlstream.otherEntity, provider, regid))
                 self.parent.router.push_manager.register(self.xmlstream.otherEntity, provider, regid)
Example #27
0
    def outgoingDisconnected(self, xs):
        thisHost = xs.thisEntity.host
        otherHost = xs.otherEntity.host

        log.debug("Outgoing connection %d from %r to %r disconnected" %
                (xs.serial, thisHost, otherHost))

        del self._outgoingStreams[thisHost, otherHost]
Example #28
0
    def outgoingDisconnected(self, xs):
        thisHost = xs.thisEntity.host
        otherHost = xs.otherEntity.host

        log.debug("Outgoing connection %d from %r to %r disconnected" %
                  (xs.serial, thisHost, otherHost))

        del self._outgoingStreams[thisHost, otherHost]
Example #29
0
 def push_regid(self, stanza):
     for child in stanza.children:
         if child.name == 'c' and child.uri == xmlstream2.NS_PRESENCE_PUSH:
             regid = str(child)
             provider = child.getAttribute('provider')
             if regid and provider:
                 log.debug("registering %s using %s with %s" % (self.xmlstream.otherEntity, provider, regid))
                 self.parent.router.push_manager.register(self.xmlstream.otherEntity, provider, regid)
Example #30
0
    def _local_presence_output(self, data, user):
        log.debug("data: %r" % (data, ))
        # this will be used to set a safe recipient
        # WARNING this will create a JID anyway :(
        jid_to = self.resolveJID(user)
        for msg in data:
            log.debug("msg[%s]=%s" % (msg['id'], msg['stanza'].toXml().encode('utf-8'), ))
            stanza = msg['stanza']
            try:
                """
                Mark the stanza with our server name, so we'll receive a
                copy of the receipt
                """
                if stanza.request:
                    stanza.request['from'] = self.xmlstream.thisEntity.full()
                elif stanza.received:
                    stanza.received['from'] = self.xmlstream.thisEntity.full()

                # mark delayed delivery
                if 'timestamp' in msg:
                    delay = stanza.addElement((xmlstream2.NS_XMPP_DELAY, 'delay'))
                    delay['stamp'] = msg['timestamp'].strftime(xmlstream2.XMPP_STAMP_FORMAT)

                # are we sending a message to a user we have blocked?
                jid_from = jid.JID(stanza['from'])
                if self.is_presence_allowed(jid_to, jid_from) == -1:
                    log.debug("sending message to blocked user, bouncing error")
                    e = error.StanzaError('not-acceptable', 'cancel')
                    errstanza = e.toResponse(msg['stanza'])
                    errstanza.error.addElement((xmlstream2.NS_IQ_BLOCKING_ERRORS, 'blocked'))
                    self.send(errstanza)

                else:
                    # check for permission
                    allowed = self.is_presence_allowed(jid_from, jid_to)
                    if allowed == -1:
                        # user is blocked!
                        log.debug("not allowed to send messages to %s, discarding message" % (stanza['to'], ))
                        self.message_offline_delete(msg['id'], stanza.name)
                    else:
                        """
                        We use direct delivery here: it's faster and does not
                        involve JID resolution
                        """
                        stanza['to'] = jid_to.full()
                        self.dispatch(stanza, hold=(allowed != 1))

                """
                If a receipt is requested, we won't delete the message from
                storage now; we must be sure client has received it.
                Otherwise just delete the message immediately.
                """
                if not xmlstream2.extract_receipt(stanza, 'request') and \
                        not xmlstream2.extract_receipt(stanza, 'received'):
                    self.message_offline_delete(msg['id'], stanza.name)
            except:
                log.debug("offline message delivery failed (%s)" % (msg['id'], ))
                traceback.print_exc()
Example #31
0
 def _error(failure):
     log.debug("error: %s" % (failure, ))
     if isinstance(failure.value, RuntimeError):
         e = error.StanzaError('bad-request', 'modify', failure.getErrorMessage())
     else:
         e = error.StanzaError('service-unavailable', 'cancel', failure.getErrorMessage())
     iq = xmlstream.toResponse(stanza, 'error')
     iq.addChild(e.getElement())
     manager.send(iq, True)
Example #32
0
    def _presence_data(self, presence):
        log.debug("presence: %r" % (presence, ))
        if type(presence) == list and len(presence) > 0:

            for user in presence:
                # store fingerprint
                self.keyring.set_fingerprint(user['userid'],
                                             user['fingerprint'])

                host = util.component_jid(self.servername, util.COMPONENT_C2S)
                response_from = jid.JID(tuple=(user['userid'], host,
                                               None)).full()

                num_avail = 0
                try:
                    streams = self.sfactory.streams[user['userid']]
                    for x in streams.itervalues():
                        presence = x._presence
                        if presence and not presence.hasAttribute('type'):
                            self.cache.user_available(presence)

                            if self.logTraffic:
                                log.debug("local presence: %s" %
                                          (presence.toXml().encode('utf-8'), ))
                            else:
                                log.debug("local presence: %s" %
                                          (presence['from'], ))

                            num_avail += 1
                except KeyError:
                    pass

                # no available resources - send unavailable presence
                if not num_avail:
                    response = domish.Element((None, 'presence'))
                    response['from'] = response_from

                    if user['status'] is not None:
                        response.addElement((None, 'status'),
                                            content=user['status'])
                    if user['show'] is not None:
                        response.addElement((None, 'show'),
                                            content=user['show'])

                    response['type'] = 'unavailable'
                    delay = domish.Element(('urn:xmpp:delay', 'delay'))
                    delay['stamp'] = user['timestamp'].strftime(
                        xmlstream2.XMPP_STAMP_FORMAT)
                    response.addChild(delay)

                    self.cache.user_unavailable(response)

                    if self.logTraffic:
                        log.debug("local presence: %s" %
                                  (response.toXml().encode('utf-8'), ))
                    else:
                        log.debug("local presence: %s" % (response['from'], ))
Example #33
0
 def _error(failure):
     log.debug("error: %s" % (failure, ))
     if isinstance(failure.value, RuntimeError):
         e = error.StanzaError('bad-request', 'modify', failure.getErrorMessage())
     else:
         e = error.StanzaError('service-unavailable', 'cancel', failure.getErrorMessage())
     iq = xmlstream.toResponse(stanza, 'error')
     iq.addChild(e.getElement())
     manager.send(iq, True)
Example #34
0
        def _bind(stanza, name):
            if not stanza.hasAttribute('error'):
                # no errors, register route
                unused, host = util.jid_component(name)

                if host not in self.routes:
                    self.routes[host] = []

                self.routes[host].append(name)
                log.debug("ROUTES: %s" % (self.routes, ))
Example #35
0
    def _authd(self, xs):
        component.Component._authd(self, xs)
        log.debug("connected to router.")
        self.xmlstream.addObserver("/presence", self.dispatch, ignore_consumed=False)
        self.xmlstream.addObserver("/iq", self.iq, 50)
        self.xmlstream.addObserver("/iq", self.dispatch, ignore_consumed=False)
        # <message/> has its own handler

        # resolver stuff
        resolver.ResolverMixIn._authd(self, xs)
Example #36
0
    def bounce(self, stanza):
        """Bounce stanzas as results."""
        if not stanza.consumed:
            util.resetNamespace(stanza, self.namespace)

            if self.router.logTraffic:
                log.debug("bouncing %s" % (stanza.toXml(), ))

            stanza.consumed = True
            self.send(xmlstream.toResponse(stanza, 'result'))
Example #37
0
    def connectionInitialized(self, xs):
        """Called from the handler when a client has authenticated."""
        userid, resource = util.jid_to_userid(xs.otherEntity, True)
        if userid not in self.streams:
            self.streams[userid] = {}

        if resource in self.streams[userid]:
            log.debug("resource conflict for %s" % (xs.otherEntity, ))
            self.streams[userid][resource].conflict()
        self.streams[userid][resource] = xs.manager
Example #38
0
    def dispatch(self, stanza):
        """Incoming message from router."""
        if not stanza.consumed:
            if self.parent.logTraffic:
                log.debug("incoming message: %s" % (stanza.toXml().encode('utf-8')))

            stanza.consumed = True

            util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)
            self.parent.process_message(stanza)
Example #39
0
    def connectionInitialized(self, xs):
        """Called from the handler when a client has authenticated."""
        userid, resource = util.jid_to_userid(xs.otherEntity, True)
        if userid not in self.streams:
            self.streams[userid] = {}

        if resource in self.streams[userid]:
            log.debug("resource conflict for %s" % (xs.otherEntity, ))
            self.streams[userid][resource].conflict()
        self.streams[userid][resource] = xs.manager
Example #40
0
        def _bind(stanza, name):
            if not stanza.hasAttribute('error'):
                # no errors, register route
                unused, host = util.jid_component(name)

                if host not in self.routes:
                    self.routes[host] = []

                self.routes[host].append(name)
                log.debug("ROUTES: %s" % (self.routes, ))
Example #41
0
    def bounce(self, stanza):
        """Bounce stanzas as results."""
        if not stanza.consumed:
            util.resetNamespace(stanza, self.namespace)

            if self.router.logTraffic:
                log.debug("bouncing %s" % (stanza.toXml(), ))

            stanza.consumed = True
            self.send(xmlstream.toResponse(stanza, 'result'))
Example #42
0
    def _authd(self, xs):
        component.Component._authd(self, xs)
        log.debug("connected to router")
        xs.addObserver("/iq", self.iq, 500)
        xs.addObserver("/presence", self.presence, 500)

        # bind to network route
        bind = domish.Element((None, 'bind'))
        bind['name'] = self.network
        bind.addElement((None, 'private'))
        xs.send(bind)
Example #43
0
            def _error(failure, stanza):
                log.debug("error: %s" % (failure, ))
                if isinstance(failure.value, oursql.IntegrityError):
                    # duplicate key of userid: throttling
                    e = error.StanzaError('service-unavailable', 'wait', 'Too many attempts.')
                else:
                    e = error.StanzaError('service-unavailable', 'cancel', failure.getErrorMessage())

                iq = xmlstream.toResponse(stanza, 'error')
                iq.addChild(e.getElement())
                manager.send(iq, True)
Example #44
0
    def onPresenceAvailable(self, stanza):
        """Handle availability presence stanzas."""
        if self.parent.logTraffic:
            log.debug("presence: %s" % (stanza.toXml().encode('utf-8'), ))
        else:
            log.debug("presence available from %s" % (stanza['from'], ))

        # update usercache with last seen and status
        user = jid.JID(stanza['from'])
        if user.user:
            self.user_available(stanza)
Example #45
0
    def upload(self, stanza):
        node = stanza.upload.getAttribute('node')
        log.debug("upload request received: %s" % (node, ))
        if node and node in self.serv_handlers:
            try:
                return self.serv_handlers[node].upload(stanza)
            except:
                import traceback
                traceback.print_exc()

        self.parent.error(stanza)
Example #46
0
            def _error(failure, stanza):
                log.debug("error: %s" % (failure, ))
                if isinstance(failure.value, oursql.IntegrityError):
                    # duplicate key of userid: throttling
                    e = error.StanzaError('service-unavailable', 'wait', 'Too many attempts.')
                else:
                    e = error.StanzaError('service-unavailable', 'cancel', failure.getErrorMessage())

                iq = xmlstream.toResponse(stanza, 'error')
                iq.addChild(e.getElement())
                manager.send(iq, True)
Example #47
0
    def dispatch(self, stanza):
        """Incoming message from router."""
        if not stanza.consumed:
            if self.parent.logTraffic:
                log.debug("incoming message: %s" %
                          (stanza.toXml().encode('utf-8')))

            stanza.consumed = True

            util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)
            self.parent.process_message(stanza)
Example #48
0
    def outgoingDisconnected(self, xs):
        thisHost = xs.thisEntity.host
        otherHost = xs.otherEntity.host

        log.debug("Outgoing connection %d from %s to %s disconnected" %
                (xs.serial, thisHost, otherHost))

        # TODO this actually does the same as invalidateConnection
        del self._outgoingStreams[otherHost]

        self.router.serverDisconnected(otherHost)
Example #49
0
    def upload(self, stanza):
        node = stanza.upload.getAttribute('node')
        log.debug("upload request received: %s" % (node, ))
        if node and node in self.serv_handlers:
            try:
                return self.serv_handlers[node].upload(stanza)
            except:
                import traceback
                traceback.print_exc()

        self.parent.error(stanza)
Example #50
0
    def _authd(self, xs):
        component.Component._authd(self, xs)
        log.debug("connected to router")
        xs.addObserver("/iq", self.iq, 500)
        xs.addObserver("/presence", self.presence, 500)

        # bind to network route
        bind = domish.Element((None, 'bind'))
        bind['name'] = self.network
        bind.addElement((None, 'private'))
        xs.send(bind)
Example #51
0
    def outgoingDisconnected(self, xs):
        thisHost = xs.thisEntity.host
        otherHost = xs.otherEntity.host

        log.debug("Outgoing connection %d from %s to %s disconnected" %
                  (xs.serial, thisHost, otherHost))

        # TODO this actually does the same as invalidateConnection
        del self._outgoingStreams[otherHost]

        self.router.serverDisconnected(otherHost)
Example #52
0
 def broadcast(self, stanza, same=False):
     """
     Broadcast a stanza to every component.
     This alters the to attribute in outgoing stanza for each component.
     """
     from_host = util.jid_host(stanza['from'])
     for host, xs in self.routes.iteritems():
         # do not send to the original sender
         if host is not None and (host != from_host or same):
             log.debug("sending to %s" % (host, ))
             stanza['to'] = host
             xs.send(stanza)
Example #53
0
 def broadcast(self, stanza, same=False):
     """
     Broadcast a stanza to every component.
     This alters the to attribute in outgoing stanza for each component.
     """
     from_host = util.jid_host(stanza['from'])
     for host, xs in self.routes.iteritems():
         # do not send to the original sender
         if host is not None and (host != from_host or same):
             log.debug("sending to %s" % (host, ))
             stanza['to'] = host
             xs.send(stanza)
Example #54
0
    def _authd(self, xs):
        component.Component._authd(self, xs)
        log.debug("connected to router.")
        self.xmlstream.addObserver("/presence",
                                   self.dispatch,
                                   ignore_consumed=False)
        self.xmlstream.addObserver("/iq", self.iq, 50)
        self.xmlstream.addObserver("/iq", self.dispatch, ignore_consumed=False)
        # <message/> has its own handler

        # resolver stuff
        resolver.ResolverMixIn._authd(self, xs)
Example #55
0
    def dispatch(self, stanza):
        """Handle incoming stanza from router to the proper server stream."""
        if not stanza.consumed:
            stanza.consumed = True
            log.debug("incoming stanza from router %s" % (stanza.toXml().encode('utf-8'), ))
            to = stanza.getAttribute('to')

            if to is not None:
                to = jid.JID(to)
                if to.host != self.xmlstream.thisEntity.host:
                    util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)
                    self.service.send(stanza)