~emesene-team/emesene/master

« back to all changes in this revision

Viewing changes to emesene/e3/xmpp/SleekXMPP/docs/architecture.rst

  • Committer: Riccardo (C10uD)
  • Date: 2012-07-01 16:54:34 UTC
  • Revision ID: git-v1:17ed298a3acb830f76aa2703351993cff749ed35
import2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
.. index:: XMLStream, BaseXMPP, ClientXMPP, ComponentXMPP
 
2
 
 
3
SleekXMPP Architecture
 
4
======================
 
5
 
 
6
The core of SleekXMPP is contained in four classes: ``XMLStream``,
 
7
``BaseXMPP``, ``ClientXMPP``, and ``ComponentXMPP``. Along side this
 
8
stack is a library for working with XML objects that eliminates most
 
9
of the tedium of creating/manipulating XML.
 
10
 
 
11
.. image:: _static/images/arch_layers.png
 
12
    :height: 300px
 
13
    :align: center
 
14
 
 
15
 
 
16
.. index:: XMLStream
 
17
 
 
18
The Foundation: XMLStream
 
19
-------------------------
 
20
:class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` is a mostly XMPP-agnostic
 
21
class whose purpose is to read and write from a bi-directional XML stream.
 
22
It also allows for callback functions to execute when XML matching given
 
23
patterns is received; these callbacks are also referred to as :term:`stream
 
24
handlers <stream handler>`. The class also provides a basic eventing system
 
25
which can be triggered either manually or on a timed schedule.
 
26
 
 
27
The Main Threads
 
28
~~~~~~~~~~~~~~~~
 
29
:class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` instances run using at
 
30
least three background threads: the send thread, the read thread, and the
 
31
scheduler thread. The send thread is in charge of monitoring the send queue
 
32
and writing text to the outgoing XML stream. The read thread pulls text off
 
33
of the incoming XML stream and stores the results in an event queue. The
 
34
scheduler thread is used to emit events after a given period of time.
 
35
 
 
36
Additionally, the main event processing loop may be executed in its
 
37
own thread if SleekXMPP is being used in the background for another
 
38
application.
 
39
 
 
40
Short-lived threads may also be spawned as requested for threaded
 
41
:term:`event handlers <event handler>`.
 
42
 
 
43
How XML Text is Turned into Action
 
44
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
45
To demonstrate the flow of information, let's consider what happens
 
46
when this bit of XML is received (with an assumed namespace of
 
47
``jabber:client``):
 
48
 
 
49
.. code-block:: xml
 
50
 
 
51
    <message to="user@example.com" from="friend@example.net">
 
52
      <body>Hej!</body>
 
53
    </message>
 
54
 
 
55
 
 
56
1. **Convert XML strings into objects.**
 
57
 
 
58
   Incoming text is parsed and converted into XML objects (using
 
59
   ElementTree) which are then wrapped into what are referred to as
 
60
   :term:`Stanza objects <stanza object>`. The appropriate class for the
 
61
   new object is determined using a map of namespaced element names to
 
62
   classes.
 
63
 
 
64
   Our incoming XML is thus turned into a :class:`~sleekxmpp.stanza.Message`
 
65
   :term:`stanza object` because the namespaced element name
 
66
   ``{jabber:client}message`` is associated with the class
 
67
   :class:`~sleekxmpp.stanza.Message`.
 
68
 
 
69
2. **Match stanza objects to callbacks.**
 
70
 
 
71
   These objects are then compared against the stored patterns associated
 
72
   with the registered callback handlers. For each match, a copy of the
 
73
   :term:`stanza object` is paired with a reference to the handler and
 
74
   placed into the event queue.
 
75
 
 
76
   Our :class:`~sleekxmpp.stanza.Message` object is thus paired with the message stanza handler
 
77
   :meth:`BaseXMPP._handle_message` to create the tuple::
 
78
 
 
79
       ('stanza', stanza_obj, handler)
 
80
 
 
81
3. **Process the event queue.**
 
82
 
 
83
   The event queue is the heart of SleekXMPP. Nearly every action that
 
84
   takes place is first inserted into this queue, whether that be received
 
85
   stanzas, custom events, or scheduled events.
 
86
 
 
87
   When the stanza is pulled out of the event queue with an associated
 
88
   callback, the callback function is executed with the stanza as its only
 
89
   parameter.
 
90
 
 
91
   .. warning:: 
 
92
       The callback, aka :term:`stream handler`, is executed in the main event
 
93
       processing thread. If the handler blocks, event processing will also
 
94
       block.
 
95
 
 
96
4. **Raise Custom Events**
 
97
 
 
98
   Since a :term:`stream handler` shouldn't block, if extensive processing
 
99
   for a stanza is required (such as needing to send and receive an
 
100
   :class:`~sleekxmpp.stanza.Iq` stanza), then custom events must be used.
 
101
   These events are not explicitly tied to the incoming XML stream and may
 
102
   be raised at any time. Importantly, these events may be handled in their
 
103
   own thread.
 
104
 
 
105
   When the event is raised, a copy of the stanza is created for each
 
106
   handler registered for the event. In contrast to :term:`stream handlers
 
107
   <stream handler>`, these functions are referred to as :term:`event
 
108
   handlers <event handler>`. Each stanza/handler pair is then put into the
 
109
   event queue.
 
110
 
 
111
   .. note::
 
112
       It is possible to skip the event queue and process an event immediately
 
113
       by using ``direct=True`` when raising the event.
 
114
 
 
115
   The code for :meth:`BaseXMPP._handle_message` follows this pattern, and
 
116
   raises a ``'message'`` event::
 
117
 
 
118
       self.event('message', msg)
 
119
 
 
120
   The event call then places the message object back into the event queue
 
121
   paired with an :term:`event handler`::
 
122
 
 
123
       ('event', 'message', msg_copy1, custom_event_handler_1)
 
124
       ('event', 'message', msg_copy2, custom_evetn_handler_2) 
 
125
 
 
126
5. **Process Custom Events**
 
127
 
 
128
   The stanza and :term:`event handler` are then pulled from the event
 
129
   queue, and the handler is executed, passing the stanza as its only
 
130
   argument. If the handler was registered as threaded, then a new thread
 
131
   will be spawned for it.
 
132
 
 
133
   .. note::
 
134
       Events may be raised without needing :term:`stanza objects <stanza object>`. 
 
135
       For example, you could use ``self.event('custom', {'a': 'b'})``. 
 
136
       You don't even need any arguments: ``self.event('no_parameters')``. 
 
137
       However, every event handler MUST accept at least one argument.
 
138
 
 
139
   Finally, after a long trek, our message is handed off to the user's
 
140
   custom handler in order to do awesome stuff::
 
141
 
 
142
       msg.reply()
 
143
       msg['body'] = "Hey! This is awesome!"
 
144
       msg.send()
 
145
 
 
146
 
 
147
.. index:: BaseXMPP, XMLStream
 
148
 
 
149
Raising XMPP Awareness: BaseXMPP
 
150
--------------------------------
 
151
While :class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` attempts to shy away
 
152
from anything too XMPP specific, :class:`~sleekxmpp.basexmpp.BaseXMPP`'s
 
153
sole purpose is to provide foundational support for sending and receiving
 
154
XMPP stanzas. This support includes registering the basic message,
 
155
presence, and iq stanzas, methods for creating and sending stanzas, and
 
156
default handlers for incoming messages and keeping track of presence
 
157
notifications.
 
158
 
 
159
The plugin system for adding new XEP support is also maintained by
 
160
:class:`~sleekxmpp.basexmpp.BaseXMPP`.
 
161
 
 
162
.. index:: ClientXMPP, BaseXMPP
 
163
 
 
164
ClientXMPP
 
165
----------
 
166
:class:`~sleekxmpp.clientxmpp.ClientXMPP` extends
 
167
:class:`~sleekxmpp.clientxmpp.BaseXMPP` with additional logic for connecting
 
168
to an XMPP server by performing DNS lookups. It also adds support for stream
 
169
features such as STARTTLS and SASL.
 
170
 
 
171
.. index:: ComponentXMPP, BaseXMPP
 
172
 
 
173
ComponentXMPP
 
174
-------------
 
175
:class:`~sleekxmpp.componentxmpp.ComponentXMPP` is only a thin layer on top of
 
176
:class:`~sleekxmpp.basexmpp.BaseXMPP` that implements the component handshake
 
177
protocol.