Exemplo n.º 1
0
 def _getConnection(self):
     if self.host:
         return reactor.connectTCP(self.host, self.port, self.factory)
     else:
         c = SRVConnector(reactor, 'xmpp-client', self.domain, self.factory)
         c.connect()
         return c
Exemplo n.º 2
0
 def start(self):       
    myJid = jid.JID(self.username)
    factory = client.XMPPClientFactory(myJid, self.password)
    factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, self.authd)       
    connector = SRVConnector(reactor, 'xmpp-client', self.jabberserver, factory)       
    reactor.callLater(5, self.stop)
    connector.connect()    
Exemplo n.º 3
0
 def connect(self):
     if callable(self.override):
         self.override(self.factory)
     elif not self._isQueryNeeded():
         self.factory.doStart()
         self.factory.startedConnecting(self)
         self._reallyConnect()
     else:
         SRVConnector.connect(self)
Exemplo n.º 4
0
 def connectSRV(self, service, domain, *args, **kwargs):
     SRVConnector = kwargs.pop('ConnectorClass', None)
     if SRVConnector is None:
         from twisted.names.srvconnect import SRVConnector
     gtransport, factory = self._make_transport_and_factory()
     c = SRVConnector(self.reactor, service, domain, factory, *args, **kwargs)
     c.connect()
     gtransport._init_transport()
     return gtransport
Exemplo n.º 5
0
 def __init__(self, client_jid, secret):
     f = client.XMPPClientFactory(client_jid, secret)
     f.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, self.connected)
     f.addBootstrap(xmlstream.STREAM_END_EVENT, self.disconnected)
     f.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, self.authenticated)
     f.addBootstrap(xmlstream.INIT_FAILED_EVENT, self.init_failed)
     connector = SRVConnector(reactor, 'xmpp-client', client_jid.host, f,
                              defaultPort=5222)
     connector.connect()
Exemplo n.º 6
0
 def __init__(self, reactor, jid, secret):
     self.reactor = reactor
     f = client.XMPPClientFactory(jid, secret)
     f.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, self.connected)
     f.addBootstrap(xmlstream.STREAM_END_EVENT, self.disconnected)
     f.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, self.authenticated)
     f.addBootstrap(xmlstream.INIT_FAILED_EVENT, self.init_failed)
     connector = SRVConnector(reactor, "xmpp-client", jid.host, f, defaultPort=5222)
     connector.connect()
     self.finished = Deferred()
Exemplo n.º 7
0
 def __init__(self, client_reactor, domain, factory):
     """ Init """
     SRVConnector.__init__(self, client_reactor, 'xmpp-client', domain, factory)
     if isinstance(domain, unicode):
         warnings.warn(
             "Domain argument to XMPPClientConnector should be bytes, "
             "not unicode",
             stacklevel=2)
         domain = domain.encode('ascii')
     self.timeout = [1,3]
Exemplo n.º 8
0
 def __init__(self, service):
     jid = JID('127.0.0.1')
     f = client.XMPPClientFactory(jid, '')
     f.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, self.connected)
     f.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, self.authenticated)
     connector = SRVConnector(
         reactor, 'xmpp-client', jid.host, f, defaultPort=6523)
     connector.connect()
     self.finished = Deferred()
     self.files = {}
     self.service = service
Exemplo n.º 9
0
    def __init__(self, reactor, dn, factory,
                 overrides=None, bindAddress=None):
        if not isinstance(dn, distinguishedname.DistinguishedName):
            dn = distinguishedname.DistinguishedName(stringValue=dn)
        if overrides is None:
            overrides = {}
        self.override = self._findOverRide(dn, overrides)

        domain = dn.getDomainName() or ''
        SRVConnector.__init__(self, reactor,
                  'ldap', domain, factory,
                  connectFuncKwArgs={'bindAddress': bindAddress})
Exemplo n.º 10
0
    def connect(self, protocolFactory):
        def _canceller(deferred):
            connector.stopConnecting()
            deferred.errback(
                error.ConnectingCancelledError(connector.getDestination()))

        try:
            wf = _WrappingFactory(protocolFactory, _canceller)
            connector = SRVConnector(self._reactor, self._service, 
                self._domain, wf, protocol=self._protocol)
            connector.connect()
            return wf._onConnection
        except:
            return defer.fail()
Exemplo n.º 11
0
    def pickServer(self):
        if self.override is None:
            overriddenHost, overriddenPort = None, None
        else:
            overriddenHost, overriddenPort = self.override

        if (overriddenHost is not None
            and (overriddenPort is not None
                 or self.domain is None)):
            host = overriddenHost
            port = overriddenPort
        else:
            host, port = SRVConnector.pickServer(self)
            if overriddenHost is not None:
                host = overriddenHost
            if overriddenPort is not None:
                port = overriddenPort

        try:
            port = int(port)
        except ValueError:
            pass

        assert host is not None
        if port is None:
            port = 389
        return host, port
Exemplo n.º 12
0
    def connect(self, server_address, service=None, protocol='tcp'):
        """
        Connect to the given server_address.

        Without the 'service' keyword, the server_address can be formatted
        as HOST[:PORT] (if no port given, 8800 will be assumed).

        If 'service' is used, it must be the name of a service to look up
        using a DNS SRV record at the server_address (in this case, no port is
        expected in the server_address). The 'protocol' is also sent used in
        the DNS SRV lookup.

        The 'protocol' keyword is ignored if 'service' is not used.

        Examples:
            c = Client()

            # connect to example.com at port 8800
            c.connect('example.com')

            # connect to example.com at port 45
            c.connect('example.com:45')

            # look up the host and port using SRV, passing 'SIP' as the
            ## service name to the DNS SRV host at example.com
            c.connect('example.com', service='SIP')

         TODO: Twisted uses it's own lookup cache that appears to be
         cleared when the process terminates. I am unsure whether that
         cache respects SRV TTL; if not, long-living reconnecting
         clients *might* not get a new lookup. Further testing is needed
         to determine this.
        """
        self.ip = server_address
        if service:
            connector = SRVConnector(reactor, service, server_address,
                self.factory, protocol=protocol)
            connector.connect()
        else:
            self.host, self.port = utils.parse_host_port(server_address, 8800)
            try:
                reactor.connectTCP(self.host, self.port, self.factory)
            except error.ConnectionRefusedError, e:
                logger.error(e)
                # wraps the error in a slightly more generic ClientError
                ## and reraises
                raise ClientError(str(e))
Exemplo n.º 13
0
Arquivo: xmpp.py Projeto: Ri0n/Hermes
    def pickServer(self):
        host, port = SRVConnector.pickServer(self)

        if not self.servers and not self.orderedServers:
            # no SRV record, fall back..
            port = int(config()['xmpp']['port'])

        return host, port
Exemplo n.º 14
0
    def pickServer(self):
        host, port = SRVConnector.pickServer(self)

        if not self.servers and not self.orderedServers:
            # no SRV record, fall back..
            port = 5222

        return host, port
Exemplo n.º 15
0
    def pickServer(self):
        assert self.servers is not None
        assert self.orderedServers is not None

        if not self.servers and not self.orderedServers:
            # no SRV record, fall back..
            return self.domain, 2855

        return SRVConnector.pickServer(self)
Exemplo n.º 16
0
    def connectSSL(self, server_address, cert_path, cert_chain_path=None,
            service=None, protocol='ssl'):
        """
        Connect to the given server_address.

        See the docstring for Client.connect() for more information.
        """
        self.ip = server_address

        # verify that the given key/cert files actually exist
        if not os.path.exists(cert_path):
            raise ClientError('Cert file %r does not exist!' % cert_path)
        if cert_chain_path and not os.path.exists(cert_chain_path):
            raise ClientError('Cert chain file %r does not exist!' % \
                cert_chain_path)

        class CtxFactory(ssl.ClientContextFactory):
            def getContext(self):
                self.method = SSL.SSLv23_METHOD
                ctx = ssl.ClientContextFactory.getContext(self)
                if cert_chain_path:
                    ctx.use_certificate_chain_file(cert_chain_path)
                ctx.use_certificate_file(cert_path)
                return ctx

        if service:
            connector = SRVConnector(reactor, service, server_address,
                self.factory, protocol=protocol, connectFuncName='connectSSL',
                connectFuncArgs=(CtxFactory(),))
            connector.connect()
        else:
            self.host, self.port = utils.parse_host_port(server_address, 2220)
            try:
                reactor.connectSSL(self.host, self.port, self.factory,
                    CtxFactory())
            except error.ConnectionRefusedError, e:
                logger.error(e)
                # wraps the error in a slightly more generic ClientError
                ## and reraises
                raise ClientError(str(e))
Exemplo n.º 17
0
    def init(self):
        self.username, self.server = self.mirror('username').split('@')
        self.password = self.mirror('password')
        listener = self.parent().get_listener(self._id)
        self.resource = listener['resource']
        self.nickname = listener['nickname']

        jid = "%s@%s/%s" % (self.username, self.server, self.resource)
        self.jid = JID(jid)
        self.f = client.XMPPClientFactory(self.jid, self.password)

        self.con = SRVConnector(
            reactor, 'xmpp-client', self.jid.host, self.f, defaultPort=5222)
Exemplo n.º 18
0
    def pickServer(self):
        """
        Pick a server and port to make the connection.
        """
        host, port = SRVConnector.pickServer(self)

        if port == 5223 and ssl:
            context = ssl.ClientContextFactory()
            context.method = ssl.SSL.SSLv23_METHOD

            self.connectFuncName = 'connectSSL'
            self.connectFuncArgs = (context,)
        return host, port
Exemplo n.º 19
0
    def pickServer(self):
        """
        Pick a server and port to make the connection.
        """
        host, port = SRVConnector.pickServer(self)

        if port == 5223 and ssl:
            context = ssl.ClientContextFactory()
            context.method = ssl.SSL.SSLv23_METHOD

            self.connectFuncName = 'connectSSL'
            self.connectFuncArgs = (context, )
        return host, port
Exemplo n.º 20
0
    def pickServer(self):
        """
        Pick a server and port to make the connection.
        """
        host, port = SRVConnector.pickServer(self)

        if not self.servers and not self.orderedServers:
            # no SRV record, fall back..
            port = 5222
        if port == 5223 and xmlstream.ssl:
            context = xmlstream.ssl.ClientContextFactory()
            context.method = xmlstream.ssl.SSL.SSLv23_METHOD

            self.connectFunc = 'connectSSL'
            self.connectFuncArgs = (context)
        return host, port
Exemplo n.º 21
0
    def pickServer(self):
        """
        Pick a server and port to make the connection.
        """
        host, port = SRVConnector.pickServer(self)

        if not self.servers and not self.orderedServers:
            # no SRV record, fall back..
            port = 5222
        if port == 5223 and xmlstream.ssl:
            context = xmlstream.ssl.ClientContextFactory()
            context.method = xmlstream.ssl.SSL.SSLv23_METHOD
            
            self.connectFunc = 'connectSSL'
            self.connectFuncArgs = (context)
        return host, port
Exemplo n.º 22
0
def fetch_server_key(server_name, ssl_context_factory):
    """Fetch the keys for a remote server."""

    factory = SynapseKeyClientFactory()

    SRVConnector(
        reactor,
        "matrix",
        server_name,
        factory,
        protocol="tcp",
        connectFuncName="connectSSL",
        defaultPort=443,
        connectFuncKwArgs=dict(contextFactory=ssl_context_factory)).connect()

    server_key, server_certificate = yield factory.remote_key

    defer.returnValue((server_key, server_certificate))
Exemplo n.º 23
0
def clientCreator(factory):
    domain = factory.authenticator.jid.host
    c = SRVConnector(reactor, 'xmpp-client', domain, factory)
    c.connect()
    return factory.deferred
Exemplo n.º 24
0
class XmppService(Service):

    timeout = True
    active_controllers = []

    def __init__(self,
                 device,
                 user='******',
                 secret='password',
                 userlist=[],
                 web_server=None):
        self.log = Logger()
        self.description = None
        self.reactor = reactor
        self.user = user
        self.services = {}
        self.nodes = []
        self.registrations = []
        self.active_controllers = []
        self.webserver = web_server
        self.resource = web_server.resource
        device.location = user

        def _map_context(ctx):
            ctx.udc = UserDefinedContext(device.player)

        self._jid = _jid = ''.join(
            (user, '/', device.deviceType, ':uuid:', device.uuid))
        self.device = device
        device.parent = self
        for service in device.services:
            #             if appreg.get_application(service.tns, service.name):
            #                 name = service.name + '_'
            #             else:
            #                 name = service.name
            #             soap_service = type(
            #                 service.name, (ServiceBase,), service.soap_functions)
            #             soap_service.tns = service.tns
            #             app = Application(
            #                 [soap_service],
            #                 tns=soap_service.tns,
            #                 in_protocol=Soap11(xml_declaration=False),
            #                 out_protocol=Soap11(xml_declaration=False),
            #                 name=name)
            #             app.event_manager.add_listener('method_call', _map_context)
            self.services.update({
                str(service.serviceId): {
                    'app': TwistedXMPPApp(service.app),
                    'svc': service
                }
            })
            print('name: %s, methods: %s' %
                  (device.name, service.app.interface.service_method_map))
            for var in service.stateVariables.values():
                if var.sendEvents:
                    self.nodes.append((var, service.serviceType, service))
        self.users = {user: False}
        for user in userlist:
            self.users.update({user: False})
        self.jid = jid = JID(_jid)
        self.factory = f = client.XMPPClientFactory(jid, secret)
        f.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, self.connected)
        f.addBootstrap(xmlstream.STREAM_END_EVENT, self.disconnected)
        f.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, self.authenticated)
        f.addBootstrap(xmlstream.INIT_FAILED_EVENT, self.init_failed)
        #         self.get_device_info(device)
        self.finished = defer.Deferred()

#     def get_device_info(self, device):
#         if len(device.icons) > 0:
#             icon = device.icons[0]
#             buf = read(open())

    def startService(self):
        self.connector = SRVConnector(self.reactor,
                                      'xmpp-client',
                                      self.jid.host,
                                      self.factory,
                                      defaultPort=5222)
        self.connector.connect()

    def stopService(self):
        for node in self.registrations:
            self.delete_ps_node(node)
        self.xmlstream.sendFooter()
        Service.stopService(self)

    def connected(self, xs):
        #  print 'Connected.'
        #  log.debug('!!!!!!!!!!!!!!!!!!!{app}', app=appreg._applications)
        self.xmlstream = xs

        # Log all traffic
#         xs.rawDataInFn = self.rawDataIn
#         xs.rawDataOutFn = self.rawDataOut

    def disconnected(self, xs):

        print 'Disconnected.'

#         self.finished.callback(None)

    def authenticated(self, xs):
        #  print "Authenticated."

        xs.addObserver('/presence', self.on_presence)
        xs.addObserver('/iq', self.on_iq)

        presence = domish.Element((None, 'presence'))
        uc = domish.Element(
            ('urn:schemas-upnp-org:cloud-1-0', 'ConfigIdCloud'))
        uc['hash'] = 'uda'
        uc.addContent('1.0')
        #  print(uc.toXml())
        presence.addChild(uc)
        #  print(presence.toXml())
        xs.send(presence)
        disco = IQ(xs, 'get')
        disco.addElement(('http://jabber.org/protocol/disco#info', 'query'))
        disco.addCallback(self.check_server)
        disco.send(to='pubsub.xmpp.bertrandverdu.me')
        self.check_ps_nodes()
        self.reactor.callLater(30, self.ping)

    def ping(self):
        def pong(res):
            if res['type'] == 'result':
                #                 log.debug('pong !')
                self.timeout = False
                self.reactor.callLater(30, self.ping)
            else:
                self.log.error('ping error: %s' % res.toXml())
                self.timeout = False
#                 self.startService()

        def check_timeout():
            if self.timeout:
                self.log.error('ping timeout !')
#                 self.connector.connect()

        iq = IQ(self.xmlstream, 'get')
        iq.addElement('ping', 'urn:xmpp:ping')
        self.reactor.callLater(10, check_timeout)
        iq.addCallback(pong)
        self.timeout = True
        iq.send(to=self.jid.host)

    def rawDataIn(self, buf):
        print("Device RECV: %s" %
              unicode(buf, 'utf-8').encode('ascii', 'replace'))

    def rawDataOut(self, buf):
        print("Device SEND: %s" %
              unicode(buf, 'utf-8').encode('ascii', 'replace'))

    def check_server(self, result):
        def display_info(res):
            return
            e = fromstring(res.toXml())
            dump(e)

        self.log.debug("server checked")
        display_info(result)
#         e = fromstring(result.toXml())
#         dump(e)
#         iq = IQ(self.xmlstream, 'get')
#         ps = domish.Element(
#             ('http://jabber.org/protocol/pubsub#owner', 'pubsub'))
#         ps.addElement('default')
#         iq.addChild(ps)
#         iq.addCallback(display_info)
#         iq.send(to='pubsub.' + self.jid.host)
#         print(result.toXml())

    def dump_description(self, dest):
        def sent(res):
            self.log.debug('description sent')
            pass

        self.log.debug('send description')
        #         print(dest['id'])
        if self.description:
            self.log.debug('cached description')
            iq = IQ(self.xmlstream, 'result')
            iq.addRawXml(self.description)
            iq['id'] = dest['id']
        else:
            self.log.debug('generate description')
            iq = IQ(self.xmlstream, 'result')
            query = domish.Element(('urn:schemas-upnp-org:cloud-1-0', 'query'))
            query['type'] = 'described'
            query['name'] = self.device.uuid
            d = tostring(self.device.dump(), encoding='unicode')
            query.addRawXml(d)
            #         print(query.toXml())
            for service in self.device.services:
                s = tostring(service.dump(), encoding='unicode')
                #             print(s)
                query.addRawXml(s)

    #         print(query.toXml())
            self.description = query.toXml()
            iq.addChild(query)
            iq['id'] = dest['id']
#             self.description = iq
#         print(iq.toXml())
        iq.addCallback(sent)
        iq.send(to=dest['from'])

    def check_ps_nodes(self):
        def got_response(node, response):
            if response['type'] in ('error', 'cancel'):
                self.create_ps_node(node)
            elif response['type'] == 'result':
                node_name = '/'.join((self._jid, node[1]))
                if node_name in self.registrations:
                    return
                self.registrations.append(node_name)
                self.log.debug('node {name} registered', name=node_name)
                event = XmppEvent(node_name, self, 'pubsub.' + self.jid.host)
                node[2].subscribe(event, 100)
                self.reactor.callLater(95, self.renew_subscription,
                                       *(node_name, node))
            else:
                self.log.error('unknown response from server: %s' %
                               response.toXml())

        self.log.debug('check nodes: {nodes}', nodes=str(self.nodes))
        IQ_ = IQ  # Basic optimisation...
        element = domish.Element
        for node in self.nodes:
            iq = IQ_(self.xmlstream, 'get')
            query = element(('http://jabber.org/protocol/disco#info', 'query'))
            query['node'] = '/'.join((self._jid, node[1], node[0].name))
            iq.addChild(query)
            iq.addCallback(got_response, node)
            iq.send(to='pubsub.' + self.jid.host)

    def create_ps_node(self, node):
        def registered(node, iq):
            if iq['type'] == 'result':
                node_name = '/'.join((self._jid, node[1]))
                if node_name in self.registrations:
                    return
                event = XmppEvent(node_name, self, 'pubsub.' + self.jid.host)
                node[2].subscribe(event, 100)
                self.reactor.callLater(95, self.renew_subscription,
                                       *(node_name, node))
                self.registrations.append(node_name)
                self.log.debug('node {node} registered', node=node_name)
            else:
                self.log.error('node creation {name} failed:{iq}',
                               name=node,
                               iq=iq.toXml())

        iq = IQ(self.xmlstream, 'set')
        ps = domish.Element(('http://jabber.org/protocol/pubsub', 'pubsub'))
        create = domish.Element((None, 'create'))
        create['node'] = '/'.join((self._jid, node[1], node[0].name))
        ps.addChild(create)
        configure = domish.Element((None, 'configure'))
        x = domish.Element(('jabber:x:data', 'x'))
        x['type'] = 'submit'
        field = domish.Element((None, 'field'))
        field['var'] = 'FORM_TYPE'
        field['type'] = 'hidden'
        field.addElement(
            'value', content='http://jabber.org/protocol/pubsub#node_config')
        x.addChild(field)
        access = domish.Element((None, 'field'))
        access['var'] = 'pubsub#access_model'
        access.addElement('value', content='roster')
        x.addChild(access)
        #         expire = domish.Element((None, 'field'))
        #         expire['var'] = 'pubsub#item_expire'
        #         expire.addElement('value', content='60')
        #         x.addChild(expire)
        last = domish.Element((None, 'field'))
        last['var'] = 'pubsub#send_last_published_item'
        last.addElement('value', content='on_sub_and_presence')
        x.addChild(last)
        configure.addChild(x)
        ps.addChild(configure)
        iq.addChild(ps)
        iq.addCallback(registered, node)
        iq.send(to='pubsub.' + self.jid.host)

    def delete_ps_node(self, node):
        def deleted(res):
            if res['type'] == 'error':
                self.log.error('node deletion failed: %s' % res.toXml())

        iq = IQ(self.xmlstream, 'set')
        ps = domish.Element(
            ('http://jabber.org/protocol/pubsub#owner', 'pubsub'))
        delete = domish.Element((None, 'delete'))
        delete['node'] = node
        ps.addChild(delete)
        iq.addChild(ps)
        iq.send(to='pubsub.' + self.jid.host)

    def renew_subscription(self, name, node):
        self.log.debug('renew %s : %s' % (name, (name in self.registrations)))
        if name in self.registrations:
            self.log.debug('renew: %s' % name)
            event = XmppEvent(name, self, 'pubsub.' + self.jid.host)
            node[2].subscribe(event, 100)
            self.reactor.callLater(95, self.renew_subscription, *(name, node))

    def on_iq(self, iq):
        #         print('received iq: %s' % iq.toXml().encode('utf-8'))
        user, host, res = parse(iq['from'])
        del (res)
        if not user:
            return
        jid = '@'.join((user, host))
        self.log.debug('received request of type {typ} from {user}',
                       typ=iq['type'],
                       user=jid)
        if jid not in self.users and jid != self.user:
            self.log.info('rejected User: %s' % jid)
            return
        if iq['type'] == 'get':
            for child in iq.children:
                if child.name == 'query':
                    if child['type'] == 'description':
                        self.log.debug('description requested')
                        self.dump_description(iq)
        elif iq['type'] == 'set':
            if iq.children[0].name == 'Envelope':
                self.log.debug('received rpc')
                root = iq.children[0]
                #                 print(root.toXml())
                for child in root.children:
                    if child.name == 'Header':
                        res = self.services[
                            child.children[0]['serviceId']]['app'].handle_rpc(
                                root.toXml(), child.children[0]['serviceId'])
                    elif child.name == 'Body':
                        decomposed = child.children[0].uri.split(':')
                        guessed_id = ':'.join(
                            (decomposed[0], decomposed[1],
                             decomposed[2] + 'Id', decomposed[3]))
                        res = self.services[str(guessed_id)]['app'].handle_rpc(
                            root.toXml(), str(guessed_id))
                    else:
                        self.log.warn('bad iq request: %s' % child.name)
                        continue

                    res.addCallback(self.respond_rpc, iq['from'], iq['id'])

    def respond_rpc(self, resp, to, queryID):
        #         print('send: %s' % resp)
        #         self.log.debug('respond rpc: %s' % resp[0][39:])
        res = IQ(self.xmlstream, 'result')
        res['id'] = queryID
        if resp:
            for item in resp:
                res.addRawXml(item[39:].decode('utf-8'))  # Skip the xml header
        res.send(to=to)

    def on_presence(self, presence):
        self.log.debug('received presence: %s' %
                       presence.toXml().encode('utf-8'))
        if presence.hasAttribute('from'):
            user, host, res = parse(presence['from'])
            if presence['from'] in self.active_controllers:
                if presence.hasAttribute('type'):
                    if presence['type'] == 'unavailable':
                        self.active_controllers.remove(presence['from'])
                        self.log.info('User {_from} disconnected',
                                      _from=presence['from'])
                        return
            elif 'ControlPoint' in res:
                if presence.hasAttribute('type'):
                    if presence['type'] == 'unavailable':
                        return
                self.log.info('control point %s added' % presence['from'])
                if len(self.active_controllers) == 0:
                    self.check_ps_nodes()
                self.active_controllers.append(presence['from'])
            del (res)
            jid = '@'.join((user, host))
            if presence.hasAttribute('type'):
                if presence['type'] == 'subscribe':
                    if jid in self.users:
                        self.log.info('received subscription from %s' % jid)
                        if self.users[jid] is False:
                            iq = IQ(self.xmlstream, 'set')
                            query = domish.Element(
                                ('jabber:iq:roster', 'query'))
                            item = domish.Element((None, 'item'))
                            item['jid'] = jid
                            item['name'] = jid
                            item.addElement('group', content='UPnPCloud')
                            query.addChild(item)
                            iq.addChild(query)
                            iq.addCallback(self.subscribed, jid)
                            iq.send()
                    else:
                        self.log.error('subscription for user %s failed: %s' %
                                       (jid, 'Not in user list'))
                        pres = domish.Element((None, 'presence'))
                        pres['type'] = 'unsubscribed'
                        pres['to'] = presence['from']
                        self.xmlstream.send(pres)

    def subscribed(self, jid, result):
        if result['type'] == 'result':
            self.log.info('user %s successfully suscribed' % jid)
            self.users.update({jid: True})
            pres = domish.Element((None, 'presence'))
            pres['type'] = 'subscribed'
            pres['to'] = jid
            self.xmlstream.send(pres)
        else:
            self.log.error('subscription for user %s failed: %s' %
                           (jid, result.toXml()))
            pres = domish.Element((None, 'presence'))
            pres['type'] = 'unsubscribed'
            pres['to'] = jid
            self.xmlstream.send(pres)

    def init_failed(self, failure):
        print "Initialization failed."
        print failure

    def register_art_url(self, url, cloud=False):
        if cloud:
            return None
        newurl = hashlib.md5(url).hexdigest() + url[-4:]
        self.resource.putChild(newurl, static.File(url))
        return self.webserver.weburl % get_default_v4_address() + '/' + newurl
Exemplo n.º 25
0
            0]
        print "If the hostname and port are not specified, the MSRP relay will be discovered"
        print "through the the _msrps._tcp.domain SRV record. If a hostname is specified but"
        print "no port, the default port of 2855 will be used."
    else:
        username, domain = sys.argv[1].split("@", 1)
        cred = X509Credentials(None, None)
        cred.verify_peer = False
        ctx = TLSContext(cred)
        password = getpass()
        if len(sys.argv) == 2:
            factory = MSRPFileReceiverFactory(username, password,
                                              URI(domain, use_tls=True))
            connector = SRVConnector(reactor,
                                     "msrps",
                                     domain,
                                     factory,
                                     connectFuncName="connectTLS",
                                     connectFuncArgs=[ctx])
            connector.connect()
        else:
            relay_host = sys.argv[2]
            if len(sys.argv) == 4:
                relay_port = int(sys.argv[3])
            else:
                relay_port = 2855
            factory = MSRPFileReceiverFactory(
                username, password,
                URI(relay_host, port=relay_port, use_tls=True))
            reactor.connectTLS(relay_host, relay_port, factory, ctx)
        reactor.run()
Exemplo n.º 26
0
 def pickServer(self):
     host, port = SRVConnector.pickServer(self)
     if not self.servers and not self.orderedServers:
         port = 5222
     return host, port
Exemplo n.º 27
0
 def __init__(self, reactor, domain, factory, port=5222):
     self.port=port
     SRVConnector.__init__(self, reactor, 'xmpp-client', domain, factory)
Exemplo n.º 28
0
 def __init__(self, reactor, domain, factory, credentials, tls_reactor):
     self.tls_reactor = tls_reactor
     SRVConnector.__init__(self, reactor, 'xmpp-net', str(domain), factory,
         connectFuncName='connectTLS', connectFuncKwArgs={'credentials':credentials})
Exemplo n.º 29
0
class XMPPClient:
    '''
    The XMPPClients uses the username, server and password to connect to the xmpp server.
    
    A message can be send using the sendMessage function, received presences and messages
    can be processed by a callback function.
    
    If the connection fails or is lost, the client will try to reconnect automatically.
    The disconnectedCallback can be used to catch the connection failed or connection lost event.
    At startup, a watchdog is started: if the server can't authenticate the user within the
    timeOut, the connection will be closed and the disconnectedCallback will be called. 
    '''
    def __init__(self, username, server, password, hostname, timeOut=5):
        self.username = username
        self.server = server
        self.password = password
        self.timeOut = timeOut
        self.hostname = hostname
        self.xmpp_user = None

        self.status = 'NOT_CONNECTED'

        self.messageReceivedCallback = None
        self.presenceReceivedCallback = None
        self.connectedCallback = None
        self.disconnectedCallback = None

        self.connector = None
        self.xmlstream = None

    def start(self):
        ''' Start the xmpp client, opens the connection to the server '''
        if self.status <> 'NOT_CONNECTED':
            raise RuntimeError('The XmppClient has already been started.')

        q.logger.log(
            "[XMPPCLIENT] Starting the xmpp client to " + self.username + "@" +
            self.server, 5)

        self.startup_watchdog = reactor.callLater(self.timeOut,
                                                  self._watchdog_timeout)
        self._connect()

    def stop(self):
        ''' Stop the xmpp client '''
        if self.status == 'NOT_CONNECTED':
            raise RuntimeError('The XmppClient has not yet been started.')

        q.logger.log(
            "[XMPPCLIENT] Stopping the xmpp client to " + self.username + "@" +
            self.server, 5)
        self.connector.disconnect()

    def sendMessage(self, to, type, id, message=' '):
        ''' Send a message
        @param to: The username of the client to send the message to
        @type to: string
        @param type: The type of the message
        @type type: string
        @param id: The id of the message
        @type id: string
        @param message: The message to send
        @type message: string 
        '''
        if self.status <> 'RUNNING':
            raise NotConnectedException()

        q.logger.log(
            "[XMPPCLIENT] Sending message '" + str(id) + "' of type '" +
            str(type) + "' to " + str(to) + " for " + self.username + "@" +
            self.server, 5)

        elemToSend = domish.Element(('jabber:client', 'message'),
                                    attribs={
                                        'to': to + "@" + self.server,
                                        'type': type,
                                        'id': id
                                    })
        body = domish.Element((None, 'body'))
        body.addContent(message)
        elemToSend.addContent(body)
        self.xmlstream.send(elemToSend)

    def sendPresence(self, to=None, type=None):
        ''' Send a presence
        @param to: The username of the client to send the presence to. None=send to all your friends
        @type to: string
        @param type: The type of the presence. Possible values: None=available, unavailable, subscribe, subscribed 
        @type type: string
        '''
        if self.status <> 'RUNNING':
            raise NotConnectedException()

        q.logger.log(
            "[XMPPCLIENT] Sending presence of type '" + str(type) + "' to " +
            str(to) + "'", 5)

        attribs = {}
        if to <> None: attribs['to'] = to + "@" + self.server
        if type <> None: attribs['type'] = type

        presence = domish.Element(('jabber:client', 'presence'),
                                  attribs=attribs)
        self.xmlstream.send(presence)

    def _presence_received(self, elem):
        fromm = elem.getAttribute('from').split("@")[0]
        if not elem.hasAttribute('type'):
            type = 'available'
        else:
            type = elem.getAttribute('type')

        q.logger.log(
            "[XMPPCLIENT] Presence received from '" + fromm + "' of type '" +
            type + "'", 5)

        if self.presenceReceivedCallback:
            self.presenceReceivedCallback(fromm, type)

    def setMessageReceivedCallback(self, callback):
        '''
        @param callback: function to call when a message is received
        @type callback: function that expects 4 params: from, type, id and message
        '''
        self.messageReceivedCallback = callback

    def setPresenceReceivedCallback(self, callback):
        '''
        @param callback: function to call when a presence is received
        @type callback: function that expects 2 params: from and type
        '''
        self.presenceReceivedCallback = callback

    def setDisconnectedCallback(self, callback):
        '''
        Set the function to call when the client is disconnected from the xmpp server,
        if the keepAlive param is True in the constructor, the reconnect will be initiated after this callback.
        @param callback: function to call when the client is disconnected
        @type callback: function that expects 1 param: string containing the reason of the disconnect
        '''
        self.disconnectedCallback = callback

    def setConnectedCallback(self, callback):
        '''
        Set the function to call when the client is connected and authenticated with the xmpp server.
        @param callback: function to call when the client is connected and authenticated
        @type callback: function that expects no params
        '''
        self.connectedCallback = callback

    def _connect(self):
        self.status = 'CONNECTING'

        if self.hostname != None:
            self.xmpp_user = self.username + "@" + self.hostname
        else:
            self.xmpp_user = self.username + "@" + self.server

        q.logger.log(
            "[XMPPCLIENT] Connecting to server %s with xmpp user %s'" %
            (self.server, self.xmpp_user))

        c = client.XMPPClientFactory(jid.JID(self.xmpp_user), self.password)
        c.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, self._connected)
        c.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, self._authenticated)
        c.addBootstrap(xmlstream.INIT_FAILED_EVENT, self._init_failed)
        c.addBootstrap(xmlstream.STREAM_END_EVENT, self._end_stream)

        def _do_connect():
            self.connector = SRVConnector(reactor, 'xmpp-client', self.server,
                                          c)
            self.connector.pickServer = lambda: (self.server, 5222)
            self.connector.connect()

        reactor.callInThread(_do_connect)

    def _connected(self, xmlstream):
        self.status = 'CONNECTED'

        q.logger.log(
            "[XMPPCLIENT] _connected:  Connected to server [%s], trying with usersname [%s]"
            % (self.server, self.xmpp_user))

        # Connected: capture the stream
        self.xmlstream = xmlstream
        self.xmlstream.addObserver('/presence', self._presence_received)
        self.xmlstream.addObserver('/message', self._message_received)

    def _authenticated(self, xmlstream):
        self.status = 'RUNNING'

        q.logger.log(
            "[XMPPCLIENT] Server '" + self.server + "' authenticated user '" +
            self.xmpp_user + "'", 5)

        # Authentication succes: stop the startup watchdog
        if self.startup_watchdog:
            self.startup_watchdog.cancel()
            self.startup_watchdog = None

        # Put the agent controllers status to online
        self.sendPresence()

        if self.connectedCallback:
            self.connectedCallback()

    def _presence_received(self, elem):
        fromm = elem.getAttribute('from').split("@")[0]
        if not elem.hasAttribute('type'):
            type = 'available'
        else:
            type = elem.getAttribute('type')

        q.logger.log(
            "[XMPPCLIENT] Presence received from '" + fromm + "' of type '" +
            type + "'", 5)

        if self.presenceReceivedCallback:
            self.presenceReceivedCallback(fromm, type)

    def _message_received(self, elem):
        fromm = elem.getAttribute('from').split("@")[0]
        type = elem.getAttribute('type')
        id = elem.getAttribute('id')
        message = str(elem.children[0].children[0])

        q.logger.log(
            "[XMPPCLIENT] Message '" + str(id) + "' of type '" + str(type) +
            "'" + "' received from '" + fromm + "'", 5)

        if self.messageReceivedCallback:
            self.messageReceivedCallback(fromm, type, id, message)

    def _init_failed(self, failure):
        self._disconnected('Init failed ' + str(failure))

    def _end_stream(self, xmlstream):
        self._disconnected('Stream ended: connection lost')

    def _watchdog_timeout(self):
        self.connector.disconnect()
        self._disconnected('Connection timed out')

    def _disconnected(self, reason):
        self.status = 'DISCONNECTED'
        q.logger.log("[XMPPCLIENT] Disconnected: " + reason, 4)

        if self.disconnectedCallback:
            self.disconnectedCallback(reason)
 def pickServer(self):
     host, port = SRVConnector.pickServer(self)
     print 'Resolved _%s._%s.%s --> %s:%s' % (self.service, self.protocol,
                                              self.domain, host, port)
     return host, port
Exemplo n.º 31
0
class XMPP(Listener):
    def init(self):
        self.username, self.server = self.mirror('username').split('@')
        self.password = self.mirror('password')
        listener = self.parent().get_listener(self._id)
        self.resource = listener['resource']
        self.nickname = listener['nickname']

        jid = "%s@%s/%s" % (self.username, self.server, self.resource)
        self.jid = JID(jid)
        self.f = client.XMPPClientFactory(self.jid, self.password)

        self.con = SRVConnector(
            reactor, 'xmpp-client', self.jid.host, self.f, defaultPort=5222)
        #self.con.connect()

    def is_twisted(self):
        return True

    def handlers(self):
        # Register event handlers.
        self.f.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, self.on_connected)
        self.f.addBootstrap(xmlstream.STREAM_END_EVENT, self.on_disconnected)
        self.f.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, self.on_authenticated)
        self.f.addBootstrap(xmlstream.INIT_FAILED_EVENT, self.on_init_failed)
        pass

    def signon(self):
        # Log in.
        self.con.connect()
        self.online(True)

    def loop(self):
        pass

    def rawDataIn(self, buf):
        #print "RECV: %s" % unicode(buf, 'utf-8').encode('ascii', 'replace')
        pass

    def rawDataOut(self, buf):
        #print "SEND: %s" % unicode(buf, 'utf-8').encode('ascii', 'replace')
        pass

    def send_message(self, to, content):
        message = domish.Element(('jabber:client', 'message'))
        message['to']   = JID(to).full()
        message['type'] = 'chat'
        message.addElement('body', 'jabber:client', content)
        self.xmlstream.send(message)

    def allow_subscribe(self, to):
        """Respond to an add (subscribe) request by allowing it."""
        message = domish.Element({'jabber:client', 'presence'})
        message['to']   = JID(to).full()
        message['type'] = 'subscribed'
        self.xmlstream.send(message)

    def deny_subscribe(self, to):
        """Respond to somebody removing us from their contact list."""
        message = domish.Element({'jabber:client', 'presence'})
        message['to']   = JID(to).full()
        message['type'] = 'unsubscribed'
        self.xmlstream.send(message)

    def on_connected(self, xs):
        #print 'Connected.'
        self.xmlstream = xs

        # Log all traffic.
        xs.rawDataInFn = self.rawDataIn
        xs.rawDataOutFn = self.rawDataOut

    def on_disconnected(self, xs):
        #print 'Disconnected.'
        pass

    def on_authenticated(self, xs):
        #print 'Authenticated.'
        presence = domish.Element(('jabber:client', 'presence'))
        xs.send(presence)

        # Register event handlers.
        xs.addObserver('/message', self.on_message)
        xs.addObserver('/presence', self.on_presence)
        xs.addObserver('/*', self.debug)
#        xs.sendFooter()
#        reactor.callLater(5, xs.sendFooter)

    def on_init_failed(self, failure):
        print 'Initialization failure.'
        print failure

    def on_message(self, el):
        #print "Received message!"

        # The sender.
        source   = str(el['from'])
        username = singleton.format_name('XMPP', source.split("/")[0])

        # Get the chat body.
        body = None
        for e in el.elements():
            if e.name == 'body':
                if el['type'] == 'chat':
                    body = str(e)

        #print "body:", body
        if body is None:
            return

        reply = singleton.get_reply(self._id, username, body)
        self.send_message(source, reply)

    def on_presence(self, el):
        #print "Received presence!"

        # The sender.
        source   = str(el['from'])
        username = singleton.format_name('XMPP', source.split("/")[0])

        # What type of presence message is this?
        if el['type'] == 'subscribe':
            # Somebody added us to their buddy list. Allow this.
            print "Allowing subscription by {}".format(source)
            self.allow_subscribe(source)
        elif el['type'] == 'unsubscribe':
            # They removed us from their list. Revoke the subscription.
            print "{} deleted us, removing subscription.".format(source)
            self.deny_subscribe(source)

    def debug(self, el):
        print el.toXml().encode('utf-8')

    def on_iq(self, con, iq):
        pass
Exemplo n.º 32
0
 def __init__(self, reactor, domain, factory):
     SRVConnector.__init__(self, reactor, 'xmpp-server', domain, factory)
Exemplo n.º 33
0
    def clientConnectionLost(self, connector, err):
        print "Connection lost"
        print err.value
        reactor.callLater(0, reactor.stop)

if __name__ == "__main__":
    if len(sys.argv) < 2 or len(sys.argv) > 4:
        print "Usage: %s user@domain [relay-hostname [relay-port]]" % sys.argv[0]
        print "If the hostname and port are not specified, the MSRP relay will be discovered"
        print "through the the _msrps._tcp.domain SRV record. If a hostname is specified but"
        print "no port, the default port of 2855 will be used."
    else:
        username, domain = sys.argv[1].split("@", 1)
        cred = X509Credentials(None, None)
        cred.verify_peer = False
        ctx = TLSContext(cred)
        password = getpass()
        if len(sys.argv) == 2:
            factory = MSRPFileReceiverFactory(username, password, URI(domain, use_tls=True))
            connector = SRVConnector(reactor, "msrps", domain, factory, connectFuncName="connectTLS", connectFuncArgs=[ctx])
            connector.connect()
        else:
            relay_host = sys.argv[2]
            if len(sys.argv) == 4:
                relay_port = int(sys.argv[3])
            else:
                relay_port = 2855
            factory = MSRPFileReceiverFactory(username, password, URI(relay_host, port=relay_port, use_tls=True))
            reactor.connectTLS(relay_host, relay_port, factory, ctx)
        reactor.run()
Exemplo n.º 34
0
 def pickServer(self):
     host, port = SRVConnector.pickServer(self)
     print('Resolved _%s._%s.%s --> %s:%s' % (self.service, self.protocol, self.domain, host, port))
     return host, port
Exemplo n.º 35
0
class XMPP(Listener):
    def init(self):
        self.username, self.server = self.mirror('username').split('@')
        self.password = self.mirror('password')
        listener = self.parent().get_listener(self._id)
        self.resource = listener['resource']
        self.nickname = listener['nickname']

        jid = "%s@%s/%s" % (self.username, self.server, self.resource)
        self.jid = JID(jid)
        self.f = client.XMPPClientFactory(self.jid, self.password)

        self.con = SRVConnector(reactor,
                                'xmpp-client',
                                self.jid.host,
                                self.f,
                                defaultPort=5222)
        #self.con.connect()

    def is_twisted(self):
        return True

    def handlers(self):
        # Register event handlers.
        self.f.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT,
                            self.on_connected)
        self.f.addBootstrap(xmlstream.STREAM_END_EVENT, self.on_disconnected)
        self.f.addBootstrap(xmlstream.STREAM_AUTHD_EVENT,
                            self.on_authenticated)
        self.f.addBootstrap(xmlstream.INIT_FAILED_EVENT, self.on_init_failed)
        pass

    def signon(self):
        # Log in.
        self.con.connect()
        self.online(True)

    def loop(self):
        pass

    def rawDataIn(self, buf):
        #print "RECV: %s" % unicode(buf, 'utf-8').encode('ascii', 'replace')
        pass

    def rawDataOut(self, buf):
        #print "SEND: %s" % unicode(buf, 'utf-8').encode('ascii', 'replace')
        pass

    def send_message(self, to, content):
        message = domish.Element(('jabber:client', 'message'))
        message['to'] = JID(to).full()
        message['type'] = 'chat'
        message.addElement('body', 'jabber:client', content)
        self.xmlstream.send(message)

    def allow_subscribe(self, to):
        """Respond to an add (subscribe) request by allowing it."""
        message = domish.Element({'jabber:client', 'presence'})
        message['to'] = JID(to).full()
        message['type'] = 'subscribed'
        self.xmlstream.send(message)

    def deny_subscribe(self, to):
        """Respond to somebody removing us from their contact list."""
        message = domish.Element({'jabber:client', 'presence'})
        message['to'] = JID(to).full()
        message['type'] = 'unsubscribed'
        self.xmlstream.send(message)

    def on_connected(self, xs):
        #print 'Connected.'
        self.xmlstream = xs

        # Log all traffic.
        xs.rawDataInFn = self.rawDataIn
        xs.rawDataOutFn = self.rawDataOut

    def on_disconnected(self, xs):
        #print 'Disconnected.'
        pass

    def on_authenticated(self, xs):
        #print 'Authenticated.'
        presence = domish.Element(('jabber:client', 'presence'))
        xs.send(presence)

        # Register event handlers.
        xs.addObserver('/message', self.on_message)
        xs.addObserver('/presence', self.on_presence)
        xs.addObserver('/*', self.debug)
#        xs.sendFooter()
#        reactor.callLater(5, xs.sendFooter)

    def on_init_failed(self, failure):
        print 'Initialization failure.'
        print failure

    def on_message(self, el):
        #print "Received message!"

        # The sender.
        source = str(el['from'])
        username = singleton.format_name('XMPP', source.split("/")[0])

        # Get the chat body.
        body = None
        for e in el.elements():
            if e.name == 'body':
                if el['type'] == 'chat':
                    body = str(e)

        #print "body:", body
        if body is None:
            return

        reply = singleton.get_reply(self._id, username, body)
        self.send_message(source, reply)

    def on_presence(self, el):
        #print "Received presence!"

        # The sender.
        source = str(el['from'])
        username = singleton.format_name('XMPP', source.split("/")[0])

        # What type of presence message is this?
        if el['type'] == 'subscribe':
            # Somebody added us to their buddy list. Allow this.
            print "Allowing subscription by {}".format(source)
            self.allow_subscribe(source)
        elif el['type'] == 'unsubscribe':
            # They removed us from their list. Revoke the subscription.
            print "{} deleted us, removing subscription.".format(source)
            self.deny_subscribe(source)

    def debug(self, el):
        print el.toXml().encode('utf-8')

    def on_iq(self, con, iq):
        pass
Exemplo n.º 36
0
 def pickServer(self):
     host, port = SRVConnector.pickServer(self)
     if not self.servers and not self.orderedServers:
         port = 5222
     return host, port
Exemplo n.º 37
0
Arquivo: xmpp.py Projeto: Ri0n/Hermes
 def __init__(self, reactor, domain, factory):
     SRVConnector.__init__(self, reactor, 'xmpp-client', domain, factory)
Exemplo n.º 38
0
 def __init__(self, reactor, domain, factory):
     SRVConnector.__init__(self, reactor, 'xmpp-server', domain, factory)
Exemplo n.º 39
0
 def __init__(self, reactor, domain, factory):
     SRVConnector.__init__(self, reactor, 'xmpp-client', domain, factory)
Exemplo n.º 40
0
 def __init__(self, client_reactor, domain, factory):
     """ Init """
     SRVConnector.__init__(self, client_reactor, 'xmpp-client', domain, factory)
     self.timeout = [1,3]
Exemplo n.º 41
0
 def _do_connect():
     self.connector = SRVConnector(reactor, 'xmpp-client', self.server,
                                   c)
     self.connector.pickServer = lambda: (self.server, 5222)
     self.connector.connect()
Exemplo n.º 42
0
 def __init__(self, client_reactor, domain, factory):
     """ Init """
     SRVConnector.__init__(self, client_reactor, 'xmpp-client', domain,
                           factory)
     self.timeout = [1, 3]
Exemplo n.º 43
0
class XMPPClient:
    '''
    The XMPPClients uses the username, server and password to connect to the xmpp server.
    
    A message can be send using the sendMessage function, received presences and messages
    can be processed by a callback function.
    
    If the connection fails or is lost, the client will try to reconnect automatically.
    The disconnectedCallback can be used to catch the connection failed or connection lost event.
    At startup, a watchdog is started: if the server can't authenticate the user within the
    timeOut, the connection will be closed and the disconnectedCallback will be called. 
    '''
    
    def __init__(self, username, server, password, hostname, timeOut=5):
        self.username = username
        self.server = server
        self.password = password
        self.timeOut = timeOut
        self.hostname = hostname
        self.xmpp_user = None

        self.status = 'NOT_CONNECTED'
        
        self.messageReceivedCallback = None
        self.presenceReceivedCallback = None
        self.connectedCallback = None
        self.disconnectedCallback = None
        
        self.connector = None
        self.xmlstream = None
    
    def start(self):
        ''' Start the xmpp client, opens the connection to the server '''
        if self.status <> 'NOT_CONNECTED':
            raise RuntimeError('The XmppClient has already been started.')
        
        q.logger.log("[XMPPCLIENT] Starting the xmpp client to " + self.username + "@" + self.server, 5)
        
        self.startup_watchdog = reactor.callLater(self.timeOut, self._watchdog_timeout)
        self._connect()
    
    def stop(self):
        ''' Stop the xmpp client '''
        if self.status == 'NOT_CONNECTED':
            raise RuntimeError('The XmppClient has not yet been started.')
        
        q.logger.log("[XMPPCLIENT] Stopping the xmpp client to " + self.username + "@" + self.server, 5)
        self.connector.disconnect()
    
    def sendMessage(self, to, type, id, message=' '):
        ''' Send a message
        @param to: The username of the client to send the message to
        @type to: string
        @param type: The type of the message
        @type type: string
        @param id: The id of the message
        @type id: string
        @param message: The message to send
        @type message: string 
        '''
        if self.status <> 'RUNNING':
            raise NotConnectedException()
        
        q.logger.log("[XMPPCLIENT] Sending message '" + str(id) + "' of type '" + str(type) +"' to " + str(to) + " for " + self.username + "@" + self.server, 5)
        
        elemToSend = domish.Element(('jabber:client','message'), attribs={'to':to+"@"+self.server, 'type':type, 'id':id})
        body = domish.Element((None, 'body'))
        body.addContent(message)
        elemToSend.addContent(body)
        self.xmlstream.send(elemToSend)
    
    def sendPresence(self, to=None, type=None):
        ''' Send a presence
        @param to: The username of the client to send the presence to. None=send to all your friends
        @type to: string
        @param type: The type of the presence. Possible values: None=available, unavailable, subscribe, subscribed 
        @type type: string
        '''
        if self.status <> 'RUNNING':
            raise NotConnectedException()
        
        q.logger.log("[XMPPCLIENT] Sending presence of type '" + str(type) +"' to " + str(to) + "'", 5)
        
        attribs={}
        if to <> None: attribs['to'] =  to+"@"+self.server
        if type <> None: attribs['type'] = type
        
        presence = domish.Element(('jabber:client','presence'), attribs=attribs)
        self.xmlstream.send(presence)
    
    def _presence_received(self, elem):
        fromm = elem.getAttribute('from').split("@")[0]
        if not elem.hasAttribute('type'):
            type = 'available'
        else:
            type = elem.getAttribute('type')
            
        q.logger.log("[XMPPCLIENT] Presence received from '" + fromm + "' of type '" + type +"'", 5)
        
        if self.presenceReceivedCallback:
            self.presenceReceivedCallback(fromm, type)                
    
    def setMessageReceivedCallback(self, callback):
        '''
        @param callback: function to call when a message is received
        @type callback: function that expects 4 params: from, type, id and message
        '''
        self.messageReceivedCallback = callback
        
    def setPresenceReceivedCallback(self, callback):
        '''
        @param callback: function to call when a presence is received
        @type callback: function that expects 2 params: from and type
        '''
        self.presenceReceivedCallback = callback
    
    def setDisconnectedCallback(self, callback):
        '''
        Set the function to call when the client is disconnected from the xmpp server,
        if the keepAlive param is True in the constructor, the reconnect will be initiated after this callback.
        @param callback: function to call when the client is disconnected
        @type callback: function that expects 1 param: string containing the reason of the disconnect
        '''
        self.disconnectedCallback = callback
        
    def setConnectedCallback(self, callback):
        '''
        Set the function to call when the client is connected and authenticated with the xmpp server.
        @param callback: function to call when the client is connected and authenticated
        @type callback: function that expects no params
        '''
        self.connectedCallback = callback
    
    def _connect(self):
        self.status = 'CONNECTING'
       
        if self.hostname != None:
            self.xmpp_user = self.username+"@"+self.hostname
        else:
            self.xmpp_user = self.username+"@"+self.server

        q.logger.log("[XMPPCLIENT] Connecting to server %s with xmpp user %s'" % (self.server, self.xmpp_user) )

        c = client.XMPPClientFactory(jid.JID(self.xmpp_user), self.password)
        c.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, self._connected)
        c.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, self._authenticated)
        c.addBootstrap(xmlstream.INIT_FAILED_EVENT, self._init_failed)
        c.addBootstrap(xmlstream.STREAM_END_EVENT, self._end_stream)

        def _do_connect():
            self.connector = SRVConnector(reactor,'xmpp-client' ,self.server, c)
            self.connector.pickServer =  lambda: (self.server, 5222)
            self.connector.connect()
    
        reactor.callInThread(_do_connect)
        
    def _connected(self, xmlstream):
        self.status = 'CONNECTED'
            
        q.logger.log("[XMPPCLIENT] _connected:  Connected to server [%s], trying with usersname [%s]" % (self.server, self.xmpp_user))
        
        # Connected: capture the stream
        self.xmlstream = xmlstream
        self.xmlstream.addObserver('/presence', self._presence_received)
        self.xmlstream.addObserver('/message',  self._message_received)
    
    def _authenticated(self, xmlstream):
        self.status = 'RUNNING'
        
        q.logger.log("[XMPPCLIENT] Server '" + self.server + "' authenticated user '" + self.xmpp_user + "'", 5)
        
        # Authentication succes: stop the startup watchdog
        if self.startup_watchdog:
            self.startup_watchdog.cancel()
            self.startup_watchdog = None
        
        # Put the agent controllers status to online 
        self.sendPresence()
        
        if self.connectedCallback:
            self.connectedCallback()
    
    def _presence_received(self, elem):
        fromm = elem.getAttribute('from').split("@")[0]
        if not elem.hasAttribute('type'):
            type = 'available'
        else:
            type = elem.getAttribute('type')
            
        q.logger.log("[XMPPCLIENT] Presence received from '" + fromm + "' of type '" + type +"'", 5)
        
        if self.presenceReceivedCallback:
            self.presenceReceivedCallback(fromm, type)                
    
    def _message_received(self, elem):
        fromm = elem.getAttribute('from').split("@")[0]
        type = elem.getAttribute('type')
        id = elem.getAttribute('id')
        message = str(elem.children[0].children[0])
        
        q.logger.log("[XMPPCLIENT] Message '" + str(id) + "' of type '" + str(type) +"'" + "' received from '" + fromm + "'", 5)
        
        if self.messageReceivedCallback:
            self.messageReceivedCallback(fromm, type, id, message)
    
    def _init_failed(self, failure):
        self._disconnected('Init failed ' + str(failure))
    
    def _end_stream(self, xmlstream):
        self._disconnected('Stream ended: connection lost')
        
    def _watchdog_timeout(self):
        self.connector.disconnect()
        self._disconnected('Connection timed out')

    def _disconnected(self, reason):
        self.status = 'DISCONNECTED'
        q.logger.log("[XMPPCLIENT] Disconnected: " + reason, 4)
        
        if self.disconnectedCallback:
            self.disconnectedCallback(reason)