Skip to content

Commit

Permalink
merge with abourget/master
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastibe committed Mar 15, 2012
2 parents 990bf96 + 7a7970e commit a8bfb06
Show file tree
Hide file tree
Showing 5 changed files with 302 additions and 26 deletions.
93 changes: 90 additions & 3 deletions docs/source/namespace.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,93 @@
=========================

.. automodule:: socketio.namespace
:members:
:undoc-members:
:show-inheritance:

.. autoclass:: BaseNamespace

**ACL system**

The ACL system grants access to the different ``on_*()`` and ``recv_*()``
methods of your subclass.

Developers will normally override ``get_initial_acl()`` to return a list
of the functions they want to initially open. Usually, it will be a
``connect`` method, that will perform authentication and/or authorization,
set some variables on the Namespace, and then open up the rest of the
Namespace using ``lift_acl_restrictions()`` or more granularly with
``add_acl_method`` and ``del_acl_method``.

The content of the ACL is a list of strings corresponding to the full name
of the methods defined on your subclass, like: ``"on_my_event"`` or
``"recv_json"``.

.. automethod:: get_initial_acl

.. automethod:: add_acl_method

.. automethod:: del_acl_method

.. automethod:: lift_acl_restrictions

.. automethod:: reset_acl

This function is used internally, but can be useful to the developer:

.. automethod:: is_method_allowed

**Namespace initialization**

You can override this method:

.. automethod:: initialize


**Sending data**

Functions to send data through the socket:

.. automethod:: emit

.. automethod:: send

.. automethod:: error


**Dealing with incoming data**

.. automethod:: process_event

You should override this method only if you are not satisfied with the
automatic dispatching to ``on_``-prefixed methods. You could then
implement your own dispatch. See the source code for inspiration.

.. automethod:: recv_connect

.. automethod:: recv_message

.. automethod:: recv_json

.. automethod:: recv_error

.. automethod:: recv_disconnect


**Process management**

Managing the different callbacks, greenlets and tasks you spawn from
this namespace:

.. automethod:: spawn

.. automethod:: kill_local_jobs


**Low-level methods**

Packet dispatching methods. These functions are normally not overriden if
you are satisfied with the normal dispatch behavior:

.. automethod:: process_packet

.. automethod:: call_method_with_acl

.. automethod:: call_method
76 changes: 76 additions & 0 deletions docs/source/packet.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,82 @@

The day to day user doesn't need to use this module directly.

The packets used internally (that might be exposed if you override the
``process_packet`` method of your Namespace) are dictionaries, and are different
from a message type to the other. Here is a list of message types available
in the Socket.IO protocol:

The **connect** packet:

{"type": "connect",
"qs": "",
"endpoint": "/chat"}

The ``qs`` parameter is a query string you can add to the io.connect('/chat?a=b'); calls on the client side.

The **message** packet, equivalent to Socket.IO version 0.6's string message:

{"type": "message",
"data": "this is the sent string",
"endpoint": "/chat"}

{"type": "message",
"data": "some message, but please reply",
"ack": True,
"id": 5,
"endpoint": "/chat"}

This last message includes a **msg_id**, and asks for an ack, which you can
reply to with ``self.ack()``, so that the client-side callback is fired upon
reception.

The **json** packet is like a message, with no name (unlike events) but with
structure JSON data attached. It is automatically decoded by gevent-socketio.

{"type": "json",
"data": {"this": "is a json object"},
"endpoint": "/chat"}

{"type": "json",
"data": {"this": "is a json object", "please": "reply"},
"ack": True,
"id": 5,
"endpoint": "/chat"}

The same ``ack`` mechanics also apply for the ``json`` packet.


The **event** packet holds a ``name`` and some ``args`` as a list. They are
taken as a list on the browser side (you can ``socket.emit("event", many,
parameters``) in the browser) and passed in as is.

{"type": "event",
"endpoint": "/chat",
"name": "my_event",
"args": []}

{"type": "event",
"endpoint": "/chat",
"name": "my_event",
"ack": True,
"id": 123,
"args": [{"my": "object"}, 2, "mystring"]}

The same ack semantics apply here as well.

[INSERT: mark the difference between when YOU create the packet, and when
you receive it, and what you must do with it according to different ack values]


The **heartbeat** packet just marks the connection as alive for another amount
of time.

{"type": "heartbeat",
"endpoint": ""}

This packet is for the global namespace (or empty namespace).


.. automodule:: socketio.packet
:members:
:undoc-members:
Expand Down
30 changes: 27 additions & 3 deletions socketio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,33 @@ def socketio_manage(environ, namespaces, request=None):
"""Main SocketIO management function, call from within your Framework of
choice's view.
The request object is not required, but will probably be useful to pass
framework-specific things into your Socket and Namespace functions.
The ``environ`` variable is the WSGI ``environ``. It is used to extract the
Socket object from the underlying server (as the 'socketio' key), and is
otherwise attached to both the Socket and Namespace objects.
The ``request`` object is not required, but will probably be useful to pass
framework-specific things into your Socket and Namespace functions. It will
simply be attached to the Socket and Namespace object (accessible through
``self.request`` in both cases), and it is not accessed in any case by the
``gevent-socketio`` library.
The ``namespaces`` parameter is a dictionary of the namespace string
representation as key, and the BaseNamespace namespace class descendant as
a value. The empty string ('') namespace is the global namespace. You can
use Socket.GLOBAL_NS to be more explicit. So it would look like:
namespaces={'': GlobalNamespace,
'/chat': ChatNamespace}
This function will block the current "view" or "controller" in your
framework to do the recv/send on the socket, and dispatch incoming messages
to your namespaces.
This is a simple example using Pyramid:
def my_view(request):
socketio_manage(request.environ, {'': GlobalNamespace}, request)
"""
socket = environ['socketio']
socket._set_environ(environ)
Expand All @@ -28,5 +53,4 @@ def socketio_manage(environ, namespaces, request=None):
gevent.joinall([receiver_loop, watcher])

# TODO: double check, what happens to the WSGI request here ? it vanishes ?

return
Loading

0 comments on commit a8bfb06

Please sign in to comment.