| /* libnih |
| * |
| * Copyright © 2009 Scott James Remnant <scott@netsplit.com>. |
| * Copyright © 2009 Canonical Ltd. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining |
| * a copy of this software and associated documentation files (the |
| * "Software"), to deal in the Software without restriction, including |
| * without limitation the rights to use, copy, modify, merge, publish, |
| * distribute, sublicense, and/or sell copies of the Software, and to |
| * permit persons to whom the Software is furnished to do so, subject to |
| * the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR |
| * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
| * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| #ifndef NIH_IO_H |
| #define NIH_IO_H |
| |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| |
| #include <nih/macros.h> |
| #include <nih/list.h> |
| |
| |
| /** |
| * NihIoType: |
| * |
| * Whether an NihIo structure is used for a buffered stream of data, or |
| * a queue of discreet messages. |
| **/ |
| typedef enum { |
| NIH_IO_STREAM, |
| NIH_IO_MESSAGE |
| } NihIoType; |
| |
| /** |
| * NihIoEvents: |
| * |
| * Events that we can watch for, generally used as a bit mask of the events |
| * that have occurred. |
| **/ |
| typedef enum { |
| NIH_IO_NONE = 00, |
| NIH_IO_READ = 01, |
| NIH_IO_WRITE = 02, |
| NIH_IO_EXCEPT = 04, |
| } NihIoEvents; |
| |
| |
| /* Predefine the typedefs as we use them in the callbacks */ |
| typedef struct nih_io_watch NihIoWatch; |
| typedef struct nih_io NihIo; |
| |
| /** |
| * NihIoWatcher: |
| * @data: data pointer given when registered, |
| * @watch: #NihIoWatch for which an event occurred, |
| * @events: events that occurred. |
| * |
| * An I/O watcher is a function that is called whenever an event occurs |
| * on a file descriptor or socket being watched. It is safe for the |
| * watcher to remove the watch during the call. |
| **/ |
| typedef void (*NihIoWatcher) (void *data, NihIoWatch *watch, |
| NihIoEvents events); |
| |
| /** |
| * NihIoReader: |
| * @data: data pointer given when registered, |
| * @io: NihIo with data to be read, |
| * @buf: buffer data is available in, |
| * @len: bytes in @buf. |
| * |
| * An I/O reader is a function that is called whenever new data or a new |
| * message has been received on a file descriptor or socket and placed |
| * into the receive buffer or queue. |
| * |
| * In stream mode, @buf and @len will point to the entire receive buffer |
| * and this function need not clear the buffer, it is entirely permitted |
| * for the data to be left there. When further data arrives, the buffer |
| * will be extended and the reader called again. |
| * |
| * In message mode, @buf and @len will point to the contents of the oldest |
| * message in the receive queue. You'll almost certainly want to remove |
| * this message from the queue, otherwise when a new message arrives, the |
| * function will still be called with the same oldest message. |
| * |
| * It is safe to call nih_io_close() from within the reader function, this |
| * results in the structure being flagged to be closed when the watcher |
| * that invokes it has finished. You must not nih_free() @io or cause it |
| * to be freed from within this function, except by nih_io_close(). |
| **/ |
| typedef void (*NihIoReader) (void *data, NihIo *io, |
| const char *buf, size_t len); |
| |
| /** |
| * NihIoCloseHandler: |
| * @data: data pointer given when registered. |
| * @io: NihIo that closed. |
| * |
| * An I/O close handler is a function that is called when the remote end |
| * of a file descriptor or socket is closed and data can no longer be |
| * read from it. |
| * |
| * It should take appropriate action, which may include closing the |
| * file descriptor with nih_io_close(). You must not nih_free() @io or |
| * cause it to be freed from within this function, except by nih_io_close(). |
| **/ |
| typedef void (*NihIoCloseHandler) (void *data, NihIo *io); |
| |
| /** |
| * NihIoErrorHandler: |
| * @data: data pointer given when registered, |
| * @io: NihIo that caused the error. |
| * |
| * An I/O error handler is a function that is called to handle an error |
| * raise while reading from the file descriptor or socket. The error |
| * itself can be obtained using nih_error_get(). |
| * |
| * It should take appropriate action, which may include closing the |
| * file descriptor with nih_io_close(). You must not nih_free() @io or |
| * cause it to be freed from within this function, except by nih_io_close(). |
| **/ |
| typedef void (*NihIoErrorHandler) (void *data, NihIo *io); |
| |
| |
| /** |
| * NihIoWatch: |
| * @entry: list header, |
| * @fd: file descriptor, |
| * @events: events to watch for, |
| * @watcher: function called when @events occur on @fd, |
| * @data: pointer passed to @watcher. |
| * |
| * This structure represents the most basic kind of I/O handling, a watch |
| * on a file descriptor or socket that causes a function to be called |
| * when listed events occur. |
| * |
| * The watch can be cancelled by calling nih_list_remove() on the structure |
| * as they are held in a list internally. |
| **/ |
| struct nih_io_watch { |
| NihList entry; |
| int fd; |
| NihIoEvents events; |
| |
| NihIoWatcher watcher; |
| void *data; |
| }; |
| |
| /** |
| * NihIoBuffer: |
| * @buf: memory allocated for buffer, |
| * @size: allocated size of @buf, |
| * @len: number of bytes of @buf used. |
| * |
| * This structure is used to represent a buffer holding data that is |
| * waiting to be sent or processed. |
| **/ |
| typedef struct nih_io_buffer { |
| char *buf; |
| size_t size; |
| size_t len; |
| } NihIoBuffer; |
| |
| /** |
| * NihIoMessage: |
| * @entry: list header, |
| * @addr: address received from or to be sent to, |
| * @addrlen: length of @addr, |
| * @data: buffer for message data, |
| * @control: NULL-terminated array of control messages, |
| * @int_data: user-supplied integer data, |
| * @ptr_data: user-supplied pointer data. |
| * |
| * This structure is used to represent an individual message waiting in |
| * a queue to be sent or processed. |
| * |
| * When a message is in the queue, it is sometimes useful to be able to |
| * associate it with the source or destination of the message, for example |
| * when handling errors. You may use the @int_data or @ptr_member to store |
| * an integer or pointer value that is useful to you. These are not usually |
| * initialised. |
| **/ |
| typedef struct nih_io_message { |
| NihList entry; |
| |
| struct sockaddr *addr; |
| socklen_t addrlen; |
| |
| NihIoBuffer *data; |
| struct cmsghdr **control; |
| |
| union { |
| int int_data; |
| void *ptr_data; |
| }; |
| } NihIoMessage; |
| |
| /** |
| * NihIo: |
| * @type: type of structure, |
| * @watch: associated file descriptor watch, |
| * @send_buf: buffer that pools data to be sent (NIH_IO_STREAM), |
| * @send_q: queue of messages to be sent (NIH_IO_MESSAGE), |
| * @recv_buf: buffer that pools data received (NIH_IO_STREAM), |
| * @recv_q: queue of messages received (NIH_IO_MESSAGE), |
| * @reader: function called when new data in @recv_buf or @recv_q, |
| * @close_handler: function called when socket closes, |
| * @error_handler: function called when an error occurs, |
| * @data: pointer passed to functions, |
| * @shutdown: TRUE if the structure should be freed once the buffers are empty, |
| * @free: pointer to variable to set to TRUE if freed during the watcher. |
| * |
| * This structure implements more featureful I/O handling than provided by |
| * an NihIoWatch alone. |
| * |
| * When used in the stream mode (@type is NIH_IO_STREAM), it combines an |
| * NihIoWatch and two NihIoBuffer structures to implement a high-throughput |
| * alternative to the traditional stdio functions. |
| * |
| * Those functions are optimised to reduce the number of read() or write() |
| * calls made on a file descriptor, and cannot be used to pool large |
| * amounts of data for processing. |
| * |
| * The NihIo functions are instead optimised for being able to queue and |
| * receive much data as possible, and have the data sent in the background |
| * or processed at your leisure. |
| * |
| * When used in the message mode (@type is NIH_IO_MESSAGE), it combines the |
| * NihIoWatch with an NihList of NihIoMessage structures to implement |
| * asynchronous handling of datagram sockets. |
| **/ |
| struct nih_io { |
| NihIoType type; |
| |
| NihIoWatch *watch; |
| union { |
| NihIoBuffer *send_buf; |
| NihList *send_q; |
| }; |
| union { |
| NihIoBuffer *recv_buf; |
| NihList *recv_q; |
| }; |
| |
| NihIoReader reader; |
| NihIoCloseHandler close_handler; |
| NihIoErrorHandler error_handler; |
| void *data; |
| |
| int shutdown; |
| int *free; |
| }; |
| |
| |
| NIH_BEGIN_EXTERN |
| |
| extern NihList *nih_io_watches; |
| |
| |
| void nih_io_init (void); |
| |
| NihIoWatch * nih_io_add_watch (const void *parent, int fd, |
| NihIoEvents events, |
| NihIoWatcher watcher, void *data) |
| __attribute__ ((warn_unused_result, malloc)); |
| |
| void nih_io_select_fds (int *nfds, fd_set *readfds, |
| fd_set *writefds, fd_set *exceptfds); |
| void nih_io_handle_fds (fd_set *readfds, fd_set *writewfds, |
| fd_set *exceptfds); |
| |
| |
| NihIoBuffer * nih_io_buffer_new (const void *parent) |
| __attribute__ ((warn_unused_result, malloc)); |
| |
| int nih_io_buffer_resize (NihIoBuffer *buffer, size_t grow); |
| char * nih_io_buffer_pop (const void *parent, |
| NihIoBuffer *buffer, size_t *len) |
| __attribute__ ((warn_unused_result, malloc)); |
| void nih_io_buffer_shrink (NihIoBuffer *buffer, size_t len); |
| int nih_io_buffer_push (NihIoBuffer *buffer, |
| const char *str, size_t len) |
| __attribute__ ((warn_unused_result)); |
| |
| |
| NihIoMessage *nih_io_message_new (const void *parent) |
| __attribute__ ((warn_unused_result, malloc)); |
| |
| int nih_io_message_add_control (NihIoMessage *message, int level, |
| int type, socklen_t len, |
| const void *data) |
| __attribute__ ((warn_unused_result)); |
| |
| NihIoMessage *nih_io_message_recv (const void *parent, int fd, |
| size_t *len) |
| __attribute__ ((warn_unused_result, malloc)); |
| ssize_t nih_io_message_send (NihIoMessage *message, int fd) |
| __attribute__ ((warn_unused_result)); |
| |
| |
| NihIo * nih_io_reopen (const void *parent, int fd, |
| NihIoType type, NihIoReader reader, |
| NihIoCloseHandler close_handler, |
| NihIoErrorHandler error_handler, |
| void *data) |
| __attribute__ ((warn_unused_result, malloc)); |
| void nih_io_shutdown (NihIo *io); |
| int nih_io_destroy (NihIo *io); |
| |
| NihIoMessage *nih_io_read_message (const void *parent, NihIo *io); |
| void nih_io_send_message (NihIo *io, NihIoMessage *message); |
| |
| char * nih_io_read (const void *parent, NihIo *io, |
| size_t *len) |
| __attribute__ ((warn_unused_result, malloc)); |
| int nih_io_write (NihIo *io, const char *str, |
| size_t len) |
| __attribute__ ((warn_unused_result)); |
| |
| char * nih_io_get (const void *parent, NihIo *io, |
| const char *delim) |
| __attribute__ ((warn_unused_result, malloc)); |
| |
| int nih_io_printf (NihIo *io, const char *format, ...) |
| __attribute__ ((warn_unused_result, format (printf, 2, 3))); |
| |
| |
| int nih_io_set_nonblock (int fd); |
| int nih_io_set_cloexec (int fd); |
| |
| ssize_t nih_io_get_family (int fd); |
| |
| NIH_END_EXTERN |
| |
| #endif /* NIH_IO_H */ |