slixmpp/docs/architecture.rst

151 lines
5.4 KiB
ReStructuredText
Raw Normal View History

2011-08-13 00:33:32 +00:00
.. index:: XMLStream, BaseXMPP, ClientXMPP, ComponentXMPP
2014-07-17 12:19:04 +00:00
Slixmpp Architecture
2011-08-13 00:33:32 +00:00
======================
2014-07-17 12:19:04 +00:00
The core of Slixmpp is contained in four classes: ``XMLStream``,
2011-08-13 00:33:32 +00:00
``BaseXMPP``, ``ClientXMPP``, and ``ComponentXMPP``. Along side this
stack is a library for working with XML objects that eliminates most
of the tedium of creating/manipulating XML.
.. image:: _static/images/arch_layers.png
:height: 300px
:align: center
.. index:: XMLStream
The Foundation: XMLStream
-------------------------
2014-07-17 12:19:04 +00:00
:class:`~slixmpp.xmlstream.xmlstream.XMLStream` is a mostly XMPP-agnostic
2011-11-22 23:25:24 +00:00
class whose purpose is to read and write from a bi-directional XML stream.
It also allows for callback functions to execute when XML matching given
patterns is received; these callbacks are also referred to as :term:`stream
handlers <stream handler>`. The class also provides a basic eventing system
which can be triggered either manually or on a timed schedule.
2011-08-13 00:33:32 +00:00
The event loop
~~~~~~~~~~~~~~
:class:`~slixmpp.xmlstream.xmlstream.XMLStream` instances inherit the
:class:`asyncio.BaseProtocol` class, and therefore do not have to handle
reads and writes directly, but receive data through
:meth:`~slixmpp.xmlstream.xmlstream.XMLStream.data_received` and write
data in the socket transport.
Upon receiving data, :term:`stream handlers <stream handler>` are run
immediately, except if they are coroutines, in which case they are
scheduled using :meth:`asyncio.async`.
:term:`Event handlers <event handler>` (which are called inside
:term:`stream handlers <stream handler>`) work the same way.
2011-08-13 00:33:32 +00:00
How XML Text is Turned into Action
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To demonstrate the flow of information, let's consider what happens
when this bit of XML is received (with an assumed namespace of
``jabber:client``):
.. code-block:: xml
<message to="user@example.com" from="friend@example.net">
<body>Hej!</body>
</message>
#. **Convert XML strings into objects.**
2011-08-13 00:33:32 +00:00
Incoming text is parsed and converted into XML objects (using
ElementTree) which are then wrapped into what are referred to as
:term:`Stanza objects <stanza object>`. The appropriate class for the
new object is determined using a map of namespaced element names to
classes.
2014-07-17 12:19:04 +00:00
Our incoming XML is thus turned into a :class:`~slixmpp.stanza.Message`
2011-11-22 23:25:24 +00:00
:term:`stanza object` because the namespaced element name
``{jabber:client}message`` is associated with the class
2014-07-17 12:19:04 +00:00
:class:`~slixmpp.stanza.Message`.
2011-08-13 00:33:32 +00:00
#. **Match stanza objects to callbacks.**
2011-08-13 00:33:32 +00:00
These objects are then compared against the stored patterns associated
with the registered callback handlers.
2011-08-13 00:33:32 +00:00
Each handler matching our :term:`stanza object` is then added to a list.
2011-08-13 00:33:32 +00:00
#. **Processing callbacks**
2011-08-13 00:33:32 +00:00
Every handler in the list is then called with the :term:`stanza object`
as a parameter; if the handler is a
:class:`~slixmpp.xmlstream.handler.CoroutineCallback`
then it will be scheduled in the event loop using :meth:`asyncio.async`
instead of run.
2011-08-13 00:33:32 +00:00
#. **Raise Custom Events**
2011-08-13 00:33:32 +00:00
Since a :term:`stream handler` shouldn't block, if extensive processing
for a stanza is required (such as needing to send and receive an
2014-07-17 12:19:04 +00:00
:class:`~slixmpp.stanza.Iq` stanza), then custom events must be used.
2011-11-22 23:25:24 +00:00
These events are not explicitly tied to the incoming XML stream and may
be raised at any time.
2011-08-13 00:33:32 +00:00
In contrast to :term:`stream handlers <stream handler>`, these functions
are referred to as :term:`event handlers <event handler>`.
2011-08-13 00:33:32 +00:00
2011-11-22 23:25:24 +00:00
The code for :meth:`BaseXMPP._handle_message` follows this pattern, and
raises a ``'message'`` event
2011-08-13 00:33:32 +00:00
.. code-block:: python
2011-08-13 00:33:32 +00:00
self.event('message', msg)
2011-08-13 00:33:32 +00:00
#. **Process Custom Events**
2011-08-13 00:33:32 +00:00
The :term:`event handlers <event handler>` are then executed, passing
the stanza as the only argument.
2011-08-13 00:33:32 +00:00
.. note::
2014-08-17 19:53:34 +00:00
Events may be raised without needing :term:`stanza objects <stanza object>`.
For example, you could use ``self.event('custom', {'a': 'b'})``.
You don't even need any arguments: ``self.event('no_parameters')``.
2011-08-13 00:33:32 +00:00
However, every event handler MUST accept at least one argument.
Finally, after a long trek, our message is handed off to the user's
custom handler in order to do awesome stuff::
reply = msg.reply()
reply['body'] = "Hey! This is awesome!"
reply.send()
2011-08-13 00:33:32 +00:00
.. index:: BaseXMPP, XMLStream
Raising XMPP Awareness: BaseXMPP
--------------------------------
2014-07-17 12:19:04 +00:00
While :class:`~slixmpp.xmlstream.xmlstream.XMLStream` attempts to shy away
from anything too XMPP specific, :class:`~slixmpp.basexmpp.BaseXMPP`'s
2011-11-22 23:25:24 +00:00
sole purpose is to provide foundational support for sending and receiving
XMPP stanzas. This support includes registering the basic message,
presence, and iq stanzas, methods for creating and sending stanzas, and
default handlers for incoming messages and keeping track of presence
notifications.
2011-08-13 00:33:32 +00:00
The plugin system for adding new XEP support is also maintained by
2014-07-17 12:19:04 +00:00
:class:`~slixmpp.basexmpp.BaseXMPP`.
2011-08-13 00:33:32 +00:00
.. index:: ClientXMPP, BaseXMPP
ClientXMPP
----------
2014-07-17 12:19:04 +00:00
:class:`~slixmpp.clientxmpp.ClientXMPP` extends
:class:`~slixmpp.clientxmpp.BaseXMPP` with additional logic for connecting
2011-11-22 23:25:24 +00:00
to an XMPP server by performing DNS lookups. It also adds support for stream
2011-08-13 00:33:32 +00:00
features such as STARTTLS and SASL.
.. index:: ComponentXMPP, BaseXMPP
ComponentXMPP
-------------
2014-07-17 12:19:04 +00:00
:class:`~slixmpp.componentxmpp.ComponentXMPP` is only a thin layer on top of
:class:`~slixmpp.basexmpp.BaseXMPP` that implements the component handshake
2011-11-22 23:25:24 +00:00
protocol.