+static rb_fde_t *
+make_fde_from_wsaprotocol_info(void *data)
+{
+ WSAPROTOCOL_INFO *info = data;
+ SOCKET t;
+ t = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, info, 0, 0);
+ if(t == INVALID_SOCKET)
+ {
+ rb_get_errno();
+ return NULL;
+ }
+ return rb_open(t, RB_FD_SOCKET, "remote_socket");
+}
+
+static uint8_t fd_buf[16384];
+#define MAGIC_CONTROL 0xFF0ACAFE
+
+int
+rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasize, pid_t pid)
+{
+ size_t bufsize =
+ sizeof(uint32_t) + sizeof(uint8_t) + (sizeof(WSAPROTOCOL_INFO) * (size_t)count) +
+ sizeof(size_t) + datasize;
+ int i;
+ uint32_t magic = MAGIC_CONTROL;
+ void *ptr;
+ if(count > 4)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ if(bufsize > sizeof(fd_buf))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ memset(fd_buf, 0, sizeof(fd_buf));
+
+ ptr = fd_buf;
+ memcpy(ptr, &magic, sizeof(magic));
+ ptr = (void *)((uintptr_t)ptr + (uintptr_t)sizeof(magic));
+ *((uint8_t *)ptr) = count;
+ ptr = (void *)((uintptr_t)ptr + (uintptr_t)sizeof(uint8_t));
+
+ for(i = 0; i < count; i++)
+ {
+ make_wsaprotocol_info(pid, F[i], (WSAPROTOCOL_INFO *) ptr);
+ ptr = (void *)((uintptr_t)ptr + (uintptr_t)sizeof(WSAPROTOCOL_INFO));
+ }
+ memcpy(ptr, &datasize, sizeof(size_t));
+ ptr = (void *)((uintptr_t)ptr + (uintptr_t)sizeof(size_t));
+ memcpy(ptr, data, datasize);
+ return rb_write(xF, fd_buf, bufsize);
+}
+
+#ifdef MYMIN
+#undef MYMIN
+#endif
+#define MYMIN(a, b) ((a) < (b) ? (a) : (b))
+
+int
+rb_recv_fd_buf(rb_fde_t *F, void *data, size_t datasize, rb_fde_t **xF, int nfds)
+{
+ size_t minsize = sizeof(uint32_t) + sizeof(uint8_t) + sizeof(size_t);
+ size_t datalen;
+ ssize_t retlen;
+ uint32_t magic;
+ uint8_t count;
+ unsigned int i;
+ void *ptr;
+ ssize_t ret;
+ memset(fd_buf, 0, sizeof(fd_buf)); /* some paranoia here... */
+ ret = rb_read(F, fd_buf, sizeof(fd_buf));
+ if(ret <= 0)
+ {
+ return ret;
+ }
+ if(ret < (ssize_t) minsize)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ ptr = fd_buf;
+ memcpy(&magic, ptr, sizeof(uint32_t));
+ if(magic != MAGIC_CONTROL)
+ {
+ errno = EAGAIN;
+ return -1;
+ }
+ ptr = (void *)((uintptr_t)ptr + (uintptr_t)sizeof(uint32_t));
+ memcpy(&count, ptr, sizeof(uint8_t));
+ ptr = (void *)((uintptr_t)ptr + (uintptr_t)sizeof(uint8_t));
+ for(i = 0; i < count && i < (unsigned int)nfds; i++)
+ {
+ rb_fde_t *tF = make_fde_from_wsaprotocol_info(ptr);
+ if(tF == NULL)
+ return -1;
+ xF[i] = tF;
+ ptr = (void *)((uintptr_t)ptr + (uintptr_t)sizeof(WSAPROTOCOL_INFO));
+ }
+ memcpy(&datalen, ptr, sizeof(size_t));
+ ptr = (void *)((uintptr_t)ptr + (uintptr_t)sizeof(size_t));
+ retlen = MYMIN(datalen, datasize);
+ memcpy(data, ptr, datalen);
+ return retlen;
+}