UDP receive: /* * General flow: * * If I/O result == CANCELED, free the buffer and notify everyone as * the various queues drain. * * If I/O is error (not canceled and not success) log it, free the buffer, * and restart. * * If query: * if no listeners: free the buffer, restart. * if listener: allocate event, fill in details. * If cannot allocate, free buffer, restart. * if rq event queue is not empty, queue. else, send. * restart. * * If response: * Allocate event, fill in details. * If cannot allocate, free buffer, restart. * find target. If not found, free buffer, restart. * if event queue is not empty, queue. else, send. * restart. */ UDP restart: /* * If too many recv()'s are already running, just return. * * If no one is attached to us, just return. * * Allocate a new buffer to receive into. * If no more buffers: * If there are buffers handed out: wait for one to come back. * If there are no buffers handed out: * If there are responses attached to us, just return. * If there are queries only, send one an error event. * * * start recv() on socket. If this fails: * Free buffer. * Set dispatch state to "shutting down" and why to "socket error" * Start failsafe shutdown. */ Adding a response: /* * If shutting down, return error. * * Allocate an unique messageid and return it. If none can be allocated, * return that. * * Allocate a new structure and fill it in. If no memory, return that. * * Insert into the correct linked list. * * If the receiver is not running, try to start it. */ Adding a request: /* * If shutting down, return error. * * Allocate new structure and fill it in. If no memory, return that. * * Insert it into the linked list. * * If the incoming query packet queue is not empty, pull an item off and * send that event to this task. * * If the receiver is not running, try to start it. */ Detaching a response: /* * decrement dispatch reference count by one. If zero, remember to kill it * later. * * unlink the response from the hashed list. * * Free any buffers and events attached to the response structure. * * Free the response structure. * * If an event is also being returned, jump to "internal event free" below. * * If the ref count became zero above, destroy this dispatch fully, and return. * * If the receiver is not running, try to start it. */ Detaching a request: /* * decrement dispatch ref count by one. If zero, remember to kill it later. * * unlink from the request list. * * Free the response structure. * * If an event is also being returned, jump to "internal event free" below. * * If the ref count became zero above, destroy the dispatch fully, and return. * * If the receiver is not running, try to start it. */ Internal event free (from library space): /* * If it is the failsafe event, send it to the next response/request on the * dispatcher, and return. * * Free buffer. * * Free event. */ Returning an event (from application space): /* * If it is the failsafe event, die. * * Free associated buffer. * * Free event. * * If response: do next response on this response's queue, if any. * If request: do next request on this dispatcher's queue, if any. * * If the receiver is not running, try to start it. */