+static int
+sock_poll (int fd, double timeout, int wait_for)
+{
+#ifdef HAVE_SELECT
+ return select_fd (fd, timeout, wait_for);
+#else
+ return 1;
+#endif
+}
+
+static void
+sock_close (int fd)
+{
+ close (fd);
+ DEBUGP (("Closed fd %d\n", fd));
+}
+#undef read
+#undef write
+#undef close
+\f
+/* Reading and writing from the network. We build around the socket
+ (file descriptor) API, but support "extended" operations for things
+ that are not mere file descriptors under the hood, such as SSL
+ sockets.
+
+ That way the user code can call xread(fd, ...) and we'll run read
+ or SSL_read or whatever is necessary. */
+
+static struct hash_table *extended_map;
+static long extended_map_modified_tick;
+
+struct extended_info {
+ xreader_t reader;
+ xwriter_t writer;
+ xpoller_t poller;
+ xcloser_t closer;
+ void *ctx;
+};
+
+void
+register_extended (int fd, xreader_t reader, xwriter_t writer,
+ xpoller_t poller, xcloser_t closer, void *ctx)
+{
+ struct extended_info *info = xnew (struct extended_info);
+ info->reader = reader;
+ info->writer = writer;
+ info->poller = poller;
+ info->closer = closer;
+ info->ctx = ctx;
+ if (!extended_map)
+ extended_map = hash_table_new (0, NULL, NULL);
+ hash_table_put (extended_map, (void *) fd, info);
+ ++extended_map_modified_tick;
+}
+
+/* When xread/xwrite are called multiple times in a loop, they should
+ remember the INFO pointer instead of fetching it every time. It is
+ not enough to compare FD to LAST_FD because FD might have been
+ closed and reopened. modified_tick ensures that changes to
+ extended_map will not be unnoticed.
+
+ This is a macro because we want the static storage variables to be
+ per-function. */
+
+#define LAZY_RETRIEVE_INFO(info) do { \
+ static struct extended_info *last_info; \
+ static int last_fd = -1, last_tick; \
+ if (!extended_map) \
+ info = NULL; \
+ else if (last_fd == fd && last_tick == extended_map_modified_tick) \
+ info = last_info; \
+ else \
+ { \
+ info = hash_table_get (extended_map, (void *) fd); \
+ last_fd = fd; \
+ last_tick = extended_map_modified_tick; \
+ } \
+} while (0)
+
+/* Read no more than BUFSIZE bytes of data from FD, storing them to
+ BUF. If TIMEOUT is non-zero, the operation aborts if no data is
+ received after that many seconds. If TIMEOUT is -1, the value of
+ opt.timeout is used for TIMEOUT. */