+ int res;
+ do
+ res = recv (fd, buf, bufsize, MSG_PEEK);
+ while (res == -1 && errno == EINTR);
+ return res;
+}
+
+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 fd_read(fd, ...) and we'll run read
+ or SSL_read or whatever is necessary. */
+
+static struct hash_table *transport_map;
+static unsigned int transport_map_modified_tick;
+
+struct transport_info {
+ struct transport_implementation *imp;
+ void *ctx;
+};
+
+/* Register the transport layer operations that will be used when
+ reading, writing, and polling FD.
+
+ This should be used for transport layers like SSL that piggyback on
+ sockets. FD should otherwise be a real socket, on which you can
+ call getpeername, etc. */
+
+void
+fd_register_transport (int fd, struct transport_implementation *imp, void *ctx)
+{
+ struct transport_info *info;
+
+ /* The file descriptor must be non-negative to be registered.
+ Negative values are ignored by fd_close(), and -1 cannot be used as
+ hash key. */
+ assert (fd >= 0);
+
+ info = xnew (struct transport_info);
+ info->imp = imp;
+ info->ctx = ctx;
+ if (!transport_map)
+ transport_map = hash_table_new (0, NULL, NULL);
+ hash_table_put (transport_map, (void *)(intptr_t) fd, info);
+ ++transport_map_modified_tick;
+}