The networking I/O layer is responsible for all network I/O (duh!).
It is implemented as a set of asyncronous operations for opening / acception connections and reading/writing data on those connections. The asyncronous operation means that each API call will only initiate the operation, and when the operation s finished a supplied callback function will be called.
Created filehandles are cbdata enabled, and any links / pointers to filehandles should be properly managed as cbdata.
The return value of is 0 on success or -1 on error. On error, errno will be set to a suitable error code.
All data is contained in IOBuf handlers. Each IOBuf has a reference count, knows the amount of data stored in the IOBuf, actual size of the allocated buffer area (internal) and the buffer area itself. IOBuf is not a simple pointer.
This are the functions available for performing network I/O operations
int ncomm_close(filehandle *fh);
Signals EOF on the socket. No further ncomm_write calls is allowed after this.
Any pending I/O operations will be completed.
The socket will get fully closed when the last reference to the filehandle is gone.
int ncomm_closed(filehandle *fh);
Returns true if a filehandle has been closed with ncomm_close()
What should we do with callbacks?
int ncomm_abort(filehandle *fh);
Aborts the given network connection immediately. Any pending I/O requests will be aborted. No callbacks will be done for cancelled I/O requests.
filehandle * ncomm_listen(int sock_type, int proto, struct sockaddr *where, int addrsize, int backlog, COMMNEWCB *callback, void *cbdata)
start listening for new connections on the given address/port.
The listening port is open until closed with ncomm_close or aborted with ncomm_abort. comm_abort will cancel any pending queued incoming connections not yet notified to the callback, while ncomm_close will only stop listening for new connection requests.
filehandle * ncomm_accept(int sock_type, int proto, struct sockaddr *where, struct sockaddr *from, int addrsize, COMMNEWCB callback, void *cbdata)
Accept a single connection from the given source
The returned filehandle is not valid for use until the callback has been notified, except for comm_abort to cancel the connection request.
filehandle * ncomm_connect(int sock_type, int proto, const struct sockaddr *local, const struct sockaddr *remote, int addrsize, COMMNEWCB *callback, void *cbdata)
Creates a new network connection to the given remote address, optionally using a specified local source address.
The returned filehandle is not valid for use until the callback has been notified, except for comm_abort to cancel the connection request.
void ncomm_read(filehandle *fh, COMMIOCB *callback, void *cbdata); void ncomm_read_limited(filehandle *fh, size_t max_size, COMMIOCB *callback, void *cbdata);
Request to write data. The callback will be called when the request has finished, or if an unrecoverable error occurs.
ncomm_read_limited can limit the max amount of data read in one request.
Any errors will be signalled to the callback function.
void ncomm_write(filehandle *fh, IOBUF *buf, COMMIOCB *callback, void *cbdata);
Request to write data. The callback will be called when the request has finished, or if an unrecoverable error occurs.
it is allowable to queue more write requests before the first has finished. The requests will be processed and completed in the order requested without reordering in data or callback order.
Any errors will be signalled to the callback function.
void ncomm_write_fragment(filehandle *fh, IOBUF *buf, off_t offset, size_t size, COMMIOCB *callback, void *cbdata);
as ncomm_write, but only writes the indicated range of the supplied IOBuf.
void ncomm_write_mbuf(filehandle *fh, MemBuf mb, COMMIOCB *callback, void *cbdata);
Like comm_write, but gets the data from a MemBuf instead of a IOBuf.
The MemBuf should not be used after this. The responsibility for the data area is taken over by ncomm.
int ncomm_add_close_handler(filehandle *fh, COMMCLOSECB *handler, void *cbdata);
Registers a close handler what will be called when the socket is closed. For example to clean up associated data structures or keep relations proper.
Callbacks are used to get notifications when an network operation has finished. These functions are passed as arguments to the I/O operation to be performed, and will get called when the operation finishes (completed or error).
typedef void COMMNEWCB(filehandle *fh, int error, struct sockaddr *local, struct sockaddr *peer, int addrsize, void *cbdata);
Called when a new filehandle is created (ncomm_listen / ncomm_accept / ncomm_connect)
On error, error is set to the appropriate errno.
typedef void COMMIOCB(filehandle *fh, IOBUF *buf, int offset, int size, int errno, void *cbdata);
Called when an I/O operation has finished (ncomm_read / ncomm_write).
On error errno will be set to the error, otherwise errno will be 0.
offset is the offset in the IOBUF where the data for the operation starts, and size is the amount of data processed by the operation.
Note: On error the operation might have been partially completed. In such case size >= 0 and errno != 0.
typedef void COMMCLOSECB(filehandle *fh, void *cbdata);
Called when the filehandle is closed (ncomm_close / ncomm_abort), as requested (ncomm_add_close_handler)
These functions are part of the general framework, and are generally only called once, at suitable locations in the program.
void ncomm_handle_events(int timeout);
This is the network I/O "main loop". Will execute any pending I/O events, and if no events are pending optionally wait for timeout milliseconds for an event to arrive.
void ncomm_module_init(void);
Initializes the network I/O subsystem
void ncomm_module_shutdown(void);
Called on shutdown. Terminates all pending I/O operations and/or connections and other related cleanups.
Do we really need this?
void ncomm_abort_all_connections(void);
Aborts all currently open network connections.
The "poll" API can be used on UNIX to implement event notification mechanisms without having to reimplement all the read/write logics. The purpose of this "event" system is to notify the generic read/write logics when I/O is possible on a socket.
void comm_register_for_read_event(filehandle *fh, COMMEVENTREAD *handler);
Ask to receive read events on the filehandle "fh". When there is a read event available, "handler" will be called.
typedef int COMMEVENTREAD(filehandle *fh);
Callback function type for receiving read event notifications
void comm_register_for_write_event(filehandle *fh, COMMEVENTWRITE *handler);
Ask to receive write events on the filehandle "fh". When writing is possible, "handler" will get called.
typedef int COMMEVENTWRITE(filehandle *fh);
Callback function type for receiving write event notifications