chiark / gitweb /
Build system: Fix check for <linux/if_tun.h> and remove our copy
[secnet.git] / util.h
diff --git a/util.h b/util.h
index c4e34a8f2458f619f99e6ff23b709d846a6aeec7..de1aaa51b8fd99ed0ecc8afbcc32b1ed5eae95ea 100644 (file)
--- a/util.h
+++ b/util.h
@@ -23,6 +23,7 @@ extern void buffer_assert_used(struct buffer_if *buffer, cstring_t file,
                               int line);
 extern void buffer_new(struct buffer_if *buffer, int32_t len);
 extern void buffer_init(struct buffer_if *buffer, int32_t max_start_pad);
+extern void buffer_destroy(struct buffer_if *buffer);
 extern void buffer_copy(struct buffer_if *dst, const struct buffer_if *src);
 extern void *buf_append(struct buffer_if *buf, int32_t amount);
 extern void *buf_prepend(struct buffer_if *buf, int32_t amount);
@@ -82,9 +83,94 @@ extern void send_nak(const struct comm_addr *dest, uint32_t our_index,
 extern int consttime_memeq(const void *s1, const void *s2, size_t n);
 
 const char *iaddr_to_string(const union iaddr *ia);
-bool_t iaddr_equal(const union iaddr *ia, const union iaddr *ib);
 int iaddr_socklen(const union iaddr *ia);
 
+void string_item_to_iaddr(const item_t *item, uint16_t port, union iaddr *ia,
+                         const char *desc);
+
+
+/*
+ * SBUF_DEFINE(int nbufs, size_t size);
+ *   // Generates a number of definitions and statements organising
+ *   // nbufs rotating char[size] buffers such that subsequent code
+ *   // may refer to:
+ * char *const SBUF;
+ */
+#define SBUF_DEFINE(nbufs, size)                       \
+    static int static_bufs__bufnum;                    \
+    static char static_bufs__bufs[(nbufs)][(size)];    \
+    static_bufs__bufnum++;                             \
+    static_bufs__bufnum %= (nbufs);                    \
+    static_bufs__bufs[static_bufs__bufnum]
+#define SBUF (static_bufs__bufs[static_bufs__bufnum])
+
+/*----- line-buffered asynch input -----*/
+
+enum async_linebuf_result {
+    async_linebuf_nothing,
+    async_linebuf_ok,
+    async_linebuf_eof,
+    async_linebuf_broken,
+};
+
+const char *pollbadbit(int revents); /* returns 0, or bad bit description */
+
+enum async_linebuf_result
+async_linebuf_read(struct pollfd *pfd, struct buffer_if *buf,
+                  const char **emsg_out);
+   /* Implements reading whole lines, asynchronously.  Use like
+    * this:
+    *   - set up the fd, which should be readable, O_NONBLOCK
+    *   - set up and initialise buffer, which should be big enough
+    *     for one line plus its trailing newline, and be empty
+    *     with start==base
+    *   - in your beforepoll_fn, be interested in POLLIN
+    *   - in your afterpoll_fn, repeatedly call this function
+    *     until it doesn't return `nothing'
+    *   - after you're done, simply close fd and free or reset buf
+    * State on return from async_linebuf_read depends on return value:
+    *
+    *   async_linebuf_nothing:
+    *
+    *      No complete lines available right now.  You should return
+    *      from afterpoll.  buf should be left untouched until the
+    *      next call to async_linebuf_read.
+    *
+    *   async_linebuf_ok:
+    *
+    *      buf->base contains a input line as a nul-terminated string
+    *      (\n replaced by \0); *emsg_out==0.  You must call
+    *      async_linebuf_read again before returning from afterpoll.
+    *
+    *   async_linebuf_eof:
+    *
+    *      EOF on stream.  buf->base contains any partial
+    *      (non-newline-terminated) line; *emsg_out!=0 iff there was
+    *      such a partial line.  You can call async_linebuf_read again
+    *      if you like but it will probably just return eof again.
+    *
+    *   broken:
+    *
+    *      Fatal problem (might be overly long lines, nuls in input
+    *      data, bad bits in pfd->revents, errors from read, etc.)
+    *
+    *      *emsg_out is the error message describing the problem;
+    *      this message might be stored in buf, might be from
+    *      strerror, or might be a constant.
+    *
+    *      You must not call async_linebuf_read again.  buf contents
+    *      is undefined: it is only safe to reset or free.
+    *
+    * While using this function, do not look at buf->start or ->size
+    * or anything after the first '\0' in buf.
+    *
+    * If you decide to stop reading with async_linebuf_read that's
+    * fine and you can reset or free buf, but you risk missing some
+    * read-but-not-reported data.
+    */
+
+/*----- some handy macros -----*/
+
 #define MINMAX(ae,be,op) ({                    \
        typeof((ae)) a=(ae);                    \
        typeof((be)) b=(be);                    \
@@ -93,4 +179,10 @@ int iaddr_socklen(const union iaddr *ia);
 #define MAX(a,b) MINMAX((a),(b),>)
 #define MIN(a,b) MINMAX((a),(b),<)
 
+#define MAX_RAW(a,b) ((a)>(b)?(a):(b))
+#define MIN_RAW(a,b) ((a)<(b)?(a):(b))
+
+static inline bool_t iswouldblock(int e)
+    { return e==EWOULDBLOCK || e==EAGAIN; }
+
 #endif /* util_h */