2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file util/network.c
23 * @brief basic, low-level networking interface
25 * @author Christian Grothoff
29 #include "gnunet_util_lib.h"
31 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
32 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
33 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
35 #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
38 #ifndef INVALID_SOCKET
39 #define INVALID_SOCKET -1
43 struct GNUNET_NETWORK_Handle
52 * Address family / domain.
62 * Number of bytes in addr.
67 * Address we were bound to, or NULL.
69 struct sockaddr *addr;
75 * Test if the given protocol family is supported by this system.
77 * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
78 * @return #GNUNET_OK if the PF is supported
81 GNUNET_NETWORK_test_pf (int pf)
85 s = socket (pf, SOCK_STREAM, 0);
88 if (EAFNOSUPPORT == errno)
90 fprintf (stderr, "Failed to create test socket: %s\n", STRERROR (errno));
103 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
104 * shorten it to an acceptable length while keeping it unique
105 * and making sure it remains a valid filename (if possible).
107 * @param unixpath long path, will be freed (or same pointer returned
108 * with moved 0-termination).
109 * @return shortened unixpath, NULL on error
112 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
114 struct sockaddr_un dummy;
117 struct GNUNET_HashCode sh;
118 struct GNUNET_CRYPTO_HashAsciiEncoded ae;
121 upm = sizeof (dummy.sun_path);
122 slen = strlen (unixpath);
124 return unixpath; /* no shortening required */
125 GNUNET_CRYPTO_hash (unixpath, slen, &sh);
127 strlen (unixpath) >= upm)
129 if (NULL == (end = strrchr (unixpath, '/')))
131 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
132 _("Unable to shorten unix path `%s' while keeping name unique\n"),
134 GNUNET_free (unixpath);
139 GNUNET_CRYPTO_hash_to_enc (&sh, &ae);
140 strncat (unixpath, (char*) ae.encoding, 16);
146 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
151 * Set if a socket should use blocking or non-blocking IO.
154 * @param doBlock blocking mode
155 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
158 GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
165 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
168 SetErrnoFromWinsockError (WSAGetLastError ());
169 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
170 return GNUNET_SYSERR;
176 int flags = fcntl (fd->fd, F_GETFL);
181 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
182 return GNUNET_SYSERR;
185 flags &= ~O_NONBLOCK;
189 if (0 != fcntl (fd->fd, F_SETFL, flags))
192 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
193 return GNUNET_SYSERR;
201 * Make a socket non-inheritable to child processes
203 * @param h the socket to make non-inheritable
204 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
205 * @warning Not implemented on Windows
208 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
212 i = fcntl (h->fd, F_GETFD);
214 return GNUNET_SYSERR;
215 if (i == (i | FD_CLOEXEC))
218 if (fcntl (h->fd, F_SETFD, i) < 0)
219 return GNUNET_SYSERR;
223 b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
226 SetErrnoFromWinsockError (WSAGetLastError ());
227 return GNUNET_SYSERR;
236 * The MSG_NOSIGNAL equivalent on Mac OS X
238 * @param h the socket to make non-delaying
241 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
246 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE,
247 (const void *) &abs_value,
249 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
255 * Disable delays when sending data via the socket.
256 * (GNUnet makes sure that messages are as big as
259 * @param h the socket to make non-delaying
262 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
267 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
268 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
270 const char *abs_value = "1";
273 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY,
274 (const void *) abs_value,
276 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
282 * Perform proper canonical initialization for a network handle.
283 * Set it to non-blocking, make it non-inheritable to child
284 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
285 * stream socket) and check that it is smaller than FD_SETSIZE.
287 * @param h socket to initialize
288 * @param af address family of the socket
289 * @param type socket type
290 * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
291 * failed and the handle was destroyed
294 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
299 if (h->fd == INVALID_SOCKET)
302 SetErrnoFromWinsockError (WSAGetLastError ());
305 return GNUNET_SYSERR;
308 if (h->fd >= FD_SETSIZE)
310 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
312 return GNUNET_SYSERR;
315 if (GNUNET_OK != socket_set_inheritable (h))
316 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
317 "socket_set_inheritable");
319 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
322 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
323 return GNUNET_SYSERR;
326 socket_set_nosigpipe (h);
328 if ( (type == SOCK_STREAM)
333 socket_set_nodelay (h);
339 * accept a new connection on a socket
341 * @param desc bound socket
342 * @param address address of the connecting peer, may be NULL
343 * @param address_len length of @a address
344 * @return client socket
346 struct GNUNET_NETWORK_Handle *
347 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
348 struct sockaddr *address,
349 socklen_t *address_len)
351 struct GNUNET_NETWORK_Handle *ret;
353 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
356 struct sockaddr name;
357 socklen_t namelen = sizeof (name);
358 int gsn = getsockname (desc->fd, &name, &namelen);
361 LOG (GNUNET_ERROR_TYPE_DEBUG,
362 "Accepting connection on `%s'\n",
363 GNUNET_a2s (&name, namelen));
366 ret->fd = accept (desc->fd, address, address_len);
372 if (GNUNET_OK != initialize_network_handle (ret,
373 (NULL != address) ? address->sa_family : desc->af,
381 * Bind a socket to a particular address.
383 * @param desc socket to bind
384 * @param address address to be bound
385 * @param address_len length of @a address
386 * @param flags flags affecting bind behaviour
387 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
390 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
391 const struct sockaddr *address,
392 socklen_t address_len,
396 socklen_t bind_address_len = address_len;
399 if (address->sa_family == AF_UNIX)
401 const struct sockaddr_un *address_un = (const struct sockaddr_un *)address;
402 if (address_un->sun_path[0] == '\0')
404 sizeof (struct sockaddr_un) \
405 - sizeof (address_un->sun_path) \
406 + strnlen (address_un->sun_path + 1, sizeof (address_un->sun_path) - 1) \
416 if (desc->af == AF_INET6)
417 if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY,
420 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
428 /* This is required here for TCP sockets, but only on UNIX */
429 if ((SOCK_STREAM == desc->type)
430 && (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))))
431 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
436 if (address->sa_family == AF_UNIX && (flags & GNUNET_BIND_EXCLUSIVE) == 0)
438 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
440 (void) unlink (un->sun_path);
444 ret = bind (desc->fd, address, bind_address_len);
446 if (SOCKET_ERROR == ret)
447 SetErrnoFromWinsockError (WSAGetLastError ());
450 return GNUNET_SYSERR;
453 desc->addr = GNUNET_malloc (address_len);
454 memcpy (desc->addr, address, address_len);
455 desc->addrlen = address_len;
466 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
469 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
477 ret = closesocket (desc->fd);
478 error = WSAGetLastError ();
479 SetErrnoFromWinsockError (error);
480 LOG (GNUNET_ERROR_TYPE_DEBUG,
481 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
484 ret = close (desc->fd);
488 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
490 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
492 if (0 != unlink (un->sun_path))
493 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
497 GNUNET_NETWORK_socket_free_memory_only_ (desc);
498 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
503 * Only free memory of a socket, keep the file descriptor untouched.
508 GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc)
510 GNUNET_free_non_null (desc->addr);
516 * Box a native socket (and check that it is a socket).
518 * @param fd socket to box
519 * @return NULL on error (including not supported on target platform)
521 struct GNUNET_NETWORK_Handle *
522 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
524 struct GNUNET_NETWORK_Handle *ret;
528 /* FIXME: Find a better call to check that FD is valid */
529 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
530 return NULL; /* invalid FD */
531 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
536 if (fcntl (fd, F_GETFD) < 0)
537 return NULL; /* invalid FD */
538 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
547 * Connect a socket to some remote address.
550 * @param address peer address
551 * @param address_len length of @a address
552 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
555 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
556 const struct sockaddr *address,
557 socklen_t address_len)
562 if (address->sa_family == AF_UNIX)
564 const struct sockaddr_un *address_un = (const struct sockaddr_un *)address;
565 if(address_un->sun_path[0] == '\0')
567 sizeof (struct sockaddr_un) \
568 - sizeof (address_un->sun_path) \
569 + strnlen (address_un->sun_path + 1, sizeof (address_un->sun_path) - 1) \
573 ret = connect (desc->fd, address, address_len);
576 if (SOCKET_ERROR == ret)
578 SetErrnoFromWinsockError (WSAGetLastError ());
579 if (errno == EWOULDBLOCK)
583 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
591 * @param level protocol level of the option
592 * @param optname identifier of the option
593 * @param optval options
594 * @param optlen length of @a optval
595 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
598 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
599 int level, int optname, void *optval,
604 ret = getsockopt (desc->fd, level, optname, optval, optlen);
607 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
608 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
610 else if (SOCKET_ERROR == ret)
611 SetErrnoFromWinsockError (WSAGetLastError ());
613 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
621 * @param backlog length of the listen queue
622 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
625 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
630 ret = listen (desc->fd, backlog);
633 if (SOCKET_ERROR == ret)
634 SetErrnoFromWinsockError (WSAGetLastError ());
637 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
642 * How much data is available to be read on this descriptor?
645 * @returns #GNUNET_NO if no data is available, or on error!
648 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
653 /* How much is there to be read? */
657 error = ioctl (desc->fd, FIONREAD, &pending);
659 return (ssize_t) pending;
664 error = ioctlsocket (desc->fd, FIONREAD, &pending);
665 if (error != SOCKET_ERROR)
666 return (ssize_t) pending;
673 * Read data from a socket (always non-blocking).
676 * @param buffer buffer
677 * @param length length of @a buffer
678 * @param src_addr either the source to recv from, or all zeroes
679 * to be filled in by recvfrom
680 * @param addrlen length of the @a src_addr
683 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
684 void *buffer, size_t length,
685 struct sockaddr *src_addr, socklen_t *addrlen)
693 flags |= MSG_DONTWAIT;
696 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
698 if (SOCKET_ERROR == ret)
699 SetErrnoFromWinsockError (WSAGetLastError ());
706 * Read data from a connected socket (always non-blocking).
709 * @param buffer buffer
710 * @param length length of @a buffer
713 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
714 void *buffer, size_t length)
722 flags |= MSG_DONTWAIT;
724 ret = recv (desc->fd, buffer, length, flags);
726 if (SOCKET_ERROR == ret)
727 SetErrnoFromWinsockError (WSAGetLastError ());
734 * Send data (always non-blocking).
737 * @param buffer data to send
738 * @param length size of the @a buffer
739 * @return number of bytes sent, #GNUNET_SYSERR on error
742 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
743 const void *buffer, size_t length)
751 flags |= MSG_DONTWAIT;
755 flags |= MSG_NOSIGNAL;
758 ret = send (desc->fd, buffer, length, flags);
761 if (SOCKET_ERROR == ret)
762 SetErrnoFromWinsockError (WSAGetLastError ());
770 * Send data to a particular destination (always non-blocking).
771 * This function only works for UDP sockets.
774 * @param message data to send
775 * @param length size of the data
776 * @param dest_addr destination address
777 * @param dest_len length of @a address
778 * @return number of bytes sent, #GNUNET_SYSERR on error
781 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
782 const void *message, size_t length,
783 const struct sockaddr * dest_addr,
792 flags |= MSG_DONTWAIT;
795 flags |= MSG_NOSIGNAL;
798 if (dest_addr->sa_family == AF_UNIX)
800 const struct sockaddr_un *dest_addr_un = (const struct sockaddr_un *)dest_addr;
801 if (dest_addr_un->sun_path[0] == '\0')
803 sizeof (struct sockaddr) \
804 - sizeof (dest_addr_un->sun_path) \
805 + strnlen (dest_addr_un->sun_path + 1, sizeof (dest_addr_un->sun_path) - 1) \
809 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
811 if (SOCKET_ERROR == ret)
812 SetErrnoFromWinsockError (WSAGetLastError ());
822 * @param level protocol level of the option
823 * @param option_name option identifier
824 * @param option_value value to set
825 * @param option_len size of option_value
826 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
829 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
830 int option_name, const void *option_value,
831 socklen_t option_len)
835 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
837 if (SOCKET_ERROR == ret)
838 SetErrnoFromWinsockError (WSAGetLastError ());
840 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
845 * Create a new socket. Configure it for non-blocking IO and
846 * mark it as non-inheritable to child processes (set the
847 * close-on-exec flag).
849 * @param domain domain of the socket
850 * @param type socket type
851 * @param protocol network protocol
852 * @return new socket, NULL on error
854 struct GNUNET_NETWORK_Handle *
855 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
857 struct GNUNET_NETWORK_Handle *ret;
859 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
860 ret->fd = socket (domain, type, protocol);
867 initialize_network_handle (ret, domain, type))
874 * Shut down socket operations
876 * @param how type of shutdown
877 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
880 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
884 ret = shutdown (desc->fd, how);
887 SetErrnoFromWinsockError (WSAGetLastError ());
889 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
894 * Disable the "CORK" feature for communication with the given socket,
895 * forcing the OS to immediately flush the buffer on transmission
896 * instead of potentially buffering multiple messages. Essentially
897 * reduces the OS send buffers to zero.
900 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
903 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
912 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
914 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
917 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
919 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
925 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
926 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
929 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
930 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
932 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
942 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
947 GNUNET_CONTAINER_slist_clear (fds->handles);
953 * Add a socket to the FD set
956 * @param desc socket to add
959 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
960 const struct GNUNET_NETWORK_Handle *desc)
962 FD_SET (desc->fd, &fds->sds);
963 if (desc->fd + 1 > fds->nsds)
964 fds->nsds = desc->fd + 1;
969 * Check whether a socket is part of the fd set
973 * @return 0 if the FD is not set
976 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
977 const struct GNUNET_NETWORK_Handle *desc)
979 return FD_ISSET (desc->fd, &fds->sds);
984 * Add one fd set to another
986 * @param dst the fd set to add to
987 * @param src the fd set to add from
990 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
991 const struct GNUNET_NETWORK_FDSet *src)
996 for (nfds = src->nsds; nfds > 0; nfds--)
997 if (FD_ISSET (nfds, &src->sds))
1000 FD_SET (nfds, &dst->sds);
1001 if (nfds + 1 > dst->nsds)
1002 dst->nsds = nfds + 1;
1005 /* This is MinGW32-specific implementation that relies on the code that
1006 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
1007 * that fd being added is not already in the set.
1008 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
1011 for (i = 0; i < src->sds.fd_count; i++)
1012 FD_SET (src->sds.fd_array[i], &dst->sds);
1013 if (src->nsds > dst->nsds)
1014 dst->nsds = src->nsds;
1016 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
1022 * Copy one fd set to another
1024 * @param to destination
1025 * @param from source
1028 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
1029 const struct GNUNET_NETWORK_FDSet *from)
1031 FD_COPY (&from->sds, &to->sds);
1032 to->nsds = from->nsds;
1035 GNUNET_CONTAINER_slist_clear (to->handles);
1036 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
1042 * Return file descriptor for this network handle
1044 * @param desc wrapper to process
1045 * @return POSIX file descriptor
1048 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
1055 * Return sockaddr for this network handle
1057 * @param desc wrapper to process
1061 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1068 * Return sockaddr length for this network handle
1070 * @param desc wrapper to process
1071 * @return socklen_t for sockaddr
1074 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1076 return desc->addrlen;
1081 * Copy a native fd set
1083 * @param to destination
1084 * @param from native source set
1085 * @param nfds the biggest socket number in from + 1
1088 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1089 const fd_set * from, int nfds)
1091 FD_COPY (from, &to->sds);
1097 * Set a native fd in a set
1099 * @param to destination
1100 * @param nfd native FD to set
1103 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1105 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1106 FD_SET (nfd, &to->sds);
1107 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1112 * Test native fd in a set
1114 * @param to set to test, NULL for empty set
1115 * @param nfd native FD to test, or -1 for none
1116 * @return #GNUNET_YES if FD is set in the set
1119 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1122 if ((nfd == -1) || (to == NULL))
1124 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1129 * Add a file handle to the fd set
1131 * @param h the file handle to add
1134 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1135 const struct GNUNET_DISK_FileHandle *h)
1138 GNUNET_CONTAINER_slist_add (fds->handles,
1139 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1140 sizeof (struct GNUNET_DISK_FileHandle));
1145 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1146 FD_SET (fd, &fds->sds);
1147 if (fd + 1 > fds->nsds)
1155 * Check if a file handle is part of an fd set
1157 * @param h file handle
1158 * @return #GNUNET_YES if the file handle is part of the set
1161 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1162 const struct GNUNET_DISK_FileHandle *h)
1166 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1168 GNUNET_DISK_FileHandle));
1170 return FD_ISSET (h->fd, &fds->sds);
1176 * Checks if two fd sets overlap
1177 * @param fds1 first fd set
1178 * @param fds2 second fd set
1179 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1182 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1183 const struct GNUNET_NETWORK_FDSet *fds2)
1189 if (nfds > fds2->nsds)
1194 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1198 struct GNUNET_CONTAINER_SList_Iterator it;
1199 struct GNUNET_DISK_FileHandle *h;
1203 /*This code is somewhat hacky, we are not supposed to know what's
1204 * inside of fd_set; also the O(n^2) is really bad... */
1206 for (i = 0; i < fds1->sds.fd_count; i++)
1208 for (j = 0; j < fds2->sds.fd_count; j++)
1210 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1214 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1215 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1218 struct GNUNET_CONTAINER_SList_Iterator t;
1220 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1223 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1225 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1226 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1227 GNUNET_CONTAINER_slist_next (&t))
1229 struct GNUNET_DISK_FileHandle *fh;
1231 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1233 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1236 if (GNUNET_CONTAINER_slist_contains
1237 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1241 GNUNET_CONTAINER_slist_next (&it);
1251 * @return a new fd set
1253 struct GNUNET_NETWORK_FDSet *
1254 GNUNET_NETWORK_fdset_create ()
1256 struct GNUNET_NETWORK_FDSet *fds;
1258 fds = GNUNET_new (struct GNUNET_NETWORK_FDSet);
1260 fds->handles = GNUNET_CONTAINER_slist_create ();
1262 GNUNET_NETWORK_fdset_zero (fds);
1268 * Releases the associated memory of an fd set
1273 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1276 GNUNET_CONTAINER_slist_destroy (fds->handles);
1282 struct _select_params
1290 SOCKET wakeup_socket;
1295 _selector (LPVOID p)
1297 struct _select_params *sp = p;
1301 WaitForSingleObject (sp->standby, INFINITE);
1302 ResetEvent (sp->standby);
1303 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1304 if (FD_ISSET (sp->wakeup_socket, sp->r))
1306 FD_CLR (sp->wakeup_socket, sp->r);
1309 SetEvent (sp->wakeup);
1317 * Check if sockets or pipes meet certain conditions
1318 * @param rfds set of sockets or pipes to be checked for readability
1319 * @param wfds set of sockets or pipes to be checked for writability
1320 * @param efds set of sockets or pipes to be checked for exceptions
1321 * @param timeout relative value when to return
1322 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1325 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1326 struct GNUNET_NETWORK_FDSet *wfds,
1327 struct GNUNET_NETWORK_FDSet *efds,
1328 const struct GNUNET_TIME_Relative timeout)
1334 int read_handles = 0;
1335 int write_handles = 0;
1339 uint64_t mcs_total = 0;
1340 DWORD ms_rounded = 0;
1344 static HANDLE hEventPipeWrite = 0;
1345 static HANDLE hEventReadReady = 0;
1347 static struct _select_params sp;
1348 static HANDLE select_thread = NULL;
1349 static HANDLE select_finished_event = NULL;
1350 static HANDLE select_standby_event = NULL;
1351 static SOCKET select_wakeup_socket = -1;
1352 static SOCKET select_send_socket = -1;
1353 static struct timeval select_timeout;
1356 int writePipePos = 0;
1358 HANDLE handle_array[FD_SETSIZE + 2];
1359 int returncode = -1;
1360 int returnedpos = 0;
1362 struct GNUNET_CONTAINER_SList *handles_read;
1363 struct GNUNET_CONTAINER_SList *handles_write;
1364 struct GNUNET_CONTAINER_SList *handles_except;
1378 /* TODO: Make this growable */
1379 struct GNUNET_DISK_FileHandle *readArray[50];
1387 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1390 struct GNUNET_CONTAINER_SList_Iterator t;
1392 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1393 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1394 GNUNET_CONTAINER_slist_next (&t))
1396 struct GNUNET_DISK_FileHandle *fh;
1398 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1400 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1409 nfds = GNUNET_MAX (nfds, wfds->nsds);
1411 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1416 nfds = GNUNET_MAX (nfds, efds->nsds);
1418 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1423 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1430 LOG (GNUNET_ERROR_TYPE_ERROR,
1432 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1436 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1438 (timeout.rel_value_us -
1439 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1440 return select (nfds,
1441 (NULL != rfds) ? &rfds->sds : NULL,
1442 (NULL != wfds) ? &wfds->sds : NULL,
1443 (NULL != efds) ? &efds->sds : NULL,
1444 (timeout.rel_value_us ==
1445 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1448 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1449 /* calculate how long we need to wait in microseconds */
1450 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1452 mcs_total = INFINITE;
1453 ms_rounded = INFINITE;
1457 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1458 ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1459 if (mcs_total > 0 && ms_rounded == 0)
1462 /* select() may be used as a portable way to sleep */
1463 if (!(rfds || wfds || efds))
1469 if (NULL == select_thread)
1471 SOCKET select_listening_socket = -1;
1472 struct sockaddr_in s_in;
1477 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1478 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1480 select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1482 select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1485 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1486 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1488 alen = sizeof (s_in);
1489 s_in.sin_family = AF_INET;
1491 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1492 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1493 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1494 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1495 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1496 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1498 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1499 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1501 res = listen (select_listening_socket, SOMAXCONN);
1502 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1504 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1505 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1507 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1509 closesocket (select_listening_socket);
1511 sp.wakeup = select_finished_event;
1512 sp.standby = select_standby_event;
1513 sp.wakeup_socket = select_wakeup_socket;
1515 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1519 handles_read = GNUNET_CONTAINER_slist_create ();
1520 handles_write = GNUNET_CONTAINER_slist_create ();
1521 handles_except = GNUNET_CONTAINER_slist_create ();
1532 FD_COPY (&rfds->sds, &aread);
1534 FD_COPY (&rfds->sds, &bread);
1539 FD_COPY (&wfds->sds, &awrite);
1541 FD_COPY (&wfds->sds, &bwrite);
1546 FD_COPY (&efds->sds, &aexcept);
1548 FD_COPY (&efds->sds, &bexcept);
1552 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1553 By profiling we detected that to be true in 90% of the cases.
1556 /* Do the select now */
1557 select_timeout.tv_sec = 0;
1558 select_timeout.tv_usec = 0;
1560 /* Copy all the writes to the except, so we can detect connect() errors */
1561 for (i = 0; i < awrite.fd_count; i++)
1562 FD_SET (awrite.fd_array[i], &aexcept);
1563 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1564 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1565 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1568 if (selectret == -1)
1570 /* Throw an error early on, while we still have the context. */
1571 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1572 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1576 /* Check aexcept, add its contents to awrite
1577 This is technically wrong (aexcept might have its own descriptors), we should
1578 have checked that descriptors were in awrite originally before re-adding them from
1579 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1580 for (i = 0; i < aexcept.fd_count; i++)
1581 FD_SET (aexcept.fd_array[i], &awrite);
1583 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1584 /* Sadly, it means code duplication :( */
1585 if ((selectret > 0) || (mcs_total == 0))
1588 if (rfds && read_handles)
1590 struct GNUNET_CONTAINER_SList_Iterator i;
1593 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1594 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1595 GNUNET_CONTAINER_slist_next (&i), c++)
1597 struct GNUNET_DISK_FileHandle *fh;
1599 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1600 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1606 DWORD waitstatus = 0;
1607 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1608 error = GetLastError ();
1609 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1610 c, fh->h, bret, waitstatus, error);
1613 /* TODO: either add more errors to this condition, or eliminate it
1614 * entirely (failed to peek -> pipe is in serious trouble, should
1615 * be selected as readable).
1617 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1620 else if (waitstatus <= 0)
1622 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1623 fh, sizeof (struct GNUNET_DISK_FileHandle));
1625 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1630 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1631 fh, sizeof (struct GNUNET_DISK_FileHandle));
1636 if (wfds && write_handles)
1638 LOG (GNUNET_ERROR_TYPE_DEBUG,
1639 "Adding the write ready event to the array as %d\n", nhandles);
1640 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1641 retcode += write_handles;
1643 if (efds && ex_handles)
1645 struct GNUNET_CONTAINER_SList_Iterator i;
1647 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1648 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1649 GNUNET_CONTAINER_slist_next (&i))
1651 struct GNUNET_DISK_FileHandle *fh;
1654 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1655 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1657 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1659 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1660 fh, sizeof (struct GNUNET_DISK_FileHandle));
1666 /* Add our select() result.*/
1668 retcode += selectret;
1672 GNUNET_NETWORK_fdset_zero (rfds);
1673 if (selectret != -1)
1674 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1675 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1679 GNUNET_NETWORK_fdset_zero (wfds);
1680 if (selectret != -1)
1681 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1682 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1686 GNUNET_NETWORK_fdset_zero (efds);
1687 if (selectret != -1)
1688 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1689 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1691 GNUNET_CONTAINER_slist_destroy (handles_read);
1692 GNUNET_CONTAINER_slist_destroy (handles_write);
1693 GNUNET_CONTAINER_slist_destroy (handles_except);
1695 if (selectret == -1)
1700 /* If we got this far, use slower implementation that is able to do a waiting select
1701 on both sockets and pipes simultaneously */
1703 /* Events for pipes */
1704 if (!hEventReadReady)
1705 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1706 if (!hEventPipeWrite)
1707 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1723 FD_COPY (&rfds->sds, &aread);
1725 FD_COPY (&rfds->sds, &bread);
1730 FD_COPY (&wfds->sds, &awrite);
1732 FD_COPY (&wfds->sds, &bwrite);
1737 FD_COPY (&efds->sds, &aexcept);
1739 FD_COPY (&efds->sds, &bexcept);
1742 /* We will first Add the PIPES to the events */
1744 if (rfds && read_handles)
1746 struct GNUNET_CONTAINER_SList_Iterator i;
1748 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1749 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1750 GNUNET_CONTAINER_slist_next (&i))
1752 struct GNUNET_DISK_FileHandle *fh;
1754 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1756 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1758 /* Read zero bytes to check the status of the pipe */
1759 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1761 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1763 DWORD error_code = GetLastError ();
1765 if (error_code == ERROR_IO_PENDING)
1767 LOG (GNUNET_ERROR_TYPE_DEBUG,
1768 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1770 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1771 readArray[readPipes++] = fh;
1775 LOG (GNUNET_ERROR_TYPE_DEBUG,
1776 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1777 handle_array[nhandles++] = hEventReadReady;
1778 readArray[readPipes++] = fh;
1783 LOG (GNUNET_ERROR_TYPE_DEBUG,
1784 "Adding the read ready event to the array as %d\n", nhandles);
1785 handle_array[nhandles++] = hEventReadReady;
1786 readArray[readPipes++] = fh;
1791 GNUNET_CONTAINER_slist_add (handles_read,
1792 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1793 fh, sizeof (struct GNUNET_DISK_FileHandle));
1797 if (wfds && write_handles)
1799 LOG (GNUNET_ERROR_TYPE_DEBUG,
1800 "Adding the write ready event to the array as %d\n", nhandles);
1801 handle_array[nhandles++] = hEventPipeWrite;
1802 writePipePos = nhandles;
1804 if (efds && ex_handles)
1806 struct GNUNET_CONTAINER_SList_Iterator i;
1808 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1809 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1810 GNUNET_CONTAINER_slist_next (&i))
1812 struct GNUNET_DISK_FileHandle *fh;
1815 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1817 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1819 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1821 GNUNET_CONTAINER_slist_add (handles_except,
1822 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1824 sizeof (struct GNUNET_DISK_FileHandle));
1834 LOG (GNUNET_ERROR_TYPE_DEBUG,
1835 "Adding the socket event to the array as %d\n",
1837 handle_array[nhandles++] = select_finished_event;
1838 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1842 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1843 select_timeout.tv_usec =(timeout.rel_value_us -
1844 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1845 sp.tv = &select_timeout;
1847 FD_SET (select_wakeup_socket, &aread);
1850 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1855 /* Failed connections cause sockets to be set in errorfds on W32,
1856 * but on POSIX it should set them in writefds.
1857 * First copy all awrite sockets to aexcept, later we'll
1858 * check aexcept and set its contents in awrite as well
1859 * Sockets are also set in errorfds when OOB data is available,
1860 * but we don't use OOB data.
1862 for (i = 0; i < awrite.fd_count; i++)
1863 FD_SET (awrite.fd_array[i], &aexcept);
1864 ResetEvent (select_finished_event);
1865 SetEvent (select_standby_event);
1868 handle_array[nhandles] = NULL;
1869 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
1870 nfds, nhandles, mcs_total);
1874 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
1875 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode);
1879 GNUNET_break (0); /* This branch shouldn't actually be executed...*/
1880 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1881 returncode = WAIT_TIMEOUT;
1885 /* Shouldn't come this far. If it does - investigate. */
1891 /* Don't wake up select-thread when delay is 0, it should return immediately
1892 * and wake up by itself.
1895 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1896 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1897 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1902 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1905 /* Check aexcept, add its contents to awrite */
1906 for (i = 0; i < aexcept.fd_count; i++)
1907 FD_SET (aexcept.fd_array[i], &awrite);
1910 returnedpos = returncode - WAIT_OBJECT_0;
1911 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1913 if (nhandles && (returnedpos < nhandles))
1918 retcode += sp.status;
1920 if ((writePipePos != -1) && (returnedpos < writePipePos))
1922 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1923 retcode += write_handles;
1924 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1926 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1927 /* We have some pipes ready for read. */
1928 if (returnedpos < readPipes)
1930 for (i = 0; i < readPipes; i++)
1938 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1939 error = GetLastError ();
1940 LOG (GNUNET_ERROR_TYPE_DEBUG,
1941 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1942 i, readArray[i]->h, bret, waitstatus, error);
1945 /* TODO: either add more errors to this condition, or eliminate it
1946 * entirely (failed to peek -> pipe is in serious trouble, should
1947 * be selected as readable).
1949 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1952 else if (waitstatus <= 0)
1954 GNUNET_CONTAINER_slist_add (handles_read,
1955 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1957 sizeof (struct GNUNET_DISK_FileHandle));
1959 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1960 readArray[i], readArray[i]->h);
1964 if (!nhandles || (returnedpos >= nhandles))
1965 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1968 struct GNUNET_CONTAINER_SList_Iterator t;
1970 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1971 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1972 GNUNET_CONTAINER_slist_next (&t))
1974 struct GNUNET_DISK_FileHandle *fh;
1976 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1978 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1983 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1984 GNUNET_NETWORK_fdset_zero (rfds);
1985 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1986 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1987 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1991 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1992 GNUNET_NETWORK_fdset_zero (wfds);
1993 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1994 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1995 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1999 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
2000 GNUNET_NETWORK_fdset_zero (efds);
2001 if (retcode != -1 && nhandles && (returnedpos < nhandles))
2002 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
2003 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
2005 GNUNET_CONTAINER_slist_destroy (handles_read);
2006 GNUNET_CONTAINER_slist_destroy (handles_write);
2007 GNUNET_CONTAINER_slist_destroy (handles_except);
2011 struct GNUNET_CONTAINER_SList_Iterator t;
2013 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
2014 for (i = 0; i < rfds->sds.fd_count; i++)
2016 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
2018 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
2019 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
2020 GNUNET_CONTAINER_slist_next (&t))
2022 struct GNUNET_DISK_FileHandle *fh;
2024 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
2026 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
2031 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
2032 for (i = 0; i < wfds->sds.fd_count; i++)
2034 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
2039 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
2040 for (i = 0; i < efds->sds.fd_count; i++)
2042 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
2045 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
2047 if (nhandles && (returnedpos < nhandles))
2054 /* end of network.c */