示例#1
0
    def connect(self, address=tuple(), use_ssl=False,
                force_starttls=True, disable_starttls=False):
        """Connect to the XMPP server.

        When no address is given, a SRV lookup for the server will
        be attempted. If that fails, the server user in the JID
        will be used.

        :param address: A tuple containing the server's host and port.
        :param reattempt: If ``True``, repeat attempting to connect if an
                         error occurs. Defaults to ``True``.
        :param use_tls: Indicates if TLS should be used for the
                        connection. Defaults to ``True``.
        :param use_ssl: Indicates if the older SSL connection method
                        should be used. Defaults to ``False``.
        """

        # If an address was provided, disable using DNS SRV lookup;
        # otherwise, use the domain from the client JID with the standard
        # XMPP client port and allow SRV lookup.
        if address:
            self.dns_service = None
        else:
            address = (self.boundjid.host, 5222)
            self.dns_service = 'xmpp-client'

        return XMLStream.connect(self, address[0], address[1], use_ssl=use_ssl,
                                 force_starttls=force_starttls, disable_starttls=disable_starttls)
示例#2
0
    def connect(self, host=None, port=None, use_ssl=False,
                      use_tls=False, reattempt=True):
        """Connect to the server.

        Setting ``reattempt`` to ``True`` will cause connection attempts to
        be made every second until a successful connection is established.

        :param host: The name of the desired server for the connection.
                     Defaults to :attr:`server_host`.
        :param port: Port to connect to on the server.
                     Defauts to :attr:`server_port`.
        :param use_ssl: Flag indicating if SSL should be used by connecting
                        directly to a port using SSL.
        :param use_tls: Flag indicating if TLS should be used, allowing for
                        connecting to a port without using SSL immediately and
                        later upgrading the connection.
        :param reattempt: Flag indicating if the socket should reconnect
                          after disconnections.
        """
        if host is None:
            host = self.server_host
        if port is None:
            port = self.server_port

        self.server_name = self.boundjid.host

        if use_tls:
            log.info("XEP-0114 components can not use TLS")

        log.debug("Connecting to %s:%s", host, port)
        return XMLStream.connect(self, host=host, port=port,
                                       use_ssl=use_ssl,
                                       use_tls=False,
                                       reattempt=reattempt)
示例#3
0
    def connect(self,
                address=tuple(),
                use_ssl=False,
                force_starttls=True,
                disable_starttls=False):
        """Connect to the XMPP server.

        When no address is given, a SRV lookup for the server will
        be attempted. If that fails, the server user in the JID
        will be used.

        :param address: A tuple containing the server's host and port.
        :param use_tls: Indicates if TLS should be used for the
                        connection. Defaults to ``True``.
        :param use_ssl: Indicates if the older SSL connection method
                        should be used. Defaults to ``False``.
        """

        # If an address was provided, disable using DNS SRV lookup;
        # otherwise, use the domain from the client JID with the standard
        # XMPP client port and allow SRV lookup.
        if address:
            self.dns_service = None
        else:
            address = (self.boundjid.host, 5222)
            self.dns_service = 'xmpp-client'

        return XMLStream.connect(self,
                                 address[0],
                                 address[1],
                                 use_ssl=use_ssl,
                                 force_starttls=force_starttls,
                                 disable_starttls=disable_starttls)
示例#4
0
    def connect(self, host=None, port=None, use_ssl=False):
        """Connect to the server.


        :param host: The name of the desired server for the connection.
                     Defaults to :attr:`server_host`.
        :param port: Port to connect to on the server.
                     Defauts to :attr:`server_port`.
        :param use_ssl: Flag indicating if SSL should be used by connecting
                        directly to a port using SSL.
        """
        if host is None:
            host = self.server_host
        if port is None:
            port = self.server_port

        self.server_name = self.boundjid.host

        log.debug("Connecting to %s:%s", host, port)
        return XMLStream.connect(self, host=host, port=port, use_ssl=use_ssl)
示例#5
0
    def connect(self, host=None, port=None, use_ssl=False):
        """Connect to the server.


        :param host: The name of the desired server for the connection.
                     Defaults to :attr:`server_host`.
        :param port: Port to connect to on the server.
                     Defauts to :attr:`server_port`.
        :param use_ssl: Flag indicating if SSL should be used by connecting
                        directly to a port using SSL.
        """
        if host is None:
            host = self.server_host
        if port is None:
            port = self.server_port

        self.server_name = self.boundjid.host

        log.debug("Connecting to %s:%s", host, port)
        return XMLStream.connect(self, host=host, port=port,
                                       use_ssl=use_ssl)
示例#6
0
    def __init__(self, jid='', default_ns='jabber:client', **kwargs):
        XMLStream.__init__(self, **kwargs)

        self.default_ns = default_ns
        self.stream_ns = 'http://etherx.jabber.org/streams'
        self.namespace_map[self.stream_ns] = 'stream'

        #: An identifier for the stream as given by the server.
        self.stream_id = None

        #: The JabberID (JID) requested for this connection.
        self.requested_jid = JID(jid)

        #: The JabberID (JID) used by this connection,
        #: as set after session binding. This may even be a
        #: different bare JID than what was requested.
        self.boundjid = JID(jid)

        self._expected_server_name = self.boundjid.host
        self._redirect_attempts = 0

        #: The maximum number of consecutive see-other-host
        #: redirections that will be followed before quitting.
        self.max_redirects = 5

        self.session_bind_event = asyncio.Event()

        #: A dictionary mapping plugin names to plugins.
        self.plugin = PluginManager(self)

        #: Configuration options for whitelisted plugins.
        #: If a plugin is registered without any configuration,
        #: and there is an entry here, it will be used.
        self.plugin_config = {}

        #: A list of plugins that will be loaded if
        #: :meth:`register_plugins` is called.
        self.plugin_whitelist = []

        #: The main roster object. This roster supports multiple
        #: owner JIDs, as in the case for components. For clients
        #: which only have a single JID, see :attr:`client_roster`.
        self.roster = roster.Roster(self)
        self.roster.add(self.boundjid)

        #: The single roster for the bound JID. This is the
        #: equivalent of::
        #:
        #:     self.roster[self.boundjid.bare]
        self.client_roster = self.roster[self.boundjid]

        #: The distinction between clients and components can be
        #: important, primarily for choosing how to handle the
        #: ``'to'`` and ``'from'`` JIDs of stanzas.
        self.is_component = False

        #: Messages may optionally be tagged with ID values. Setting
        #: :attr:`use_message_ids` to `True` will assign all outgoing
        #: messages an ID. Some plugin features require enabling
        #: this option.
        self.use_message_ids = False

        #: Presence updates may optionally be tagged with ID values.
        #: Setting :attr:`use_message_ids` to `True` will assign all
        #: outgoing messages an ID.
        self.use_presence_ids = False

        #: The API registry is a way to process callbacks based on
        #: JID+node combinations. Each callback in the registry is
        #: marked with:
        #:
        #:   - An API name, e.g. xep_0030
        #:   - The name of an action, e.g. get_info
        #:   - The JID that will be affected
        #:   - The node that will be affected
        #:
        #: API handlers with no JID or node will act as global handlers,
        #: while those with a JID and no node will service all nodes
        #: for a JID, and handlers with both a JID and node will be
        #: used only for that specific combination. The handler that
        #: provides the most specificity will be used.
        self.api = APIRegistry(self)

        #: Flag indicating that the initial presence broadcast has
        #: been sent. Until this happens, some servers may not
        #: behave as expected when sending stanzas.
        self.sentpresence = False

        #: A reference to :mod:`slixmpp.stanza` to make accessing
        #: stanza classes easier.
        self.stanza = stanza

        self.register_handler(
            Callback('IM',
                     MatchXPath('{%s}message/{%s}body' % (self.default_ns,
                                                          self.default_ns)),
                     self._handle_message))

        self.register_handler(
            Callback('IMError',
                     MatchXPath('{%s}message/{%s}error' % (self.default_ns,
                                                           self.default_ns)),
                     self._handle_message_error))

        self.register_handler(
            Callback('Presence',
                     MatchXPath("{%s}presence" % self.default_ns),
                     self._handle_presence))

        self.register_handler(
            Callback('Stream Error',
                     MatchXPath("{%s}error" % self.stream_ns),
                     self._handle_stream_error))

        self.add_event_handler('session_start',
                               self._handle_session_start)
        self.add_event_handler('disconnected',
                               self._handle_disconnected)
        self.add_event_handler('presence_available',
                               self._handle_available)
        self.add_event_handler('presence_dnd',
                               self._handle_available)
        self.add_event_handler('presence_xa',
                               self._handle_available)
        self.add_event_handler('presence_chat',
                               self._handle_available)
        self.add_event_handler('presence_away',
                               self._handle_available)
        self.add_event_handler('presence_unavailable',
                               self._handle_unavailable)
        self.add_event_handler('presence_subscribe',
                               self._handle_subscribe)
        self.add_event_handler('presence_subscribed',
                               self._handle_subscribed)
        self.add_event_handler('presence_unsubscribe',
                               self._handle_unsubscribe)
        self.add_event_handler('presence_unsubscribed',
                               self._handle_unsubscribed)
        self.add_event_handler('roster_subscription_request',
                               self._handle_new_subscription)

        # Set up the XML stream with XMPP's root stanzas.
        self.register_stanza(Message)
        self.register_stanza(Iq)
        self.register_stanza(Presence)
        self.register_stanza(StreamError)

        # Initialize a few default stanza plugins.
        register_stanza_plugin(Iq, Roster)
示例#7
0
 def process(self, *, forever=True, timeout=None):
     self.init_plugins()
     XMLStream.process(self, forever=forever, timeout=timeout)
示例#8
0
    def __init__(self, jid='', default_ns='jabber:client', **kwargs):
        XMLStream.__init__(self, **kwargs)

        self.default_ns = default_ns
        self.stream_ns = 'http://etherx.jabber.org/streams'
        self.namespace_map[self.stream_ns] = 'stream'

        #: An identifier for the stream as given by the server.
        self.stream_id = None

        #: The JabberID (JID) requested for this connection.
        self.requested_jid = JID(jid)

        #: The JabberID (JID) used by this connection,
        #: as set after session binding. This may even be a
        #: different bare JID than what was requested.
        self.boundjid = JID(jid)

        self._expected_server_name = self.boundjid.host
        self._redirect_attempts = 0

        #: The maximum number of consecutive see-other-host
        #: redirections that will be followed before quitting.
        self.max_redirects = 5

        self.session_bind_event = asyncio.Event()

        #: A dictionary mapping plugin names to plugins.
        self.plugin = PluginManager(self)

        #: Configuration options for whitelisted plugins.
        #: If a plugin is registered without any configuration,
        #: and there is an entry here, it will be used.
        self.plugin_config = {}

        #: A list of plugins that will be loaded if
        #: :meth:`register_plugins` is called.
        self.plugin_whitelist = []

        #: The main roster object. This roster supports multiple
        #: owner JIDs, as in the case for components. For clients
        #: which only have a single JID, see :attr:`client_roster`.
        self.roster = roster.Roster(self)
        self.roster.add(self.boundjid)

        #: The single roster for the bound JID. This is the
        #: equivalent of::
        #:
        #:     self.roster[self.boundjid.bare]
        self.client_roster = self.roster[self.boundjid]

        #: The distinction between clients and components can be
        #: important, primarily for choosing how to handle the
        #: ``'to'`` and ``'from'`` JIDs of stanzas.
        self.is_component = False

        #: Messages may optionally be tagged with ID values. Setting
        #: :attr:`use_message_ids` to `True` will assign all outgoing
        #: messages an ID. Some plugin features require enabling
        #: this option.
        self.use_message_ids = True

        #: Presence updates may optionally be tagged with ID values.
        #: Setting :attr:`use_message_ids` to `True` will assign all
        #: outgoing messages an ID.
        self.use_presence_ids = True

        #: XEP-0359 <origin-id/> tag that gets added to <message/> stanzas.
        self.use_origin_id = True

        #: The API registry is a way to process callbacks based on
        #: JID+node combinations. Each callback in the registry is
        #: marked with:
        #:
        #:   - An API name, e.g. xep_0030
        #:   - The name of an action, e.g. get_info
        #:   - The JID that will be affected
        #:   - The node that will be affected
        #:
        #: API handlers with no JID or node will act as global handlers,
        #: while those with a JID and no node will service all nodes
        #: for a JID, and handlers with both a JID and node will be
        #: used only for that specific combination. The handler that
        #: provides the most specificity will be used.
        self.api = APIRegistry(self)

        #: Flag indicating that the initial presence broadcast has
        #: been sent. Until this happens, some servers may not
        #: behave as expected when sending stanzas.
        self.sentpresence = False

        #: A reference to :mod:`slixmpp.stanza` to make accessing
        #: stanza classes easier.
        self.stanza = stanza

        self.register_handler(
            Callback(
                'IM',
                MatchXPath('{%s}message/{%s}body' %
                           (self.default_ns, self.default_ns)),
                self._handle_message))

        self.register_handler(
            Callback(
                'IMError',
                MatchXPath('{%s}message/{%s}error' %
                           (self.default_ns, self.default_ns)),
                self._handle_message_error))

        self.register_handler(
            Callback('Presence', MatchXPath("{%s}presence" % self.default_ns),
                     self._handle_presence))

        self.register_handler(
            Callback('Stream Error', MatchXPath("{%s}error" % self.stream_ns),
                     self._handle_stream_error))

        self.add_event_handler('session_start', self._handle_session_start)
        self.add_event_handler('disconnected', self._handle_disconnected)
        self.add_event_handler('presence_available', self._handle_available)
        self.add_event_handler('presence_dnd', self._handle_available)
        self.add_event_handler('presence_xa', self._handle_available)
        self.add_event_handler('presence_chat', self._handle_available)
        self.add_event_handler('presence_away', self._handle_available)
        self.add_event_handler('presence_unavailable',
                               self._handle_unavailable)
        self.add_event_handler('presence_subscribe', self._handle_subscribe)
        self.add_event_handler('presence_subscribed', self._handle_subscribed)
        self.add_event_handler('presence_unsubscribe',
                               self._handle_unsubscribe)
        self.add_event_handler('presence_unsubscribed',
                               self._handle_unsubscribed)
        self.add_event_handler('roster_subscription_request',
                               self._handle_new_subscription)

        # Set up the XML stream with XMPP's root stanzas.
        self.register_stanza(Message)
        self.register_stanza(Iq)
        self.register_stanza(Presence)
        self.register_stanza(StreamError)

        # Initialize a few default stanza plugins.
        register_stanza_plugin(Iq, Roster)
示例#9
0
 def process(self, *, forever=True, timeout=None):
     self.init_plugins()
     XMLStream.process(self, forever=forever, timeout=timeout)
示例#10
0
    def __init__(self):
        # BaseXMPP does way too much crap in its __init__,
        # we'll have to skip it and do stuff ourselves
        XMLStream.__init__(self)
        self.default_ns = 'jabber:client'
        self.stream_ns = 'http://etherx.jabber.org/streams'
        self.namespace_map[self.stream_ns] = 'stream'
        self.requested_jid = JID()
        self.boundjid = JID()
        self.session_bind_event = asyncio.Event()
        self.plugin = PluginManager(self)
        self.plugin_config = {}
        self.is_component = True
        self.use_message_ids = False
        self.use_presence_ids = False
        self.api = APIRegistry(self)
        self.register_stanza(Iq)
        self.register_stanza(StreamError)
        self.authenticated = True # keep slixmpp's xep_0078 from doing stupid stuff

        # And now for our own initialization...
        self.logger_extra = {'sid': '', 'jid': ''}
        self.logger = logging.LoggerAdapter(
            logging.getLogger('xmppserver.stream'),
            self.logger_extra)
        self.ipc_logger = logging.LoggerAdapter(
            logging.getLogger('xmppserver.ipc'),
            self.logger_extra)
        self.web_user = None
        self.bound_user = None
        self.host = settings.DOMAIN
        self.kicked = False
        self._auth_hook = None
        self._roster_hook = None
        self._session_hook = None
        self.version = None
        self.default_lang = 'en'
        self.recv_task = None
        self.channel_name = None
        self.group_name = None
        self.channel_layer = get_channel_layer('xmppserver')

        self.register_plugin('xep_0086') # legacy error codes

        self.features = Features(self)
        self.disco = Disco(self)
        self.auth = Auth(self)
        self.registration = Registration(self)
        self.ping = Ping(self)
        # we only need the following components
        # after the client has authenticated.
        self.roster = None
        self.presence = None
        self.messaging = None

        self.register_handler(
            Callback('Remote Iq',
                     RemoteStanzaPath('iq'),
                     self._handle_iq))

        self.logger.debug('Creating stream')