Permalink
Browse files

starting to rewrite the doc

  • Loading branch information...
tarekziade committed Dec 26, 2012
1 parent beedd46 commit 9357b607228c5a732cd1da027e229eef5986a057
Showing with 42 additions and 118 deletions.
  1. +42 −107 docs/source/extending.rst
  2. +0 −1 docs/source/index.rst
  3. +0 −8 docs/source/keepalive.rst
  4. +0 −2 vaurien/protocols/base.py
View
@@ -3,148 +3,83 @@
Extending Vaurien
=================
-.. note::
-
- Before reading this section, make sure you read :ref:`keep`
-
You can extend Vaurien by writing new **protocols** or new **behaviors**.
Writing Protocols
-----------------
-XXX
-
-
-Writing Handlers
-----------------
-
-Creating new handlers is done by implementing a class with a specific
-signature::
-
-
- from vaurien.handlers import Handler
-
- class MySuperHandler(object):
-
- name = 'super'
- options = {}
-
- def __call__(self, client_sock, backend_sock, to_backend):
- # do something here
- return True # or False, see after.
-
-
- Handler.register(MySuperHandler)
-
+Writing a new protocol is done by creating a class that inherits from
+the :class:`vaurien.protocols.base.BaseProtocol` class.
-Vaurien can use this handler and call it when data comes from the backend (the
-server being proxied) or from a client (making calls to the server).
+The class needs to provide three elements:
-You must call **Handler.register** against your class is order to add it
-to the list of the available plugins.
+- a **name** class attribute, the protocol will ne known under that
+ name.
-Let's see the different attributes and options we have in this class:
+- an optional **options** class attribute - a mapping containing options
+ for the protocol. Each option value is composed of a
+ description, a type and a default value. The mapping is wired in the
+ command-line when you run vaurien - and is also used to generate
+ the protocol documentation.
-- **name** - the name under which your backend is known
-- **options** - a mapping containing your handler options
-- **client_sock** - the socket opened with the client
-- **backend_sock** - the socket opened with the backend server
-- **to_backend** - a boolean giving the direction of the call. If True
- it means some data is available in the client socket, that is supposed
- to go to the backend. If False, it means data is available on the backend
- socket and should be tramsmitted back to the client.
+- a **_handle** method, that will be called everytime some data
+ is ready to be read on the proxy socket or on the backend socket.
-For the handler options, each option is defined in the **options** mapping.
-The key is the option name and the value is a 3-tuple providing:
-- a description
-- a type
-- a default value
+The :class:`vaurien.protocols.base.BaseProtocol` class also provides
+a few helpers to work with the sockets:
-**every option is optional and need a default value**
+- *_get_data*: a method to read data in a socket. Catches
+ *EWOULDBLOCK* and *EAGAIN* errors and loops until they happen.
+- *option*: a method to get the value of an option
-Everytime a handler is used, it gets two extra attributes:
-- **settings** - the settings loaded for the handler
-- **proxy** - the proxy instance
+Example::
-The BaseHandler class
----------------------
+ class TCP(BaseProtocol):
+ name = 'tcp'
+ options = {'reuse_socket': ("If True, the socket is reused.",
+ bool, False),
+ 'buffer': ("Buffer size", int, 8124),
+ 'keep_alive': ("Keep the connection alive", bool, False)}
-XXX
-
-Full handler example
---------------------
-
-Here is how the `delay` handler is specified::
-
- from vaurien.handlers.base import BaseHandler
-
-
- class Dummy(BaseHandler):
- """Dummy handler.
-
- Every incoming data is passed to the backend with no alteration,
- and vice-versa.
- """
- name = 'dummy'
- options = {'keep_alive': ("Keep-alive protocol",
- bool, False),
- 'reuse_socket': ("If True, the socket is reused.",
- bool, False)}
-
- def __call__(self, client_sock, backend_sock, to_backend):
- data = self._get_data(client_sock, backend_sock, to_backend)
+ def _handle(self, source, dest, to_backend):
+ # default TCP behavior
+ data = self._get_data(source)
if data:
- dest = to_backend and backend_sock or client_sock
- source = to_backend and client_sock or backend_sock
dest.sendall(data)
-
- # If we are not keeping the connection alive
- # we can suck the answer back and close the socket
if not self.option('keep_alive'):
data = ''
while True:
- data = dest.recv(1024)
-
+ data = self._get_data(dest)
if data == '':
break
source.sendall(data)
- dest.close()
- dest._closed = True
- elif not to_backend:
- # We want to close the socket if the backend sock is empty
- if not self.option('reuse_socket'):
- backend_sock.close()
- backend_sock._closed = True
+ if not self.option('reuse_socket'):
+ dest.close()
+ dest._closed = True
+ return False
return data != ''
-Using handlers
---------------
+Once the protocol class is ready, it can be registered via the :class:`Protocol` class::
-Once the handler is ready, you can point it to Vaurien
-by providing its fully qualified name - e.g. the class name prefixed
-by the module and package(s) names.
+ from vaurien.protocols import Protocol
+ Protocol.register(TPC)
-Then you can use it with the **--behavior** option::
- $ vaurien --proxy localhost:8000 --backend google.com:80 \
- --behavior 20:path.to.the.callable \
- --handler-delay-sleep 2
+Writing Behaviors
+-----------------
-Or by using a configuration file::
+Creating new behaviors is very similar to creating protocols.
- [vaurien]
- behavior = 20:foobar
+XXX
- [handler:foobar]
- callable = path.to.the.callable
- foo=bar
-And calling Vaurien with --config::
+Using your protocols and behaviors
+----------------------------------
- $ vaurien --config config.ini
+XXX
View
@@ -236,6 +236,5 @@ And there is more! Have a look at the other sections of the documentation:
protocols
apis
extending
- keepalive
examples
@@ -1,8 +0,0 @@
-.. _keep:
-
-Keep-alive vs Disconnect
-========================
-
-
-Explain here the different strategies
-
@@ -4,7 +4,6 @@
class BaseProtocol(object):
- options = {}
name = ''
options = {'reuse_socket': ("If True, the socket is reused.",
bool, False),
@@ -55,7 +54,6 @@ def _get_data(self, sock, buffer=None):
def __call__(self, source, dest, to_backend, behavior):
if not behavior.on_before_handle(self, source, dest, to_backend):
return True
-
try:
return self._handle(source, dest, to_backend)
finally:

0 comments on commit 9357b60

Please sign in to comment.