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.
|