]> git.ozlabs.org Git - ccan/blobdiff - ccan/io/io.h
io: don't leave errno as a random value when we hit EOF.
[ccan] / ccan / io / io.h
index 8efc0024c9d230a580bd7838de4d7ad30503e381..510ee0be0166033618768b91cbcafcec8541c85b 100644 (file)
@@ -4,6 +4,7 @@
 #include <ccan/tal/tal.h>
 #include <ccan/typesafe_cb/typesafe_cb.h>
 #include <stdbool.h>
+#include <poll.h>
 #include <unistd.h>
 
 struct timers;
@@ -109,7 +110,8 @@ void io_set_finish_(struct io_conn *conn,
  * @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).
  *
@@ -221,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.
  *
@@ -254,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.
  *
@@ -629,12 +633,14 @@ 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,
+ * @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)
  * {
@@ -663,10 +669,69 @@ void *io_loop(struct timers *timers, struct timer **expired);
  * 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_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.
+ *
+ * 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_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.
@@ -677,4 +742,14 @@ int io_conn_fd(const struct io_conn *conn);
  */
 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);
+
 #endif /* CCAN_IO_H */