Example #1
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 #2
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 #3
0
    def dispatch(self, xs, stanza):
        """
        Send a stanza to the router, checking some stuff first.
        """

        log.debug("stanza from %s: %s" % (xs.otherEntity.full(), stanza.toXml()))
        util.resetNamespace(stanza, xs.namespace)
        stanzaFrom = stanza.getAttribute('from')
        stanzaTo = stanza.getAttribute('to')

        if not stanza.bind and not stanzaFrom or not stanzaTo:
            xs.sendStreamError(error.StreamError('improper-addressing'))
        else:
            try:
                sender = jid.internJID(stanzaFrom)
                jid.internJID(stanzaTo)
            except jid.InvalidFormat:
                log.debug("dropping stanza with malformed JID")

            log.debug("sender = %s, otherEntity = %s" % (sender.full(), xs.otherEntity.full()))

            try:
                unused, host = util.jid_component(sender.host)
                if host in self.keyring.hostlist():
                    self.router.send(stanza)
                else:
                    raise Exception()
            except:
                xs.sendStreamError(error.StreamError('invalid-from'))
Example #4
0
    def dispatch(self, xs, stanza):
        """
        Send a stanza to the router, checking some stuff first.
        """

        log.debug("stanza from %s: %s" %
                  (xs.otherEntity.full(), stanza.toXml()))
        util.resetNamespace(stanza, xs.namespace)
        stanzaFrom = stanza.getAttribute('from')
        stanzaTo = stanza.getAttribute('to')

        if not stanza.bind and not stanzaFrom or not stanzaTo:
            xs.sendStreamError(error.StreamError('improper-addressing'))
        else:
            try:
                sender = jid.internJID(stanzaFrom)
                jid.internJID(stanzaTo)
            except jid.InvalidFormat:
                log.debug("dropping stanza with malformed JID")

            log.debug("sender = %s, otherEntity = %s" %
                      (sender.full(), xs.otherEntity.full()))

            try:
                unused, host = util.jid_component(sender.host)
                if host in self.keyring.hostlist():
                    self.router.send(stanza)
                else:
                    raise Exception()
            except:
                xs.sendStreamError(error.StreamError('invalid-from'))
Example #5
0
    def dispatch(self, xs, stanza):
        """
        Send a stanza to the router, checking some stuff first.
        """

        log.debug("stanza from %s: %s" % (xs.otherEntity.full(), stanza.toXml()))
        util.resetNamespace(stanza, xs.namespace)
        stanzaFrom = stanza.getAttribute('from')
        stanzaTo = stanza.getAttribute('to')

        if not stanzaFrom or not stanzaTo:
            xs.sendStreamError(error.StreamError('improper-addressing'))
        else:
            try:
                sender = jid.internJID(stanzaFrom)
                jid.internJID(stanzaTo)
            except jid.InvalidFormat:
                log.debug("dropping stanza with malformed JID")

            log.debug("sender = %s, otherEntity = %s" % (sender.full(), xs.otherEntity.full()))
            if sender.host != xs.otherEntity.host and sender.host != self.defaultDomain:
                xs.sendStreamError(error.StreamError('invalid-from'))
            else:
                # replace to with destination
                destination = stanza.getAttribute('destination')
                if destination:
                    stanza['to'] = destination
                    del stanza['destination']
                self.router.send(stanza)
Example #6
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 #7
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 #8
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 #9
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 #10
0
    def network_timeout(self, stanza):
        """
        Handles errors from the net component (e.g. kontalk server not responding).
        """
        stanza.consumed = True
        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)
        message = stanza.original.firstChildElement()
        self.parent.not_found(message)

        # send ack only for chat messages
        if message.getAttribute('type') == 'chat':
            self.parent.send_ack(message, 'sent')
Example #11
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)
Example #12
0
    def network_timeout(self, stanza):
        """
        Handles errors from the net component (e.g. kontalk server not responding).
        """
        stanza.consumed = True
        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)
        message = stanza.original.firstChildElement()
        self.parent.not_found(message)

        # send ack only for chat messages
        if message.getAttribute('type') == 'chat':
            self.parent.send_ack(message, 'sent')
Example #13
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)
Example #14
0
    def dispatch(self, stanza):
        """
        Dispatch a stanza to a JID all to all available resources found locally.
        @raise L{KeyError}: if a destination route is not found
        """
        userid, unused, resource = jid.parse(stanza['to'])

        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)

        if resource is not None:
            self.streams[userid][resource].send(stanza)
        else:
            for resource, manager in self.streams[userid].iteritems():
                manager.send(stanza)
Example #15
0
    def forward(self, stanza):
        """
        Forward incoming stanza from clients to the router, setting the from
        attribute to the sender entity.
        """
        if not stanza.consumed:
            util.resetNamespace(stanza, self.namespace)

            if self.router.logTraffic:
                log.debug("forwarding %s" % (stanza.toXml().encode('utf-8'), ))

            stanza.consumed = True
            util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)
            self.router.send(stanza)
Example #16
0
    def dispatch(self, stanza):
        """
        Dispatch a stanza to a JID all to all available resources found locally.
        @raise L{KeyError}: if a destination route is not found
        """
        userid, unused, resource = jid.parse(stanza['to'])

        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)

        if resource is not None:
            self.streams[userid][resource].send(stanza)
        else:
            for resource, manager in self.streams[userid].iteritems():
                manager.send(stanza)
Example #17
0
    def forward(self, stanza, useFrom=False):
        """
        Forward incoming stanza from clients to the router, setting the from
        attribute to the sender entity.
        """
        if not stanza.consumed:
            util.resetNamespace(stanza, self.namespace)

            if self.router.logTraffic:
                log.debug("forwarding %s" % (stanza.toXml().encode('utf-8'), ))

            stanza.consumed = True
            util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)
            stanza['from'] = self.resolveJID(stanza['from'] if useFrom else self.xmlstream.otherEntity).full()
            self.router.send(stanza)
Example #18
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'), ))
            util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)
            stanza['from'] = self.resolveJID(stanza['from']).full()
            to = stanza.getAttribute('to')

            if to is not None:
                sender = jid.JID(to)
                if sender.host == self.network or sender.host in self.keyring.hostlist():
                    log.debug("stanza is for %s - resolver/c2s/net is down?" % (sender.host, ))
                else:
                    self.service.send(stanza)
Example #19
0
    def forward(self, stanza, useFrom=False):
        """
        Forward incoming stanza from clients to the router, setting the from
        attribute to the sender entity.
        """
        if not stanza.consumed:
            util.resetNamespace(stanza, self.namespace)

            if self.router.logTraffic:
                log.debug("forwarding %s" % (stanza.toXml().encode('utf-8'), ))

            stanza.consumed = True
            util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)
            stanza['from'] = self.resolveJID(stanza['from'] if useFrom else self.xmlstream.otherEntity).full()
            self.router.send(stanza)
Example #20
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'), ))
            util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)
            stanza['from'] = self.resolveJID(stanza['from']).full()
            to = stanza.getAttribute('to')

            if to is not None:
                sender = jid.JID(to)
                if sender.host == self.network or sender.host in self.keyring.hostlist(
                ):
                    log.debug("stanza is for %s - resolver/c2s/net is down?" %
                              (sender.host, ))
                else:
                    self.service.send(stanza)
Example #21
0
    def dispatch(self, stanza, hold=False, ignore_consumed=True):
        """
        Dispatches stanzas from router and from local clients.
        @param hold: if true, the stanza will not be delivered but sent to offline storage instead (used only for
        message stanzas)
        @type hold: bool
        @param ignore_consumed: if true, stanza's consumed attribute will be ignored
        @type ignore_consumed: bool
        """
        if not ignore_consumed and stanza.consumed:
            return

        stanza.consumed = True

        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)

        if stanza.hasAttribute('to'):
            to = jid.JID(stanza['to'])
            # process only our JIDs
            if util.jid_local(util.COMPONENT_C2S, self, to):
                # messages follow a different path
                if stanza.name == 'message':
                    return self.process_message(stanza, hold)
                elif stanza.name == 'presence' and stanza.getAttribute(
                        'type') == 'subscribe':
                    return self.process_subscription(stanza)

                if to.user is not None:
                    try:
                        """ TEST to store message anyway :)
                        if stanza.name == 'message':
                            raise Exception()
                        """
                        self.sfactory.dispatch(stanza)
                    except:
                        # manager not found
                        log.debug("c2s manager for %s not found" %
                                  (stanza['to'], ))
                else:
                    self.local(stanza)
            else:
                #log.debug("stanza is not our concern or is an error")
                # send to router
                component.Component.send(self, stanza)
Example #22
0
    def dispatch(self, stanza, hold=False, ignore_consumed=True):
        """
        Dispatches stanzas from router and from local clients.
        @param hold: if true, the stanza will not be delivered but sent to offline storage instead (used only for
        message stanzas)
        @type hold: bool
        @param ignore_consumed: if true, stanza's consumed attribute will be ignored
        @type ignore_consumed: bool
        """
        if not ignore_consumed and stanza.consumed:
            return

        stanza.consumed = True

        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)

        if stanza.hasAttribute('to'):
            to = jid.JID(stanza['to'])
            # process only our JIDs
            if util.jid_local(util.COMPONENT_C2S, self, to):
                # messages follow a different path
                if stanza.name == 'message':
                    return self.process_message(stanza, hold)
                elif stanza.name == 'presence' and stanza.getAttribute('type') == 'subscribe':
                    return self.process_subscription(stanza)

                if to.user is not None:
                    try:
                        """ TEST to store message anyway :)
                        if stanza.name == 'message':
                            raise Exception()
                        """
                        self.sfactory.dispatch(stanza)
                    except:
                        # manager not found
                        log.debug("c2s manager for %s not found" % (stanza['to'], ))
                else:
                    self.local(stanza)
            else:
                #log.debug("stanza is not our concern or is an error")
                # send to router
                component.Component.send(self, stanza)
Example #23
0
    def dispatch(self, xs, stanza):
        """
        Send a stanza to the router, checking some stuff first.
        """

        util.resetNamespace(stanza, xs.namespace)
        stanzaFrom = stanza.getAttribute('from')
        stanzaTo = stanza.getAttribute('to')

        if not stanzaFrom or not stanzaTo:
            xs.sendStreamError(error.StreamError('improper-addressing'))
        else:
            try:
                sender = jid.internJID(stanzaFrom)
                jid.internJID(stanzaTo)
            except jid.InvalidFormat:
                log.debug("Dropping error stanza with malformed JID")

            log.debug("sender = %s, otherEntity = %s" %
                      (sender.full(), xs.otherEntity.full()))
            if sender.host != xs.otherEntity.host and sender.host != self.defaultDomain:
                xs.sendStreamError(error.StreamError('invalid-from'))
            else:
                self.router.send(stanza)
Example #24
0
    def route(self, stanza, xs):
        """
        Route a stanza.

        @param stanza: The stanza to be routed.
        @type stanza: L{domish.Element}.
        """

        if stanza.consumed:
            return
        """"
        TEST check sender host is component
        stanzaFrom = jid.JID(stanza['from'])
        if stanzaFrom.host != xs.thisEntity.host:
            log.error("stanza is not from component - dropping")
            return
        """

        # reset namespace
        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)

        # send stanza to logging entities
        for lg in self.logs:
            lg.send(stanza)

        if not stanza.hasAttribute('to'):
            if self.logTraffic:
                log.debug("broadcasting stanza %s" %
                          (stanza.toXml().encode('utf-8'), ))
            self.broadcast(stanza)
        else:
            """
            FIXME we have encoding problems here... (why not in other components?!?!?)
            """

            # check for stanza loops
            errors = 0
            for child in stanza.children:
                if domish.IElement.providedBy(child) and child.name == 'error':
                    errors += 1
                    if errors > 1:
                        if self.logTraffic:
                            log.debug("error loop, dropping stanza %s" %
                                      (stanza.toXml().encode('utf-8'), ))
                        else:
                            log.debug("error loop, dropping stanza")

                        return

            if self.logTraffic:
                log.debug("routing stanza %s" %
                          (stanza.toXml().encode('utf-8'), ))
            try:
                destination_host = util.jid_host(stanza['to'])

                if destination_host in self.routes:
                    self.routes[destination_host].send(stanza)
                elif destination_host in self.private:
                    self.private[destination_host].send(stanza)
                else:
                    self.routes[None].send(stanza)

            except KeyError:
                log.warn("unroutable stanza, bouncing back to component")
                e = error.StanzaError('service-unavailable')
                xs.send(e.toResponse(stanza))
Example #25
0
    def send(self, stanza, force_delivery=False, force_bare=False, hold=False):
        """
        Resolves stanza recipient and send the stanza to the router.
        @param stanza: the stanza to be sent
        @type stanza: domish.Element
        @param force_delivery: if true, deliver the stanza to the first available resource found if the intended one
        is not available
        @type force_delivery bool
        @param force_bare: if true, deliver the stanza to the bare JID despite of the indicated destination
        @type force_bare bool
        @param hold: this parameter is passed directly to the dispatch method, instructing it to not deliver the stanza
        and hold it in offline storage instead (e.g. delayed/unauthorized messages)
        @type hold bool
        """

        # send raw xml if you really know what you are doing
        if not domish.IElement.providedBy(stanza):
            return component.Component.send(self, stanza)

        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)

        # force host in sender
        component_jid = util.component_jid(self.servername, util.COMPONENT_C2S)
        sender = jid.JID(stanza['from'])
        if sender.host == self.network:
            sender.host = component_jid
            stanza['from'] = sender.full()

        if not stanza.hasAttribute('to'):
            # no destination - send to router
            component.Component.send(self, stanza)
            return

        # save original recipient for later
        stanza['original-to'] = stanza['to']
        to = jid.JID(stanza['to'])

        # stanza is intended to the network
        if to.full() == self.network:
            # TODO
            log.debug("stanza for the network: %s" % (stanza.toXml(), ))
            return

        # network JID - resolve and send to router
        elif to.host == self.network:
            rcpts = self.cache.lookup(to)
            log.debug("rcpts = %r" % (rcpts, ))

            if not rcpts:
                if not stanza.consumed:
                    stanza.consumed = True
                    log.debug("JID %s not found" % (to.full(), ))
                    e = error.StanzaError('item-not-found', 'cancel')
                    self.dispatch(e.toResponse(stanza))
                else:
                    log.debug("JID %s not found (stanza has been consumed)" % (to.full(), ))
                    return
            else:
                """
                Stanza delivery rules
                1. deliver to all available resources
                2. destination was a bare JID
                  a. if all resources are unavailable, deliver to the first network bare JID (then return)
                3. destination was a full JID:
                  a. deliver to full JID
                """
                log.debug("JID found: %r" % (rcpts, ))
                jids = rcpts.jids()

                # destination was a full JID
                if to.resource and not force_bare:
                    # no available resources, deliver to bare JID if force delivery
                    if len(jids) == 0 and force_delivery:
                        stanza['to'] = rcpts.jid.userhost()
                        self.dispatch(stanza, hold=hold)
                    # deliver if resource is available
                    else:
                        sent = False
                        for _to in jids:
                            if _to.resource == to.resource:
                                stanza['to'] = _to.full()
                                self.dispatch(stanza, hold=hold)
                                sent = True
                                break

                        # if sent=False it means that the intended resource has vanished
                        # if force delivery is enabled, deliver to the first available resource
                        if not sent and len(jids) > 0 and force_delivery:
                            stanza['to'] = jids[0].full()
                            self.dispatch(stanza, hold=hold)

                # destination was a bare JID
                else:
                    log.debug("destination was a bare JID (force_bare=%s)" % (force_bare, ))
                    log.debug("jids = %s, rcpts = %s" % (jids, rcpts))
                    # no available resources, send to first network bare JID
                    if len(jids) == 0 or force_bare:
                        stanza['to'] = rcpts.jid.userhost()
                        self.dispatch(stanza, hold=hold)
                    else:
                        for _to in jids:
                            stanza['to'] = _to.full()
                            self.dispatch(stanza, hold=hold)

        # otherwise send to router
        else:
            self.dispatch(stanza, hold=hold)
Example #26
0
    def send(self, stanza, force=False):
        """Send stanza to client, setting to and id attributes if not present."""

        if stanza.hasAttribute('original-to'):
            origTo = stanza.getAttribute('original-to')
            del stanza['original-to']

            """
            Extract original recipient from stanza.
            If original-to is not present, we will assume that
            stanza was intended to the full JID.
            """
            origTo = jid.JID(origTo)

            if self.router.logTraffic:
                log.debug("sending message to client %s (original was %s)" % (self.xmlstream.otherEntity, origTo))
                if self._presence:
                    log.debug("_presence: %s" % (self._presence.toXml(), ))

            # sending to bare JID
            # initial presence found
            # negative resource
            # => DROP STANZA
            try:
                if not origTo.resource and int(str(self._presence.priority)) < 0:
                    return None
            except:
                pass

        # FIXME using deepcopy is not safe
        from copy import deepcopy
        stanza = deepcopy(stanza)

        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT, self.namespace)

        # translate sender to network JID
        sender = stanza.getAttribute('from')
        if sender and sender != self.network:
            sender = jid.JID(stanza['from'])
            sender.host = self.network
            stanza['from'] = sender.full()
        # TODO should we force self.network if no sender?

        # remove reserved elements
        if stanza.name in ('presence', 'message'):
            # storage child
            if stanza.storage and stanza.storage.uri == xmlstream2.NS_XMPP_STORAGE:
                stanza.children.remove(stanza.storage)
            # origin in receipt
            if stanza.request and stanza.request.hasAttribute('from'):
                del stanza.request['from']
            elif stanza.received and stanza.received.hasAttribute('from'):
                del stanza.received['from']
        if stanza.name == 'presence':
            # push device id
            for c in stanza.elements(name='c', uri=xmlstream2.NS_PRESENCE_PUSH):
                stanza.children.remove(c)
                break

        # force destination address
        if self.xmlstream.otherEntity:
            stanza['to'] = self.xmlstream.otherEntity.full()

        if not stanza.hasAttribute('id'):
            stanza['id'] = util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)
        xmlstream2.StreamManager.send(self, stanza, force)
Example #27
0
    def send(self, stanza, force_delivery=False, force_bare=False, hold=False):
        """
        Resolves stanza recipient and send the stanza to the router.
        @param stanza: the stanza to be sent
        @type stanza: domish.Element
        @param force_delivery: if true, deliver the stanza to the first available resource found if the intended one
        is not available
        @type force_delivery bool
        @param force_bare: if true, deliver the stanza to the bare JID despite of the indicated destination
        @type force_bare bool
        @param hold: this parameter is passed directly to the dispatch method, instructing it to not deliver the stanza
        and hold it in offline storage instead (e.g. delayed/unauthorized messages)
        @type hold bool
        """

        # send raw xml if you really know what you are doing
        if not domish.IElement.providedBy(stanza):
            return component.Component.send(self, stanza)

        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)

        # force host in sender
        component_jid = util.component_jid(self.servername, util.COMPONENT_C2S)
        sender = jid.JID(stanza['from'])
        if sender.host == self.network:
            sender.host = component_jid
            stanza['from'] = sender.full()

        if not stanza.hasAttribute('to'):
            # no destination - send to router
            component.Component.send(self, stanza)
            return

        # save original recipient for later
        stanza['original-to'] = stanza['to']
        to = jid.JID(stanza['to'])

        # stanza is intended to the network
        if to.full() == self.network:
            # TODO
            log.debug("stanza for the network: %s" % (stanza.toXml(), ))
            return

        # network JID - resolve and send to router
        elif to.host == self.network:
            rcpts = self.cache.lookup(to)
            log.debug("rcpts = %r" % (rcpts, ))

            if not rcpts:
                if not stanza.consumed:
                    stanza.consumed = True
                    log.debug("JID %s not found" % (to.full(), ))
                    e = error.StanzaError('item-not-found', 'cancel')
                    self.dispatch(e.toResponse(stanza))
                else:
                    log.debug("JID %s not found (stanza has been consumed)" %
                              (to.full(), ))
                    return
            else:
                """
                Stanza delivery rules
                1. deliver to all available resources
                2. destination was a bare JID
                  a. if all resources are unavailable, deliver to the first network bare JID (then return)
                3. destination was a full JID:
                  a. deliver to full JID
                """
                log.debug("JID found: %r" % (rcpts, ))
                jids = rcpts.jids()

                # destination was a full JID
                if to.resource and not force_bare:
                    # no available resources, deliver to bare JID if force delivery
                    if len(jids) == 0 and force_delivery:
                        stanza['to'] = rcpts.jid.userhost()
                        self.dispatch(stanza, hold=hold)
                    # deliver if resource is available
                    else:
                        sent = False
                        for _to in jids:
                            if _to.resource == to.resource:
                                stanza['to'] = _to.full()
                                self.dispatch(stanza, hold=hold)
                                sent = True
                                break

                        # if sent=False it means that the intended resource has vanished
                        # if force delivery is enabled, deliver to the first available resource
                        if not sent and len(jids) > 0 and force_delivery:
                            stanza['to'] = jids[0].full()
                            self.dispatch(stanza, hold=hold)

                # destination was a bare JID
                else:
                    log.debug("destination was a bare JID (force_bare=%s)" %
                              (force_bare, ))
                    log.debug("jids = %s, rcpts = %s" % (jids, rcpts))
                    # no available resources, send to first network bare JID
                    if len(jids) == 0 or force_bare:
                        stanza['to'] = rcpts.jid.userhost()
                        self.dispatch(stanza, hold=hold)
                    else:
                        for _to in jids:
                            stanza['to'] = _to.full()
                            self.dispatch(stanza, hold=hold)

        # otherwise send to router
        else:
            self.dispatch(stanza, hold=hold)
Example #28
0
    def route(self, stanza, xs):
        """
        Route a stanza.

        @param stanza: The stanza to be routed.
        @type stanza: L{domish.Element}.
        """

        if stanza.consumed:
            return

        """"
        TEST check sender host is component
        stanzaFrom = jid.JID(stanza['from'])
        if stanzaFrom.host != xs.thisEntity.host:
            log.error("stanza is not from component - dropping")
            return
        """

        # reset namespace
        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT)

        # send stanza to logging entities
        for lg in self.logs:
            lg.send(stanza)

        if not stanza.hasAttribute('to'):
            if self.logTraffic:
                log.debug("broadcasting stanza %s" % (stanza.toXml().encode('utf-8'), ))
            self.broadcast(stanza)
        else:
            """
            FIXME we have encoding problems here... (why not in other components?!?!?)
            """

            # check for stanza loops
            errors = 0
            for child in stanza.children:
                if domish.IElement.providedBy(child) and child.name == 'error':
                    errors += 1
                    if errors > 1:
                        if self.logTraffic:
                            log.debug("error loop, dropping stanza %s" % (stanza.toXml().encode('utf-8'), ))
                        else:
                            log.debug("error loop, dropping stanza")

                        return

            if self.logTraffic:
                log.debug("routing stanza %s" % (stanza.toXml().encode('utf-8'), ))
            try:
                destination_host = util.jid_host(stanza['to'])

                if destination_host in self.routes:
                    self.routes[destination_host].send(stanza)
                else:
                    self.routes[None].send(stanza)

            except KeyError:
                log.warn("unroutable stanza, bouncing back to component")
                e = error.StanzaError('service-unavailable')
                xs.send(xmlstream2.errorResponse(e, stanza))
Example #29
0
    def send(self, stanza, force=False):
        """Send stanza to client, setting to and id attributes if not present."""

        if stanza.hasAttribute('original-to'):
            origTo = stanza.getAttribute('original-to')
            del stanza['original-to']
            """
            Extract original recipient from stanza.
            If original-to is not present, we will assume that
            stanza was intended to the full JID.
            """
            origTo = jid.JID(origTo)

            if self.router.logTraffic:
                log.debug("sending message to client %s (original was %s)" %
                          (self.xmlstream.otherEntity, origTo))
                if self._presence:
                    log.debug("_presence: %s" %
                              (self._presence.toXml().encode('utf-8'), ))

            # sending to bare JID
            # initial presence found
            # negative resource
            # => DROP STANZA
            try:
                if not origTo.resource and int(str(
                        self._presence.priority)) < 0:
                    return None
            except:
                pass

        # FIXME using deepcopy is not safe
        from copy import deepcopy
        stanza = deepcopy(stanza)

        util.resetNamespace(stanza, component.NS_COMPONENT_ACCEPT,
                            self.namespace)

        # translate sender to network JID
        sender = stanza.getAttribute('from')
        if sender and sender != self.network:
            sender = jid.JID(stanza['from'])
            sender.host = self.network
            stanza['from'] = sender.full()
        # TODO should we force self.network if no sender?

        # remove reserved elements
        if stanza.direct and stanza.direct.uri == xmlstream2.NS_XMPP_DIRECT:
            stanza.children.remove(stanza.direct)
        if stanza.name in ('presence', 'message'):
            # storage child
            if stanza.storage and stanza.storage.uri == xmlstream2.NS_XMPP_STORAGE:
                stanza.children.remove(stanza.storage)
            # origin in receipt
            if stanza.request and stanza.request.hasAttribute('from'):
                del stanza.request['from']
            elif stanza.received and stanza.received.hasAttribute('from'):
                del stanza.received['from']
        if stanza.name == 'presence':
            # push device id
            for c in stanza.elements(name='c',
                                     uri=xmlstream2.NS_PRESENCE_PUSH):
                stanza.children.remove(c)
                break

        # force destination address
        if self.xmlstream.otherEntity:
            stanza['to'] = self.xmlstream.otherEntity.full()

        if not stanza.hasAttribute('id'):
            stanza['id'] = util.rand_str(8, util.CHARSBOX_AZN_LOWERCASE)
        xmlstream2.StreamManager.send(self, stanza, force)