terom@154: #ifndef TRANSPORT_FD_H terom@154: #define TRANSPORT_FD_H terom@154: terom@117: /** terom@117: * @file terom@117: * terom@154: * Support for transport implementations that use POSIX file descriptor streams. terom@154: * terom@165: * This provides the read/write methods, as well as functions to implement the event-based behaviour. terom@117: */ terom@154: #include "transport_internal.h" terom@154: terom@117: #include terom@117: #include terom@117: terom@155: // forward-declare terom@155: struct transport_fd; terom@155: terom@117: /** terom@159: * Our transport_type terom@159: */ terom@159: extern const struct transport_type transport_fd_type; terom@159: terom@159: /** terom@154: * Low-level callback terom@117: */ terom@156: typedef void (*transport_fd_callback_func) (struct transport_fd *fd, short what, void *arg); terom@154: terom@154: /** terom@154: * The fd-based transport implementation terom@154: */ terom@154: struct transport_fd { terom@154: /** Base transport state */ terom@154: struct transport base; terom@154: terom@154: /** Libevent base to use */ terom@155: struct event_base *ev_base; terom@117: terom@154: /** OS file descriptor */ terom@154: evutil_socket_t fd; terom@117: terom@154: /** IO events */ terom@154: struct event *ev_read, *ev_write; terom@118: terom@154: /** Low-level callback */ terom@154: transport_fd_callback_func cb_func; terom@154: terom@154: /** Callback context argument */ terom@154: void *cb_arg; terom@117: terom@117: }; terom@117: terom@117: /** terom@154: * Get a transport_t pointer from a transport_fd terom@117: */ terom@154: #define TRANSPORT_FD_BASE(tp_ptr) (&(tp_ptr)->base) terom@117: terom@155: /** terom@155: * Invalid OS FD terom@155: */ terom@155: #define TRANSPORT_FD_INVALID ((evutil_socket_t) -1) terom@117: terom@117: /** terom@155: * Implementation of transport_methods::read terom@155: */ terom@176: err_t transport_fd__read (transport_t *transport, void *buf, size_t *len, error_t *err); terom@155: terom@155: /** terom@156: * Implementation of transport_methods::write. terom@156: * terom@156: * If this gets EAGAIN, it will automatically enable the write event, unless masked out. terom@155: */ terom@176: err_t transport_fd__write (transport_t *transport, const void *buf, size_t *len, error_t *err); terom@156: terom@156: /** terom@156: * Implementation of transport_methods::events. terom@156: * terom@156: * For TRANSPORT_READ, this will simply apply enable/disable as given. terom@156: * terom@156: * For TRANSPORT_WRITE, the write event will only be enabled if given in the mask, *and* the ev_write event is currently terom@156: * active (via transport_fd_methods_write()); otherwise, the write event will not be enabled. terom@156: */ terom@176: err_t transport_fd__events (transport_t *transport, short mask, error_t *err); terom@176: terom@176: /** terom@176: * Implementation of transport_methods::deinit. terom@176: * terom@176: * This simply calls transport_fd_deinit(). terom@176: */ terom@176: void transport_fd__deinit (transport_t *transport); terom@155: terom@155: /** terom@156: * A transport_fd_callback_func that simply invokes the transport_callback user functions. terom@156: * terom@156: * Register with a NULL cb_arg. terom@156: */ terom@156: void transport_fd_callback_user (struct transport_fd *fd, short what, void *arg); terom@156: terom@156: terom@156: terom@156: terom@156: /** terom@155: * Initialize the transport_fd to use the given, connected fd, or TRANSPORT_FD_INVALID if we don't yet have an fd. terom@154: * terom@154: * It is an error to call this if the transport_fd already has an fd set terom@165: * terom@154: * @param fd the transport_fd state terom@154: * @param ev_base the libevent base to use terom@155: * @param _fd the OS file descriptor, or TRANSPORT_FD_INVALID terom@117: */ terom@154: void transport_fd_init (struct transport_fd *fd, struct event_base *ev_base, int _fd); terom@117: terom@117: /** terom@154: * Set the fd's nonblocking mode using fcntl. terom@118: */ terom@154: err_t transport_fd_nonblock (struct transport_fd *fd, bool nonblock); terom@118: terom@118: /** terom@154: * Set or replace the fd's event callback. The callback will not be enabled. terom@154: * terom@154: * The transport must have a valid fd bound to it. terom@117: */ terom@154: err_t transport_fd_setup (struct transport_fd *fd, transport_fd_callback_func cb_func, void *cb_arg); terom@117: terom@154: /** terom@157: * Enable the specified events, any of { TRANSPORT_READ, TRANSPORT_WRITE }. terom@154: */ terom@154: err_t transport_fd_enable (struct transport_fd *fd, short mask); terom@154: terom@154: /** terom@165: * Disable the specified events, any of { TRANSPORT_READ, TRANSPORT_WRITE }. terom@156: */ terom@156: err_t transport_fd_disable (struct transport_fd *fd, short mask); terom@156: terom@156: /** terom@157: * Set the enable/disable state of our events to the given mask. terom@156: */ terom@156: err_t transport_fd_events (struct transport_fd *fd, short mask); terom@156: terom@156: /** terom@154: * Remove any old event callback present, so it will not be called anymore. terom@155: * terom@155: * It is perfectly safe to call this without any callbacks installed. terom@154: */ terom@154: void transport_fd_clear (struct transport_fd *fd); terom@154: terom@154: /** terom@157: * Setup and enable the default event handlers for transport operation, that is, use transport_fd_callback_user as the terom@157: * callback and enable TRANSPORT_READ, unless masked out. terom@157: */ terom@157: err_t transport_fd_defaults (struct transport_fd *fd); terom@157: terom@157: /** terom@154: * Replace the old fd with a new one, maintaining any event callbacks set with transport_fd_callback. If any events were terom@154: * enabled before, they are not enabled anymore. terom@154: */ terom@154: err_t transport_fd_set (struct transport_fd *fd, int _fd); terom@154: terom@154: /** terom@154: * Close an opened fd, releasing all resources within our state. terom@154: */ terom@154: err_t transport_fd_close (struct transport_fd *fd); terom@117: terom@155: /** terom@176: * Deinitialize the transport_fd. terom@165: * terom@165: * This logs a warning if the close() fails. terom@165: * terom@165: * XXX: this may actually block, I think? SO_LINGER? terom@155: */ terom@176: void transport_fd_deinit (struct transport_fd *fd); terom@117: terom@117: #endif