The following code is a typical example of use:
An Ivy client is made of several threads:
- an IvyServer instance
- a UDP server, launched by the Ivy server, listening to incoming UDP broadcast messages
- IvyTimer objects
group Messages types: | |
---|---|
BYE, ADD_REGEXP, MSG, ERROR, DEL_REGEXP, END_REGEXP, END_INIT, START_REGEXP, START_INIT, DIRECT_MSG, DIE | |
group Separators: | |
ARG_START, ARG_END | |
group Misc. constants: | |
DEFAULT_IVYBUS, PROTOCOL_VERSION, IVY_SHOULD_NOT_DIE IvyApplicationConnected, IvyApplicationDisconnected, DEFAULT_TTL | |
group Objects and functions related to logging: | |
ivylogger, debug, log, warn, error, ivy_loghdlr, ivy_logformatter |
Copyright (c) 2005-2011 Sebastien Bigaret <sbigaret@users.sourceforge.net>
Represents a client connected to the bus. Every callback methods registered by an agent receive an object of this type as their first parameter, so that they know which agent on the bus is the cause of the event which triggered the callback.
An IvyClient is responsible for:
- managing the remote agent’s subscriptions,
- sending messages to the remote agent.
It is not responsible for receiving messages from the client: another object is in charge of that, namely an IvyHandler object.
The local IvyServer creates one IvyClient per agent on the bus.
See the discussion in regexps.
Group Protocol-related methods: | |
---|---|
start_init, end_init, send_new_subscription, remove_subscription, wave_bye |
|
Group Manipulating the remote agent’s subscriptions: | |
add_regexp, remove_regexp |
|
Group Sending messages: | |
send_msg, send_direct_message, send_die_message |
|
Variables: |
|
Raises IvyIllegalStateError: | |
---|---|
if the client has not been fully initialized yet (see start_init) |
Should be called when the initialization process ends.
Raises IvyIllegalStateError: | |
---|---|
if the method has already been called (and self.status has already been set to INITIALIZED) |
Removes a regexp
Returns: | the regexp that has been removed |
---|---|
Raises: |
|
Notifies the remote agent that we (the local agent) are not interested in a given subscription.
Parameters: |
|
---|
Sends a direct message
Note: the message will be encoded by encode_message with numerical_id=num_id and params==msg; this means that if msg is not a string but a list or a tuple, the direct message will contain more than one parameter. This is an extension of the original Ivy design, supported by python, but if you want to inter-operate with applications using the standard Ivy API the message you send must be a string. See in particular in ivy.h:
typedef void (*MsgDirectCallback)( IvyClientPtr app, void *user_data, int id, char *msg ) ;
Sends the message to the client. The client will receive one message for each of its subscriptions (regexps) that the message matches.
Returns: | True if the message was actually sent to the client, that is: if there is one or more regexps matching the message in the client’s subscriptions; returns False otherwise. |
---|
Notifies the remote agent that we (the local agent) subscribe to a new type of messages
Parameters: |
|
---|
Finalizes the initialization process by setting the client’s agent_name. This is a Ivy protocol requirement that an application sends its agent-name only once during the initial handshake (beginning with message of type START_INIT and ending with a type END_INIT). After this method is called, we expect to receive the initial subscriptions for that client (or none); the initialization process completes after end_init is called.
Raises IvyIllegalStateError: | |
---|---|
if the method has already been called once |
Bases: SocketServer.StreamRequestHandler
An IvyHandler is associated to one IvyClient connected to our server.
It runs into a dedicate thread as long as the remote client is connected to us.
It is in charge of examining all messages that are received and to take any appropriate actions.
Implementation note: the IvyServer is accessible in self.server
Examines the message (after passing it through the decode_msg() filter) and takes the appropriate actions depending on the message types. Please refer to the document The Ivy Architecture and Protocol and to the python code for further details.
Parameters: |
|
---|---|
Returns: | False if the connection should be terminated, True otherwise |
Bases: SocketServer.ThreadingTCPServer
An Ivy server is responsible for receiving and handling the messages that other clients send on an Ivy bus to a given agent.
An IvyServer has two important attributes: usesDaemons and server_termination.
Variables: |
|
---|
All public methods (not starting with an underscore _) are MT-safe
Group Communication on the ivybus: | |
---|---|
start, send_msg, send_direct_message, send_ready_message, handle_msg, stop | |
Group Inspecting the ivybus: | |
get_clients, _get_client, get_client_with_name | |
Group Our own subscriptions: | |
get_subscriptions, bind_msg, unbind_msg, _add_subscription, _remove_subscription, _get_fct_for_subscription |
Registers a new subscriptions, by binding a regexp to a function, so that this function is called whenever a message matching the regexp is received.
Parameters: |
|
---|---|
Returns: | the binding’s id, which can be used to unregister the binding with unbind_msg() |
Returns the list of the clients registered with a given agent-name
See: | get_clients |
---|
Returns the list of the agent names of all connected clients
See: | get_client_with_name |
---|
Simply call the function bound to the subscription id idx with the supplied parameters.
Completes connection with the client TODO: maybe add a flag (while connecting) on the client, that would prevent sending msg. etc.. as CNX. not confirmed
Removes a registered client
This method is responsible for calling server.app_callback
Returns: | the removed client, or None if no such client was found |
---|
Note
NO NETWORK CLEANUP IS DONE
Sends a direct message to the agent named agent_name. If there is more than one agent with that name on the bus, parameter stop_on_first determines the behaviour.
Parameters: |
|
---|---|
Returns: | True if at least one direct message was sent |
Examine the message and choose to send a message to the clients that subscribed to such a msg
Returns: | the number of clients to which the message was sent |
---|
Handle requests (calling handle_request()) until doomsday... or until stop() is called.
This method is registered as the target method for the thread. It is also responsible for launching the UDP server in a separate thread, see UDP_init_and_listen for details.
You should not need to call this method, use start instead.
Binds the server to the ivybus. The server remains connected until stop is called, or until it receives and accepts a ‘die’ message.
Raises IvyIllegalStateError: | |
---|---|
if the server has already been started |
Bases: threading.Thread
An IvyTimer object is responsible for calling a function regularly. It is bound to an IvyServer and stops when its server stops.
Please note: start() starts a new thread; if the same function is given as the callback to different timers, that function should be prepared to be called concurrently. Specifically, if the callback accesses shared variables, they should be protected against concurrency problems (using locks e.g.).
Called by an IvyServer at startup; the method is responsible for:
Parameters: |
|
---|
Transforms the supplied string into the corresponding broadcast address and port
Parameters: | ivybus – if None or empty, defaults to environment variable IVYBUS |
---|---|
Returns: | a tuple made of (broadcast address, port number). For example:>>> print decode_ivybus('192.168.12:2010')
('192.168.12.255', 2010)
|
Returns: | msg_id, numerical_id, parameters |
---|---|
Raises IvyMalformedMessage: | |
params is string -> added as-is params is list -> concatenated, separated by ARG_END
Tells whether the specified ip is a multicast address or not
Parameters: | ip – an IPv4 address in dotted-quad string format, for example 192.168.2.3 |
---|
Implements the standard Ivy API.
You can refer to the example code pyhello.py for an example of use.
All methods in this module are frontends to a ivy.IvyServer instance, stored in the module’s attributes _IvyServer.
group Connecting to/disconnecting from the Ivy bus: | |
---|---|
IvyInit, IvyStart,IvyMainLoop, IvyStop | |
group Bindings: | IvyBindMsg, IvyUnBindMsg, IvyBindDirectMsg |
group Inspecting the Ivy bus: | |
IvyGetApplicationList, IvyGetApplication, IvyGetApplicationName, IvyGetApplicationHost | |
group Interacting with other Ivy clients: | |
IvySendMsg, IvySendDieMsg, IvySendDirectMsg | |
group Timers: | IvyTimerRepeatAfter, IvyTimerModify, IvyTimerRemove |
Copyright (c) 2005-2011 Sebastien Bigaret <sbigaret@users.sourceforge.net>
Registers a method that should be called each time someone sends us a direct message
Registers a method that should be called each time a message matching regexps is sent on the Ivy bus.
Returns: | an id identifying the binding, that can be used to unregister it (see IvyUnBindMsg()) |
---|
Returns the Ivy client registered on the bus under the given name.
Warning
if multiple applications are registered w/ the same name only one is returned
Returns: | an ivy.IvyClient object |
---|
Equivalent to client.fqdn. IP address is stored under client.ip, and port number under client.port
Parameters: | client – an ivy.IvyClient object, as returned by IvyGetApplication() |
---|
Returns the names of the applications that are currently connected
Returns all subscriptions for that client
Parameters: | client – an ivy.IvyClient object, as returned by IvyGetApplication() |
---|---|
Returns: | list of tuples (idx, regexp) |
Equivalent to client.agent_name
Parameters: | client – an ivy.IvyClient object, as returned by IvyGetApplication() |
---|
Initializes the module. This method should be called exactly once before any other method is called.
Simulates the original main loop: simply waits for the server termination.
Note that while the original API requires this to be called, this module does NOT rely in any way on this method. In particular, a client is fully functional and begins to receive messages as soon as the IvyStart() method is called.
Sends a “die” message to client, instructing him to terminate.
Parameters: | client – an ivy.IvyClient object, as returned by IvyGetApplication() |
---|
Sends a message directly to an other Ivy client, with the supplied numerical id and message.
Parameters: |
|
---|
Sends an “error” message to client
Parameters: |
|
---|
Starts the Ivy server and fully activate the client. Please refer to the discussion in IvyMainLoop() ‘s documentation.
Modifies a timer’s delay. Note that the modification will happen after the next tick.
Parameters: |
|
---|
Stops and removes a given timer.
Parameters: | timer_id – id of the timer, as returned by IvyTimerRepeatAfter |
---|
Creates and activates a new timer
Parameters: |
|
---|---|
Returns: | the timer’s id |
Ivy is a lightweight software bus for quick-prototyping protocols. It allows applications to broadcast information through text messages, with a subscription mechanism based on regular expressions.
If you’re used to the standard Ivy API, you probably want to look at the std_api module.
Note
Version 2.0 broke backward compatibility. If you are upgrading from ivy-python v1.x, be sure to read the v2.0 compatibility notes, below.
The Ivy software bus was designed at the French Centre d’Etudes de la Navigation Aerienne (CENA). The original work: software, documentation, papers, credits can be found on the Ivy Home Page; it contains all the necessary materials needed to understand Ivy.
This package is the Python library; Ivy libraries are also available for numerous languages, among which: C, C#, C++, Java, Perl –see the Ivy Download Page for details.
This python library is a full rewrite of the original software, and it is written in pure python. Note that another python implementation is available at the Ivy downloads page, which is built by SWIG on top of the Ivy C library.
This Ivy package is made of two modules: ivy and std_api.
In order to understand the way it works, we highly suggest that you read the materials available from the Ivy Home Page. Within the documentation of this python package we suppose that you are already familiar with the way an ivy bus works, and with how the corresponding framework is organized.
Once familiar with the ivy framework, you’ll find in the std_api module the exact API you’re expecting (see for example the The Ivy C library).
An example of use, directly taken from the original swig-base python release, is included with the package, see examples/pyhello.py.
Important
One big difference with the original implementation is that there is nothing like a “main loop”: the server is activated as soon as the method ivy.std_api.IvyStart is called, and the ivy.std_api.IvyMainLoop method simply waits for the server to terminate (the server is in fact
It’s where the “magic” goes: the module std_api is built on top of it.
You’ll be interested in using this package if for example, you want to manage more than one ivy-bus in an application. We won’t give here much hint on how to use it, since the code of the ivy module itself serves as a perfect example of use!
The module issues messages through python’s standard logging module:
- logger’s name: 'Ivy'
- default level: logging.INFO
- default handler: a logging.StreamHandler logging messages to the standard error stream.
For example, if you need to see all messages issued by the package, including debug messages, use the following code excerpt:
Further details can be found in the Python standard documentation.
Version 2.0 broke the backward compatibility with former versions 1.x: every callback methods now receives an ivy.IvyClient object as its first parameter.
This makes it possible for the receiving code to know which agent on the bus sends the corresponding event. Unfortunately, this breaks backward compatibility and callback methods must be adapted to the new scheme.
For example, suppose you’re binding a regexp to the callback on_msg:
In ivy-python 1.x, you used to declare the callback as follows
or:
In version 2.0, your callbacks also get the agent triggering the event as the 1st parameter; the previous callbacks should be rewritten this way:
or:
- direct msg: to app_name == the last one registered w/ that name (for example register ivyprobe 3 times and send a direct msg to IVYPROBE from one of them)
- regexps order and ids: ivyprobe e.g. subscribes regexp in reverse order of ids. For each match, send the appropriate message. documented.
This software is distributed under the “new” BSD license,
(please refer the file LICENSE for full legal details)
Copyright (c) 2005-2011 Sebastien Bigaret <sbigaret@users.sourceforge.net>