Exemplo n.º 1
0
 def testParams(self):
     """Func should be callable with params"""
     def a(p1, p2, p3):
         return p1 + p2 + p3
     
     fc = FunctionCall(a, {'p1' : 'a', 'p2' : 'b', 'p3' : 'c'})
     self.assert_(fc.func(*fc.funcArgs))
Exemplo n.º 2
0
 def testNoParams(self):
     """Func should be callable without exceptions"""
     def a():
         pass
     fc = FunctionCall(a)
     
     self.assert_(callable(fc.func))
     fc.func()
Exemplo n.º 3
0
 def testSameHashParams(self):
     """If the args are substituted after creation, the hash shouldn't change"""
     def a(arg1, arg2):
         return arg1+arg2
     
     fc = FunctionCall(a, {'arg1' : 1, 'arg2' : 2})
     hash1 = fc.__hash__()
     fc.funcArgs = {'arg1' : 2, 'arg2' : 'something else'}
     hash2 = fc.__hash__()
     
     self.assert_(hash1 == hash2)
Exemplo n.º 4
0
 def testSameHashFunc(self):
     """If the function is substituted after creation, the hash shouldn't change"""
     def a(): pass
     def b(): return "asdf"
     
     fc = FunctionCall(a)
     hash1 = fc.__hash__()
     fc.func = b
     hash2 = fc.__hash__()
     
     self.assert_(hash1 == hash2)
Exemplo n.º 5
0
    def handle(self, tree, msg, lastRetVal=None):
        self.done = False

        tpool = msg.conn.server.threadpool

        msg.conn.data['user']['requestedRoster'] = True

        # the actual function executing in the thread
        def act():
            # TODO: verify that it's coming from a known user
            jid = msg.conn.data['user']['jid']
            resource = msg.conn.data['user']['resource']
            id = tree.get('id')
            if id is None:
                logging.warning('[%s] No id in roster get query. Tree: %s',
                                self.__class__, tree)
                # TODO: throw exception here
                return

            roster = Roster(jid)

            roster.loadRoster()

            res = Element('iq', {
                'to': '/'.join([jid, resource]),
                'type': 'result',
                'id': id
            })

            res.append(roster.getAsTree())
            return chainOutput(lastRetVal, res)

        def cb(workReq, retVal):
            self.done = True
            # make sure we pass the lastRetVal along
            if retVal is None:
                self.retVal = lastRetVal
            else:
                self.retVal = retVal

        req = threadpool.makeRequests(act, None, cb)

        def checkFunc():
            # need to poll manually or the callback's never called from the pool
            poll(tpool)
            return self.done

        def initFunc():
            tpool.putRequest(req[0])

        return FunctionCall(checkFunc), FunctionCall(initFunc)
Exemplo n.º 6
0
    def handle(self, tree, msg, lastRetVal=None):

        self.done = False

        tpool = msg.conn.server.threadpool

        # the actual function executing in the thread
        def act():
            data = msg.conn.data
            data['sasl']['in-progress'] = True
            mech = tree.get('mechanism')

            if mech == 'PLAIN':
                data['sasl']['mech'] = 'PLAIN'
                authtext64 = tree.text
                plain = mechs.SASLPlain(msg)
                data['sasl']['mechObj'] = plain
                return chainOutput(lastRetVal, plain.handle(authtext64))
            elif mech == 'DIGEST-MD5':
                data['sasl']['mech'] = 'DIGEST-MD5'
                digest = mechs.SASLDigestMD5(msg)
                data['sasl']['mechObj'] = digest
                return chainOutput(lastRetVal, digest.handle())
            else:
                logging.warning("[%s] Mechanism %s not implemented",
                                self.__class__, mech)

        def cb(workReq, retVal):
            self.done = True
            # make sure we pass the lastRetVal along
            if retVal is None:
                self.retVal = lastRetVal
            else:
                self.retVal = retVal

        req = threadpool.makeRequests(act, None, cb)

        def checkFunc():
            # need to poll manually or the callback's never called from the pool
            poll(tpool)
            return self.done

        def initFunc():
            tpool.putRequest(req[0])

        return FunctionCall(checkFunc), FunctionCall(initFunc)
Exemplo n.º 7
0
    def handle_read(self):
        def cb(exception=None):
            print 'called back', exception

        def check(asdf):
            print asdf
            return True

        checkFunc = FunctionCall(check, {'asdf': 'test string'})
        self.watch_function(checkFunc, cb)
        print self.recv(4096)
Exemplo n.º 8
0
    def handle(self, tree, msg, lastRetVal=None):
        self.done = False

        tpool = msg.conn.server.threadpool

        # the actual function executing in the thread
        def act():
            mech = msg.conn.data['sasl']['mechObj']
            if not mech:
                # TODO: close connection
                logging.warning(
                    "[%s] Mech object doesn't exist in connection data for %s",
                    self.__class__, msg.conn.addr)
                logging.debug("[%s] %s", self.__class__, msg.conn.data)
                return

            text = tree.text
            if text:
                return chainOutput(lastRetVal, mech.handle(text.strip()))
            else:
                return chainOutput(lastRetVal, mech.handle(tree))

        def cb(workReq, retVal):
            self.done = True
            # make sure we pass the lastRetVal along
            if retVal is None:
                self.retVal = lastRetVal
            else:
                self.retVal = retVal

        req = threadpool.makeRequests(act, None, cb)

        def checkFunc():
            # need to poll manually or the callback's never called from the pool
            poll(tpool)
            return self.done

        def initFunc():
            tpool.putRequest(req[0])

        return FunctionCall(checkFunc), FunctionCall(initFunc)
Exemplo n.º 9
0
    def handle(self, tree, msg, lastRetVal=None):
        def sleep(arg):
            """This is the actual function executing in the thread"""
            # time.sleep(10) # this also worked but slows down tests
            return 'success'

        def cb(workReq, retVal):
            """Asyncore calls this back when checkFunc returns true"""
            self.passed = retVal

        req = pjs.threadpool.makeRequests(sleep, [([0], None)], cb)

        def checkFunc():
            """Asyncore will run this regularly and call cb when true"""
            return self.passed

        def initFunc():
            """Asyncore will execute this function before checkFunc"""
            [self.threadpool.putRequest(r) for r in req]

        return FunctionCall(checkFunc), FunctionCall(initFunc)
Exemplo n.º 10
0
    def testInitFuncWithParams(self):
        """Init function with two parameters"""
        def cb(e=None):
            self.passed = self.passed and e is None

        def check(param1, param2):
            return True

        def init(a, b):
            self.passed = a and b

        checkFunc = FunctionCall(check, {
            'param1': 'non-empty string',
            'param2': 'asdfasdf'
        })
        initFunc = FunctionCall(init, {'a': 'str', 'b': 'str'})

        self.server.watch_function(checkFunc, cb, initFunc)

        asyncore.poll()

        self.assert_(self.passed)
Exemplo n.º 11
0
    def testInitFunc(self):
        """Simple init function"""
        def cb(e=None):
            self.passed = self.passed and e is None

        def check(param1, param2):
            return True

        def init():
            self.passed = True

        checkFunc = FunctionCall(check, {
            'param1': 'non-empty string',
            'param2': 'asdfasdf'
        })
        initFunc = FunctionCall(init)

        self.server.watch_function(checkFunc, cb, initFunc)

        asyncore.poll()

        self.assert_(self.passed)
Exemplo n.º 12
0
    def testSimple(self):
        """Simple callback and simple check function with no params"""
        def cb(e=None):
            self.passed = True and e is None

        def check():
            return True

        checkFunc = FunctionCall(check)
        self.server.watch_function(checkFunc, cb)

        asyncore.poll()

        self.assert_(self.passed)
Exemplo n.º 13
0
    def testCheckParam(self):
        """Check function has one parameter"""
        def cb(e=None):
            self.passed = self.passed and e is None

        def check(param1):
            if param1:
                self.passed = True
            return True

        checkFunc = FunctionCall(check, {'param1': 'non-empty string'})
        self.server.watch_function(checkFunc, cb)

        asyncore.poll()

        self.assert_(self.passed)
Exemplo n.º 14
0
    def testCheckParams(self):
        """Check function has more than one parameters"""
        def cb(e=None):
            self.passed = self.passed and e is None

        def check(param1, param2):
            if param1 and param2:
                self.passed = True
            return True

        checkFunc = FunctionCall(check, {
            'param1': 'non-empty string',
            'param2': 'asdfasdf'
        })
        self.server.watch_function(checkFunc, cb)

        asyncore.poll()

        self.assert_(self.passed)
Exemplo n.º 15
0
    def handle(self, tree, msg, lastRetVal=None):
        self.done = False
        self.retVal = lastRetVal

        tpool = msg.conn.server.threadpool

        def act():
            # TODO: verify that it's coming from a known user
            jid = msg.conn.data['user']['jid']
            cjid = JID(tree.get('to'))
            type = tree.get('type')

            if not cjid:
                logging.warning('[%s] No contact jid specified in subscription ' +\
                                'query. Tree: %s', self.__class__, tree)
                # TODO: throw exception here
                return

            roster = Roster(jid)
            # get the RosterItem
            cinfo = roster.getContactInfo(cjid.getBare())

            retVal = lastRetVal

            # C2S SUBSCRIBE
            if type == 'subscribe':

                # we must always route the subscribe presence so as to allow
                # the other servers to resynchronize their sub lists.
                # RFC 3921 9.2
                if not cinfo:
                    # contact doesn't exist, but according to RFC 3921
                    # section 8.2 bullet 4 we MUST create a new roster entry
                    # for it with empty name and groups.
                    roster.updateContact(cjid.getBare())

                    # now refetch the contact info
                    cinfo = roster.getContactInfo(cjid.getBare())

                cid = cinfo.id
                name = cinfo.name
                subscription = cinfo.subscription
                groups = cinfo.groups

                # update the subscription state
                if subscription == Subscription.NONE:
                    roster.setSubscription(cid, Subscription.NONE_PENDING_OUT)
                    subscription = Subscription.NONE_PENDING_OUT
                elif subscription == Subscription.NONE_PENDING_IN:
                    roster.setSubscription(cid,
                                           Subscription.NONE_PENDING_IN_OUT)
                    subscription = Subscription.NONE_PENDING_IN_OUT
                elif subscription == Subscription.FROM:
                    roster.setSubscription(cid, Subscription.FROM_PENDING_OUT)
                    subscription = Subscription.FROM_PENDING_OUT

                # send a roster push with ask
                query = Roster.createRosterQuery(
                    cjid.getBare(),
                    Subscription.getPrimaryNameFromState(subscription), name,
                    groups, {'ask': 'subscribe'})

                # stamp presence with 'from' JID
                treeCopy = deepcopy(tree)
                treeCopy.set('from', jid)

                # prepare the presence data for routing
                d = {
                    'to': cjid,
                    'data': treeCopy,
                }
                retVal = chainOutput(retVal, d)

                # sequence of events in reverse order
                # push the roster first, in case we have to create a new
                # s2s connection
                msg.setNextHandler('route-server')
                msg.setNextHandler('roster-push')

                return chainOutput(retVal, query)

            # C2S SUBSCRIBED
            elif type == 'subscribed':

                if not cinfo:
                    logging.warning("[%s] 'subscribed' presence received for " +\
                                    "non-existent contact %s", self.__class__, cjid)
                else:
                    subscription = cinfo.subscription
                    if cinfo.subscription in (Subscription.NONE_PENDING_IN,
                                              Subscription.NONE_PENDING_IN_OUT,
                                              Subscription.TO_PENDING_IN):
                        # update state and deliver
                        if cinfo.subscription == Subscription.NONE_PENDING_IN:
                            roster.setSubscription(cinfo.id, Subscription.FROM)
                            subscription = Subscription.FROM
                        elif cinfo.subscription == Subscription.NONE_PENDING_IN_OUT:
                            roster.setSubscription(
                                cinfo.id, Subscription.FROM_PENDING_OUT)
                            subscription = Subscription.FROM_PENDING_OUT
                        elif cinfo.subscription == Subscription.TO_PENDING_IN:
                            roster.setSubscription(cinfo.id, Subscription.BOTH)
                            subscription = Subscription.BOTH

                        # roster stanza
                        query = Roster.createRosterQuery(
                            cjid.getBare(),
                            Subscription.getPrimaryNameFromState(subscription),
                            cinfo.name, cinfo.groups)

                        # stamp presence with 'from'
                        treeCopy = deepcopy(tree)
                        treeCopy.set('from', jid)

                        toRoute = tostring(treeCopy)

                        # create available presence stanzas for all resources of the user
                        resources = msg.conn.server.launcher.getC2SServer(
                        ).data['resources']
                        jidForResources = resources.has_key(
                            jid) and resources[jid]
                        if jidForResources:
                            out = u''
                            for i in jidForResources:
                                out += "<presence from='%s/%s'" % (jid, i)
                                out += " to='%s'/>" % cjid.getBare()
                            # and queue for routing
                            toRoute += out

                        # prepare the presence data for routing
                        d = {
                            'to': cjid,
                            'data': toRoute,
                        }
                        retVal = chainOutput(retVal, d)

                        # next handlers in reverse order
                        msg.setNextHandler('route-server')
                        msg.setNextHandler('roster-push')

                        return chainOutput(retVal, query)

            # C2S UNSUBSCRIBE
            elif type == 'unsubscribe':

                # we must always route the unsubscribe presence so as to allow
                # the other servers to resynchronize their sub lists.
                # RFC 3921 9.2
                if not cinfo:
                    # we don't have this contact in our roster, but route the
                    # presence anyway
                    # stamp presence with 'from'
                    treeCopy = deepcopy(tree)
                    treeCopy.set('from', jid)

                    # prepare the presence data for routing
                    d = {
                        'to': cjid,
                        'data': treeCopy,
                    }
                    msg.setNextHandler('route-server')

                    return chainOutput(retVal, d)
                else:
                    subscription = cinfo.subscription
                    if subscription == Subscription.BOTH:  # mutual
                        roster.setSubscription(cinfo.id, Subscription.FROM)
                        subscription = Subscription.FROM
                    elif subscription in (
                            Subscription.NONE_PENDING_OUT,  # one way
                            Subscription.NONE_PENDING_IN_OUT,
                            Subscription.TO,
                            Subscription.TO_PENDING_IN):
                        if subscription == Subscription.NONE_PENDING_OUT \
                          or subscription == Subscription.TO:
                            roster.setSubscription(cinfo.id, Subscription.NONE)
                            subscription = Subscription.NONE
                        elif subscription == Subscription.NONE_PENDING_IN_OUT \
                          or subscription == Subscription.TO_PENDING_IN:
                            roster.setSubscription(
                                cinfo.id, Subscription.NONE_PENDING_IN)
                            subscription = Subscription.NONE_PENDING_IN

                    # roster stanza
                    query = Roster.createRosterQuery(
                        cjid.getBare(),
                        Subscription.getPrimaryNameFromState(subscription),
                        cinfo.name, cinfo.groups)

                    # stamp presence with 'from'
                    treeCopy = deepcopy(tree)
                    treeCopy.set('from', jid)

                    # prepare the presence data for routing
                    d = {
                        'to': cjid,
                        'data': treeCopy,
                    }
                    retVal = chainOutput(retVal, d)

                    # schedules handlers in reverse order
                    msg.setNextHandler('route-server')
                    msg.setNextHandler('roster-push')

                    return chainOutput(retVal, query)

            # C2S UNSUBSCRIBED
            elif type == 'unsubscribed':

                if not cinfo:
                    logging.warning("[%s] 'unsubscribed' presence received for " +\
                                    "non-existent contact %s", self.__class__, cjid)
                else:
                    subscription = cinfo.subscription
                    if subscription not in (Subscription.NONE,
                                            Subscription.NONE_PENDING_OUT,
                                            Subscription.TO):
                        if subscription == Subscription.NONE_PENDING_IN \
                          or subscription == Subscription.FROM:
                            roster.setSubscription(cinfo.id, Subscription.NONE)
                            subscription = Subscription.NONE
                        elif subscription == Subscription.NONE_PENDING_IN_OUT \
                          or subscription == Subscription.FROM_PENDING_OUT:
                            roster.setSubscription(
                                cinfo.id, Subscription.NONE_PENDING_OUT)
                            subscription = Subscription.NONE
                        elif subscription == Subscription.TO_PENDING_IN \
                          or subscription == Subscription.BOTH:
                            roster.setSubscription(cinfo.id, Subscription.TO)
                            subscription = Subscription.TO

                        # roster query
                        if subscription == Subscription.NONE_PENDING_OUT:
                            itemArgs = {'ask': 'subscribe'}
                        else:
                            itemArgs = {}
                        query = roster.createRosterQuery(
                            cjid.getBare(),
                            Subscription.getPrimaryNameFromState(subscription),
                            cinfo.name, cinfo.groups, itemArgs)

                        # stamp presence with 'from'
                        treeCopy = deepcopy(tree)
                        treeCopy.set('from', jid)

                        toRoute = tostring(treeCopy)

                        # create unavailable presence stanzas for all resources of the user
                        resources = msg.conn.server.launcher.getC2SServer(
                        ).data['resources']
                        jidForResources = resources.has_key(
                            jid) and resources[jid]
                        if jidForResources:
                            out = u''
                            for i in jidForResources:
                                out += "<presence from='%s/%s'" % (jid, i)
                                out += " to='%s' type='unavailable'/>" % cjid.getBare(
                                )
                            # and add to output
                            toRoute += out

                        # prepare the presence data for routing
                        d = {
                            'to': cjid,
                            'data': toRoute,
                        }
                        retVal = chainOutput(retVal, d)

                        # handlers in reverse order
                        msg.setNextHandler('route-server')
                        msg.setNextHandler('roster-push')

                        return chainOutput(retVal, query)

        def cb(workReq, retVal):
            self.done = True
            # make sure we pass the lastRetVal along
            if retVal is None:
                self.retVal = lastRetVal
            else:
                self.retVal = retVal

        req = threadpool.makeRequests(act, None, cb)

        def checkFunc():
            # need to poll manually or the callback's never called from the pool
            poll(tpool)
            return self.done

        def initFunc():
            tpool.putRequest(req[0])

        return FunctionCall(checkFunc), FunctionCall(initFunc)
Exemplo n.º 16
0
    def handle(self, tree, msg, lastRetVal=None):
        self.done = False
        self.retVal = lastRetVal
        tpool = msg.conn.server.threadpool

        def act():
            d = msg.conn.data

            retVal = lastRetVal

            jid = d['user']['jid']
            resource = d['user']['resource']

            roster = Roster(jid)

            presTree = deepcopy(tree)
            presTree.set('from', '%s/%s' % (jid, resource))

            probes = []
            if tree.get('to') is None and not d['user']['active']:
                # initial presence
                # TODO: we don't need to do it every time. we can cache the
                # data after the first resource is active and just resend
                # that to all new resources
                d['user']['active'] = True

                # get jids of the contacts whose status we're interested in
                cjids = roster.getPresenceSubscriptions()

                probeTree = Element('presence', {
                                                 'type': 'probe',
                                                 'from' : '%s/%s' \
                                                    % (jid, resource)
                                                 })

                # TODO: replace this with a more efficient router handler
                for cjid in cjids:
                    probeTree.set('to', cjid)
                    probeRouteData = {'to': cjid, 'data': deepcopy(probeTree)}
                    probes.append(probeRouteData)
                    # they're sent first. see below

                # broadcast to other resources of this user
                retVal = self.broadcastToOtherResources(
                    presTree, msg, retVal, jid, resource)

            elif tree.get('to') is not None:
                # TODO: directed presence
                return
            elif tree.get('type') == 'unavailable':
                # broadcast to other resources of this user
                d['user']['active'] = False
                retVal = self.broadcastToOtherResources(
                    presTree, msg, retVal, jid, resource)

            # record this stanza as the last presence sent from this client
            lastPresence = deepcopy(tree)
            lastPresence.set('from', '%s/%s' % (jid, resource))
            d['user']['lastPresence'] = lastPresence

            # lookup contacts interested in presence
            cjids = roster.getPresenceSubscribers()

            # TODO: replace this with another router handler that would send
            # it out to all cjids in a batch instead of queuing a handler
            # for each
            for cjid in cjids:
                presTree.set('to', cjid)
                presRouteData = {'to': cjid, 'data': deepcopy(presTree)}
                retVal = chainOutput(retVal, presRouteData)
                msg.setNextHandler('route-server')

            # send the probes first
            for probe in probes:
                msg.setNextHandler('route-server')
                retVal = chainOutput(retVal, probe)

            return retVal

        def cb(workReq, retVal):
            self.done = True
            # make sure we pass the lastRetVal along
            if retVal is None:
                self.retVal = lastRetVal
            else:
                self.retVal = retVal

        req = threadpool.makeRequests(act, None, cb)

        def checkFunc():
            # need to poll manually or the callback's never called from the pool
            poll(tpool)
            return self.done

        def initFunc():
            tpool.putRequest(req[0])

        return FunctionCall(checkFunc), FunctionCall(initFunc)
Exemplo n.º 17
0
            if retVal is None:
                self.retVal = lastRetVal
            else:
                self.retVal = retVal

        req = threadpool.makeRequests(act, None, cb)

        def checkFunc():
            # need to poll manually or the callback's never called from the pool
            poll(tpool)
            return self.done

        def initFunc():
            tpool.putRequest(req[0])

        return FunctionCall(checkFunc), FunctionCall(initFunc)

    def resume(self):
        return self.retVal


class C2SSubscriptionHandler(ThreadedHandler):
    """Handles subscriptions sent from clients within <presence> stanzas.
    ie. <presence> elements with types.
    """
    def __init__(self):
        # this is true when the threaded handler returns
        self.done = False
        # used to pass the output to the next handler
        self.retVal = None
Exemplo n.º 18
0
    def handle(self, tree, msg, lastRetVal=None):
        self.done = False

        tpool = msg.conn.server.threadpool

        # the actual function executing in the thread
        def act():
            # TODO: verify that it's coming from a known user
            jid = msg.conn.data['user']['jid']
            id = tree.get('id')
            if id is None:
                logging.warning('[%s] No id in roster get query. Tree: %s',
                                self.__class__, tree)
                # TODO: throw exception here
                return

            # RFC 3921 says in section 7.4 "an item", so we only handle the
            # first <item>
            item = tree[0][0]  # iq -> query -> item
            cjid = item.get('jid')
            name = item.get('name')
            if cjid is None:
                logging.warning("[%s] Client trying to add a roster item " + \
                                "without a jid. Tree: %s",
                                self.__class__, tree)
                # TODO: throw exception here
                return

            roster = Roster(jid)

            xpath = './{jabber:iq:roster}query/{jabber:iq:roster}item[@subscription="remove"]'
            if tree.find(xpath) is not None:
                # we're removing the roster item. See 3921 8.6
                out = "<presence from='%s' to='%s' type='unsubscribe'/>" \
                                                          % (jid, cjid)
                out += "<presence from='%s' to='%s' type='unsubscribed'/>" \
                                                          % (jid, cjid)
                # create unavailable presence stanzas for all resources of the user
                resources = msg.conn.server.launcher.getC2SServer(
                ).data['resources']
                jidForResources = resources.has_key(jid) and resources[jid]
                if jidForResources:
                    for i in jidForResources:
                        out += "<presence from='%s/%s'" % (jid, i)
                        out += " to='%s' type='unavailable'/>" % cjid

                # prepare routing data
                d = {'to': cjid, 'data': out}

                query = deepcopy(tree[0])

                retVal = chainOutput(lastRetVal, query)

                if roster.removeContact(cjid) is False:
                    # We don't even have this contact in the roster anymore.
                    # The contact is probably local (like ourselves).
                    # This happens with some clients (like pidgin/gaim) who
                    # cache the roster and don't delete some items even when
                    # they're not present in the roster the server sends out
                    # anymore. If we send the presence here it
                    # will probably arrive after roster-push (due to s2s)
                    # and will confuse the clients into thinking they still
                    # have that contact in their roster. This creates an
                    # undeletable contact. We can't do much about this.
                    # If/when the s2s component can do a shortcut delivery of
                    # stanzas to local users, while in the same phase, this
                    # problem should go away, as it will allow the roster-push
                    # to arrive after presences every time.
                    pass

                # route the presence first, then do a roster push
                msg.setNextHandler('roster-push')
                msg.setNextHandler('route-server')

                return chainOutput(retVal, d)

            # we're updating/adding the roster item

            groups = [
                i.text for i in list(item.findall('{jabber:iq:roster}group'))
            ]

            cid = roster.updateContact(cjid, groups, name)

            # get the subscription status before roster push
            sub = roster.getSubPrimaryName(cid)

            # prepare the result for roster push
            query = Roster.createRosterQuery(cjid, sub, name, groups)

            msg.setNextHandler('roster-push')

            return chainOutput(lastRetVal, query)

        def cb(workReq, retVal):
            self.done = True
            # make sure we pass the lastRetVal along
            if retVal is None:
                self.retVal = lastRetVal
            else:
                self.retVal = retVal

        req = threadpool.makeRequests(act, None, cb)

        def checkFunc():
            # need to poll manually or the callback's never called from the pool
            poll(tpool)
            return self.done

        def initFunc():
            tpool.putRequest(req[0])

        return FunctionCall(checkFunc), FunctionCall(initFunc)
Exemplo n.º 19
0
    def handle(self, tree, msg, lastRetVal=None):
        self.done = False

        tpool = msg.conn.server.threadpool

        def act():
            # we have to be passed a tree to work
            # or a tuple with routingData and a tree
            if not isinstance(lastRetVal, list):
                logging.warning('[%s] lastRetVal is not a list',
                                self.__class__)
                return
            if isinstance(lastRetVal[-1], Element):
                if lastRetVal[-1].tag.find('query') == -1:
                    logging.warning('[%s] Got a non-query Element last return value' +\
                                '. Last return value: %s',
                                self.__class__, lastRetVal)
            elif isinstance(lastRetVal[-1], tuple):
                if not isinstance(lastRetVal[-1][0], dict) \
                or not isinstance(lastRetVal[-1][1], Element):
                    logging.warning('[%s] Got a non-query Element last return value' +\
                                '. Last return value: %s',
                                self.__class__, lastRetVal)
                    return
            else:
                logging.warning('[%s] Roster push needs either a <query> Element ' +\
                                'as the last item in lastRetVal or a tuple ' + \
                                'with (routeData, query Element)', self.__class__)
                return

            # this is the roster <query> that we'll send
            # it could be a tuple if we got routing data as well
            query = lastRetVal.pop(-1)
            routeData = None

            # did we get routing data (from S2S)
            if isinstance(query, tuple):
                routeData = query[0]
                query = query[1]

            if routeData:
                jid = routeData['jid']
                resources = routeData['resources']
            else:
                jid = msg.conn.data['user']['jid']
                resource = msg.conn.data['user']['resource']
                resources = msg.conn.server.data['resources'][jid]

            for res, con in resources.items():
                # don't send the roster to clients that didn't request it
                if con.data['user']['requestedRoster']:
                    iq = Element(
                        'iq', {
                            'to': '%s/%s' % (jid, res),
                            'type': 'set',
                            'id': generateId()[:10]
                        })
                    iq.append(query)

                    # TODO: remove this. debug.
                    logging.debug("Sending " + tostring(iq))
                    con.send(tostring(iq))

            if tree.tag == '{jabber:client}iq' and tree.get('id'):
                # send an ack to client if this is in reply to a roster get/set
                id = tree.get('id')
                d = {
                    'to': '%s/%s' % (jid, resource),
                    'type': 'result',
                    'id': id
                }
                iq = Element('iq', d)
                return chainOutput(lastRetVal, iq)

        def cb(workReq, retVal):
            self.done = True
            # make sure we pass the lastRetVal along
            if retVal is None:
                self.retVal = lastRetVal
            else:
                self.retVal = retVal

        req = threadpool.makeRequests(act, None, cb)

        def checkFunc():
            # need to poll manually or the callback's never called from the pool
            poll(tpool)
            return self.done

        def initFunc():
            tpool.putRequest(req[0])

        return FunctionCall(checkFunc), FunctionCall(initFunc)
Exemplo n.º 20
0
    def handle(self, tree, msg, lastRetVal=None):
        self.done = False

        tpool = msg.conn.server.threadpool

        # the actual function executing in the thread
        def act():
            data = msg.conn.data
            # check for policy violation
            violation = checkPolicyViolation(msg)
            if violation is not None:
                msg.setLastHandler('close-stream')
                return chainOutput(lastRetVal, violation)

            id = tree.get('id')
            if not id:
                logging.debug("[%s] No id specified in iq-auth set request",
                              self.__class__)

            data['iqauth']['in-progress'] = True

            username = tree[0].find('{jabber:iq:auth}username')
            if username is not None:
                username = username.text
            resource = tree[0].find('{jabber:iq:auth}resource')
            if resource is not None:
                resource = resource.text

            if username is None or resource is None:
                iq = makeNotAcceptable(id)
                return chainOutput(lastRetVal, iq)

            digest = tree[0].find('{jabber:iq:auth}digest')
            if digest is not None:
                digest = digest.text
            password = tree[0].find('{jabber:iq:auth}password')
            if password is not None:
                password = password.text

            if digest:
                data['iqauth']['mech'] = 'digest'
                auth = mechs.IQAuthDigest(msg)
                try:
                    auth.handle(username, digest)
                except IQAuthError:
                    return chainOutput(lastRetVal, makeNotAuthorized(id))
            elif password:
                data['iqauth']['mech'] = 'plain'
                plain = mechs.IQAuthPlain(msg)
                try:
                    plain.handle(username, password)
                except IQAuthError:
                    return chainOutput(lastRetVal, makeNotAuthorized(id))
            else:
                iq = makeNotAcceptable(id)
                return chainOutput(lastRetVal, iq)

            # do the resource binding
            # TODO: check that we don't already have such a resource
            bindResource(msg, resource)

            data['iqauth']['complete'] = True

            return chainOutput(lastRetVal, makeSuccess(id))

        def cb(workReq, retVal):
            self.done = True
            # make sure we pass the lastRetVal along
            if retVal is None:
                self.retVal = lastRetVal
            else:
                self.retVal = retVal

        req = threadpool.makeRequests(act, None, cb)

        def checkFunc():
            # need to poll manually or the callback's never called from the pool
            poll(tpool)
            return self.done

        def initFunc():
            tpool.putRequest(req[0])

        return FunctionCall(checkFunc), FunctionCall(initFunc)
Exemplo n.º 21
0
    def handle(self, tree, msg, lastRetVal=None):
        self.done = False
        self.retVal = lastRetVal
        tpool = msg.conn.server.threadpool

        def act():
            d = msg.conn.data
            if 'new-s2s-conn' not in d or \
                'hostname' not in d['new-s2s-conn'] or \
                'ip' not in d['new-s2s-conn']:
                logging.warning(
                    "[%s] Invoked without necessary data in connection",
                    self.__class__)
                return

            local = False
            if d['new-s2s-conn'].get('local'):
                local = True

            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.connect((d['new-s2s-conn']['ip'],
                          d['new-s2s-conn'].setdefault('port', 5269)))

            serv = msg.conn.server.launcher.getS2SServer()
            if not serv:
                logging.warning("[%s] Can't find an S2SServer in launcher",
                                self.__class__)
                return

            if local:
                conn = serv.createLocalOutConnection(sock)
                # if we're connecting to ourselves, we don't need the <stream>.
                # instead just send out the outQueue
                data = d['new-s2s-conn'].get('queue')
                if data is not None:
                    conn.send(prepareDataForSending(data))
            else:
                sOutConn = serv.createRemoteOutConnection(sock)

                # copy over any queued messages to send once fully connected
                sOutConn.outQueue.extend(d['new-s2s-conn'].setdefault(
                    'queue', []))

                # register the connection with the S2S server
                serverConns = serv.s2sConns.setdefault(
                    d['new-s2s-conn']['hostname'], [None, None])
                serverConns[1] = sOutConn

                # send the initial stream
                # commenting this out for now as it causes expat problems
                sOutConn.send("<?xml version='1.0' ?>")
                sOutConn.send("<stream:stream xmlns='jabber:server' " +\
                              "xmlns:stream='http://etherx.jabber.org/streams' " +\
                              "to='%s' " % d['new-s2s-conn']['hostname'] + \
                              "version='1.0'>")

        def cb(workReq, retVal):
            self.done = True
            # we don't return anything, but make sure we pass the
            # lastRetVal along
            self.retVal = lastRetVal

        req = threadpool.makeRequests(act, None, cb)

        def checkFunc():
            # need to poll manually or the callback's never called from the pool
            poll(tpool)
            return self.done

        def initFunc():
            tpool.putRequest(req[0])

        return FunctionCall(checkFunc), FunctionCall(initFunc)