#include <ccan/tal/tal.h>
#include <ccan/typesafe_cb/typesafe_cb.h>
#include <stdbool.h>
+#include <poll.h>
#include <unistd.h>
struct timers;
* int fd[2];
* struct io_conn *conn;
*
- * pipe(fd);
+ * if (pipe(fd) != 0)
+ * exit(1);
* conn = io_new_conn(NULL, fd[0], conn_init, (const char *)"hi!");
* if (!conn)
* exit(1);
* @arg: the argument to @init.
*
* When @fd becomes readable, we accept(), create a new connection,
- * (tal'ocated off @ctx) and pass that to init().
+ * (tal'ocated off @ctx) and pass that to init(). Note that if there is
+ * an error on this file descriptor, it will be freed.
*
* Returns NULL on error (and sets errno).
*
*
* This creates a plan to read data into a buffer. Once it's all
* read, the @next function will be called: on an error, the finish
- * function is called instead.
+ * function is called instead. If read() returns 0 (EOF) errno is set
+ * to 0.
*
* Note that the I/O may actually be done immediately.
*
*
* This creates a plan to read data into a buffer. Once any data is
* read, @len is updated and the @next function will be called: on an
- * error, the finish function is called instead.
+ * error, the finish function is called instead. If read() returns 0 (EOF)
+ * errno is set to 0.
*
* Note that the I/O may actually be done immediately.
*
void *),
void *arg);
+/**
+ * io_sock_shutdown - start socket close process (flushes TCP sockets).
+ * @conn: the connection the plan is for
+ *
+ * Simply closing a TCP socket can lose data; unfortunately you should
+ * shutdown(SHUT_WR) and wait for the other side to see this and close.
+ * Of course, you also need to set a timer, in case it doesn't (you may
+ * already have some responsiveness timer, of course).
+ *
+ * On error, is equivalent to io_close().
+ *
+ * Example:
+ * #include <ccan/timer/timer.h>
+ *
+ * // Timer infra needs wrapper to contain extra data.
+ * struct timeout_timer {
+ * struct timer t;
+ * struct io_conn *conn;
+ * };
+ * static struct timers timers;
+ *
+ * static struct io_plan *flush_and_close(struct io_conn *conn)
+ * {
+ * struct timeout_timer *timeout;
+ * // Freed if conn closes normally.
+ * timeout = tal(conn, struct timeout_timer);
+ * timeout->conn = conn;
+ * timer_addrel(&timers, &timeout->t, time_from_sec(5));
+ * return io_sock_shutdown(conn);
+ * }
+ */
+struct io_plan *io_sock_shutdown(struct io_conn *conn);
+
/**
* io_connect - create an asynchronous connection to a listening socket.
* @conn: the connection that plan is for.
* io_write(conn, b->out, sizeof(b->out), io_close_cb,b));
* }
*/
-#define io_duplex(conn, in_plan, out_plan) \
- (io_duplex_prepare(conn), io_duplex_(in_plan, out_plan))
-
-struct io_plan *io_duplex_(struct io_plan *in_plan, struct io_plan *out_plan);
-void io_duplex_prepare(struct io_conn *conn);
+struct io_plan *io_duplex(struct io_conn *conn,
+ struct io_plan *in_plan, struct io_plan *out_plan);
/**
* io_halfclose - close half of an io_duplex connection.
/* FIXME: io_recvfrom/io_sendto */
/**
- * io_close - plan to close a connection.
+ * io_close - close a connection.
* @conn: the connection to close.
*
- * On return to io_loop, the connection will be closed. It doesn't have
- * to be the current connection and it doesn't need to be idle. No more
- * IO or callbacks will occur.
+ * The connection is immediately freed: it doesn't have to be the
+ * current connection and it doesn't need to be idle. No more IO or
+ * callbacks will occur, but if a function was added by io_set_finish()
+ * it will be called with the current errno preserved.
*
- * You can close a connection twice without harmful effects.
+ * This is equivalent to tal_free(io_conn), except it returns an io_plan
+ * for use in an io callback.
*
* Example:
* static struct io_plan *close_on_timeout(struct io_conn *conn, const char *msg)
* io_close_cb - helper callback to close a connection.
* @conn: the connection.
*
- * This schedules a connection to be closed; designed to be used as
- * a callback function.
+ * This is closes a connection; designed to be used as a callback
+ * function.
*
* Example:
* #define close_on_timeout io_close_cb
*/
struct io_plan *io_close_cb(struct io_conn *, void *unused);
+/**
+ * io_close_taken_fd - close a connection, but remove the filedescriptor first.
+ * @conn: the connection to take the file descriptor from and close.
+ *
+ * io_close closes the file descriptor underlying the io_conn; this version does
+ * not. Presumably you have used io_conn_fd() on it beforehand and will take
+ * care of the fd yourself.
+ *
+ * Note that this also turns off O_NONBLOCK on the fd.
+ *
+ * Example:
+ * static struct io_plan *steal_fd(struct io_conn *conn, int *fd)
+ * {
+ * *fd = io_conn_fd(conn);
+ * printf("stealing fd %i and closing\n", *fd);
+ * return io_close_taken_fd(conn);
+ * }
+ */
+struct io_plan *io_close_taken_fd(struct io_conn *conn);
+
/**
* io_loop - process fds until all closed on io_break.
* @timers - timers which are waiting to go off (or NULL for none)
* io_conn_fd - get the fd from a connection.
* @conn: the connection.
*
- * Sometimes useful, eg for getsockname().
+ * Sometimes useful, eg for getsockname(). Note that the fd is O_NONBLOCK.
+ *
+ * See Also:
+ * io_close_taken_fd
*/
int io_conn_fd(const struct io_conn *conn);
/**
- * io_set_debug - set synchronous mode on a connection.
- * @conn: the connection.
- * @debug: whether to enable or disable debug.
+ * io_plan_in_started - is this conn doing input I/O now?
+ * @conn: the conn.
*
- * Once @debug is true on a connection, all I/O is done synchronously
- * as soon as it is set, until it is unset or @conn is closed. This
- * makes it easy to debug what's happening with a connection, but note
- * that other connections are starved while this is being done.
+ * This returns true if input I/O has been performed on the conn but
+ * @next hasn't been called yet. For example, io_read() may have done
+ * a partial read.
*
- * See also: io_debug_complete()
+ * This can be useful if we want to terminate a connection only after
+ * reading a whole packet: if this returns true, we would wait until
+ * @next is called.
+ */
+bool io_plan_in_started(const struct io_conn *conn);
+
+/**
+ * io_plan_out_started - is this conn doing output I/O now?
+ * @conn: the conn.
*
- * Example:
- * // Dumb init function to set debug and tell conn to close.
- * static struct io_plan *conn_init(struct io_conn *conn, const char *msg)
- * {
- * io_set_debug(conn, true);
- * return io_close(conn);
- * }
+ * This returns true if output I/O has been performed on the conn but
+ * @next hasn't been called yet. For example, io_write() may have done
+ * a partial write.
+ *
+ * This can be useful if we want to terminate a connection only after
+ * writing a whole packet: if this returns true, we would wait until
+ * @next is called.
*/
-void io_set_debug(struct io_conn *conn, bool debug);
+bool io_plan_out_started(const struct io_conn *conn);
/**
- * io_debug_complete - empty function called when conn is closing/waiting.
+ * io_flush_sync - (synchronously) complete any outstanding output.
* @conn: the connection.
*
- * This is for putting a breakpoint onto, when debugging. It is called
- * when a conn with io_set_debug() true can no longer be synchronous:
- * 1) It is io_close()'d
- * 2) It enters io_wait() (sychronous debug will resume after io_wake())
- * 3) io_break() is called (sychronous debug will resume after io_loop())
+ * This is generally used as an emergency escape, for example when we
+ * want to write an error message on a socket before terminating, but it may
+ * be in the middle of existing I/O. We don't want to service any other
+ * IO, either.
+ *
+ * This returns true if all pending output is complete, false on error.
+ * The next callback is not called on the conn, but will be as soon as
+ * io_loop() is called.
+ *
+ * See Also:
+ * io_close_taken_fd
+ */
+bool io_flush_sync(struct io_conn *conn);
+
+/**
+ * io_conn_exclusive - set/unset an io_conn to exclusively serviced
+ * @conn: the connection
+ * @exclusive: whether to be exclusive or not
+ *
+ * If any io_conn is set exclusive, then no non-exclusive io_conn (or
+ * io_listener) will be serviced by io_loop(). If it's a io_duplex io_conn(),
+ * then io_conn_exclusive() makes the read-side exclusive; io_conn_out_exclusive()
+ * makes the write-side exclusive.
+ *
+ * This allows you to temporarily service only one (or several) fds.
+ * For example, you might want to flush out one io_conn and not
+ * receive any new connections or read any other input.
+ *
+ * Returns true if any exclusive io_conn remain, otherwise false.
+ * (This is useful for checking your own logic: dangling exclusive io_conn
+ * are dangerous!).
+ */
+bool io_conn_exclusive(struct io_conn *conn, bool exclusive);
+
+/**
+ * io_conn_out_exclusive - set/unset exclusive on the write-side of a duplex
+ * @conn: the connection, post io_duplex
+ * @exclusive: whether to be exclusive or not
+ *
+ * See io_conn_exclusive() above.
*/
-void io_debug_complete(struct io_conn *conn);
+bool io_conn_out_exclusive(struct io_conn *conn, bool exclusive);
+
+/**
+ * io_fd_block - helper to set an fd blocking/nonblocking.
+ * @fd: the file descriptor
+ * @block: true to set blocking, false to set non-blocking.
+ *
+ * Generally only fails is @fd isn't a valid file descriptor, otherwise
+ * returns true.
+ */
+bool io_fd_block(int fd, bool block);
+
+/**
+ * io_time_override - override the normal call for time.
+ * @nowfn: the function to call.
+ *
+ * io usually uses time_mono() internally, but this forces it
+ * to use your function (eg. for debugging). Returns the old
+ * one.
+ */
+struct timemono (*io_time_override(struct timemono (*now)(void)))(void);
+
+/**
+ * io_poll_override - override the normal call for poll.
+ * @pollfn: the function to call.
+ *
+ * io usually uses poll() internally, but this forces it to use your
+ * function (eg. for debugging, suppressing fds, or polling on others unknown
+ * to ccan/io). Returns the old one.
+ */
+int (*io_poll_override(int (*poll)(struct pollfd *fds, nfds_t nfds, int timeout)))(struct pollfd *, nfds_t, int);
+
+/**
+ * io_have_fd - do we own this file descriptor?
+ * @fd: the file descriptor.
+ * @listener: if non-NULL, set to true if it's a listening socket (io_listener).
+ *
+ * Returns NULL if we don't own it, otherwise a struct io_conn * or struct io_listener *.
+ */
+const void *io_have_fd(int fd, bool *listener);
+
#endif /* CCAN_IO_H */