]> git.ozlabs.org Git - ccan/blobdiff - ccan/io/io.h
base64: fix for unsigned chars (e.g. ARM).
[ccan] / ccan / io / io.h
index 11eeade63f820c2be20a296c6c7583f771b002a3..eeb5e36ecdff0bfedd633b734cc2b380b92d8b2b 100644 (file)
@@ -223,7 +223,8 @@ struct io_plan *io_write_(struct io_conn *conn,
  *
  * 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.
  *
@@ -256,7 +257,8 @@ struct io_plan *io_read_(struct io_conn *conn,
  *
  * 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.
  *
@@ -387,6 +389,39 @@ struct io_plan *io_out_always_(struct io_conn *conn,
                                                       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.
@@ -674,6 +709,34 @@ void *io_loop(struct timers *timers, struct timer **expired);
  */
 int io_conn_fd(const struct io_conn *conn);
 
+/**
+ * io_plan_in_started - is this conn doing input I/O now?
+ * @conn: the conn.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ */
+bool io_plan_out_started(const struct io_conn *conn);
+
 /**
  * io_flush_sync - (synchronously) complete any outstanding output.
  * @conn: the connection.
@@ -692,6 +755,45 @@ int io_conn_fd(const struct io_conn *conn);
  */
 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.
+ */
+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.
@@ -712,4 +814,13 @@ struct timemono (*io_time_override(struct timemono (*now)(void)))(void);
  */
 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 */