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