Reference: Proxies
General
A proxy is a single-process event multiplexer. It takes control of the
execution flow, and waits in a nice way for something to happen that requires
your program's attention. This is typically caused by user input or other
processes (remote or local) signalling your process, connecting to public
services it offers, etc.
Properties overview
- Multiple subsystems. Handles different kinds of subsystems
simultaneously.
- Multiple instances per subsystem. Handles any number of subsystem
instances (e.g. sockets or timers).
- Specific handlers per instance. Each instance has specific handler slots
that can be registered with. Only one function can be attached to any
single event on an instance. Exception: Subsystems that do
filtering, like COMM.
Events
Events are handled for the following subsystems:
- Sockets, SOCK.
- Block communications, COMM.
- Timers.
These are the prototypes for your event handlers, along with invocation
semantics - sorted by subsystem:
SOCK
- int read(SOCK *s, void *priv);
Invoked whenever there is data to be read from the socket s.
The data you passed upon registering is passed back to you in priv.
- int write(SOCK *s, void *priv);
Invoked whenever socket s can be written to. This
doesn't neccessarily mean you can write as much as you want, so beware.
The data you passed upon registering is passed back to you in priv.
- int connect(SOCK *sp, SOCK *s, void *priv);
Invoked whenever a connection attempt involving the socket
sp is resolved. The semantics are a little different for
incoming and outgoing connections: For successful incoming connections,
you get a new, connected socket in s. For outgoing
connections, s will be NULL,
and you have to check if sp is connected, to determine
if your attempt was successful. If it is not, this indicates a failed
outgoing connection attempt.
The data you passed upon registering the handler is passed back to you in priv.
- int close(SOCK *s, void *priv);
Invoked whenever the remote end closes a connection to your socket. Not
invoked for sockets you've closed in your end. Upon invocation, the socket
is not closed in your end - you have to take care of this yourself.
The data you passed upon registering is passed back to you in priv.
COMM
- int recv(COMM *c, TT
*tt, ushort trans, int complete, void *priv);
Invoked whenever c receives a tree, or a node in a
tree, matching the transaction and root this handler was registered with.
If the handler was registered as accepting incomplete trees (tree nodes),
complete can be FALSE, in
which case tt is the last received node, prepared with
data and connected to the rest of the tree. Any handler, whether accepting
part-trees or not, can receive a complete tree. In that case, tt is the root node of the complete tree.
The data you passed upon registering is passed back to you in priv.
- int connect(COMM
*cp, COMM *c, void *priv);
Invoked whenever a connection attempt involving the comm
cp is resolved. The semantics is a little different for
incoming and outgoing connections: For successful incoming connections,
you get a new, connected comm in c. For outgoing
connections, c will be NULL,
and you have to check if cp is connected, to determine
if your attempt was successful. If it is not, this indicates a failed
outgoing connection attempt.
The data you passed upon registering the handler is passed back to you in priv.
- void close(COMM *c, void *priv);
Invoked whenever the remote end closes a connection to your comm. Not
invoked for comms you've closed in your end. Upon invocation, the comm
is not closed in your end - you have to take care of this yourself.
The data you passed upon registering is passed back to you in priv.
Timer
- int timeout(char *name, void *priv);
Invoked whenever the timer name times out.
The data you passed upon registering is passed back to you in priv.
Allocation
- PROXY *proxy_new();
Allocates, initializes to empty and returns a new proxy.
- void proxy_del(PROXY *p);
Deletes all handlers and the proxy, p, itself. Never
delete a proxy within one of its handlers. This should be done outside the
loop, i.e. on the level that initialized and started the proxy in the first
place.
Running
- void proxy_loop(PROXY *p);
Starts the proxy loop for proxy p. This loop will
activate event handlers in your source as things happen. Activating an
empty proxy is not a good idea. Keeps running until
proxy_break is called on it from a handler.
- void proxy_break(PROXY *p);
Makes a proxy stop executing. Usually, you will call this from within
one of its handlers. The proxy_loop function
will return to its caller as soon as control is returned to the proxy (when
your current handler exits).
Adding handlers
- void proxy_add_sock(PROXY *p, SOCK *s,
void *priv,
int (*read)(SOCK *, void *),
int (*write)(SOCK *, void *),
int (*connect)(SOCK *, SOCK *, void *),
int (*close)(SOCK *, void *));
Add handlers to proxy p for socket s, potentially for all possible socket events at once. Any
combination of the function pointers read, write, connect and close can be NULL, in which case
that handler for the specified socket, is not touched.
- void proxy_add_sock_read(PROXY *p, SOCK *s,
void *priv,
int (*read)(SOCK *, void *));
Set read handler for socket s in proxy p.
Data set in priv is passed back to the handler upon
invocation.
- void proxy_add_sock_write(PROXY *p, SOCK *s,
void *priv,
int (*write)(SOCK *, void *));
Set write handler for socket s in proxy p.
Data set in priv is passed back to the handler upon
invocation.
- void proxy_add_sock_connect(PROXY
*p, SOCK *s, void *priv,
int (*connect)(SOCK *, void *));
Set connection handler for socket s in proxy p.
Data set in priv is passed back to the handler upon
invocation.
- void proxy_add_sock_close(PROXY *p, SOCK *s,
void *priv, int (*close)(SOCK *, void *));
Set close handler for socket s in proxy p.
Data set in priv is passed back to the handler upon
invocation.
- void proxy_add_comm(PROXY *p, COMM *c,
char *root, ushort trans, int incomplete, void *priv, int (*recv)(COMM *, TT *, ushort, int, void *));
Adds a handler for incoming token trees on comm c in
proxy p. root is the root
string the trees must match, and trans is the
transaction number they must match. If either is NULL or zero, that argument
means catch-any-root or catch-any-trans. If root is
NULL and trans is zero,
this handler will be a default handler, i.e. it gets all incoming trees.
If incomplete is TRUE, the
handler will be invoked as the tree is constructed, with each finished node
(see the Events section above). You can have
any number of these handlers, and their characteristics may overlap in part
or in full.
- void proxy_add_comm_connect(PROXY
*p, COMM *c, void *priv,
int (*connect)(COMM *, COMM *, void *));
Set connection handler for comm c in proxy p.
Data set in priv is passed back to the handler upon
invocation.
- void proxy_add_comm_close(PROXY *p, COMM *c,
void *priv, int (*close)(COMM *, void *));
Set close handler for comm c in proxy p.
Data set in priv is passed back to the handler upon
invocation.
- void proxy_add_timer(PROXY *p, char *name,
struct timeval *interval,
int recurrent, void *priv, int (*timeout)(char *, void *));
Set a timer-invoked function. The timer's unique name (passed to the function
and used for identification, e.g. when deleting the handler) will be
name. The function timeout will
be invoked at intervals defined by interval, first
invocation being the time span defined by interval,
from now. If recurrent is
TRUE, timeout will be
invoked until the handler is removed manually, otherwise it is just invoked
once (the handler goes away afterwards).
Deleting handlers
- void proxy_del_sock(PROXY *p, SOCK *s);
Removes the handlers for socket s from proxy
p. You will get no more events for the socket.
This must be done before deleting the socket structure itself.
- void proxy_del_comm(PROXY *p, COMM *c);
Removes the handlers for comm c from proxy
p. You will get no more events for the comm.
This must be done before deleting the comm structure itself.
- void proxy_del_comm_trans(PROXY *p, COMM *c, u16 trans);
Removes the handlers matching transaction trans for
comm c from proxy p.
- void proxy_del_comm_block(PROXY *p, COMM *c, char *root);
Removes the handlers matching root string root for
comm c from proxy p.
- void proxy_del_timer(PROXY *p, char *name);
Removes the timer named name from proxy
p.
Special interfaces
- void proxy_reset_timer(PROXY *p, char *name);
Resets countdown for timer named name, so the next
invocation will occur in the pre-set interval, from now.