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 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
91 "Failed to create test socket: %s\n",
105 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
106 * shorten it to an acceptable length while keeping it unique
107 * and making sure it remains a valid filename (if possible).
109 * @param unixpath long path, will be freed (or same pointer returned
110 * with moved 0-termination).
111 * @return shortened unixpath, NULL on error
114 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
116 struct sockaddr_un dummy;
119 struct GNUNET_HashCode sh;
120 struct GNUNET_CRYPTO_HashAsciiEncoded ae;
123 upm = sizeof (dummy.sun_path);
124 slen = strlen (unixpath);
126 return unixpath; /* no shortening required */
127 GNUNET_CRYPTO_hash (unixpath, slen, &sh);
129 strlen (unixpath) >= upm)
131 if (NULL == (end = strrchr (unixpath, '/')))
133 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
134 _("Unable to shorten unix path `%s' while keeping name unique\n"),
136 GNUNET_free (unixpath);
141 GNUNET_CRYPTO_hash_to_enc (&sh, &ae);
142 strncat (unixpath, (char*) ae.encoding, 16);
148 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
153 * Set if a socket should use blocking or non-blocking IO.
156 * @param doBlock blocking mode
157 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
160 GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
167 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
170 SetErrnoFromWinsockError (WSAGetLastError ());
171 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
172 return GNUNET_SYSERR;
178 int flags = fcntl (fd->fd, F_GETFL);
183 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
184 return GNUNET_SYSERR;
187 flags &= ~O_NONBLOCK;
191 if (0 != fcntl (fd->fd, F_SETFL, flags))
194 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
195 return GNUNET_SYSERR;
203 * Make a socket non-inheritable to child processes
205 * @param h the socket to make non-inheritable
206 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
207 * @warning Not implemented on Windows
210 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
214 i = fcntl (h->fd, F_GETFD);
216 return GNUNET_SYSERR;
217 if (i == (i | FD_CLOEXEC))
220 if (fcntl (h->fd, F_SETFD, i) < 0)
221 return GNUNET_SYSERR;
225 b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
228 SetErrnoFromWinsockError (WSAGetLastError ());
229 return GNUNET_SYSERR;
238 * The MSG_NOSIGNAL equivalent on Mac OS X
240 * @param h the socket to make non-delaying
243 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
248 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE,
249 (const void *) &abs_value,
251 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
257 * Disable delays when sending data via the socket.
258 * (GNUnet makes sure that messages are as big as
261 * @param h the socket to make non-delaying
264 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
269 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
270 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
272 const char *abs_value = "1";
275 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY,
276 (const void *) abs_value,
278 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
284 * Perform proper canonical initialization for a network handle.
285 * Set it to non-blocking, make it non-inheritable to child
286 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
287 * stream socket) and check that it is smaller than FD_SETSIZE.
289 * @param h socket to initialize
290 * @param af address family of the socket
291 * @param type socket type
292 * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
293 * failed and the handle was destroyed
296 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
301 if (h->fd == INVALID_SOCKET)
304 SetErrnoFromWinsockError (WSAGetLastError ());
307 return GNUNET_SYSERR;
310 if (h->fd >= FD_SETSIZE)
312 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
314 return GNUNET_SYSERR;
317 if (GNUNET_OK != socket_set_inheritable (h))
318 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
319 "socket_set_inheritable");
321 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
324 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
325 return GNUNET_SYSERR;
328 socket_set_nosigpipe (h);
330 if ( (type == SOCK_STREAM)
335 socket_set_nodelay (h);
341 * accept a new connection on a socket
343 * @param desc bound socket
344 * @param address address of the connecting peer, may be NULL
345 * @param address_len length of @a address
346 * @return client socket
348 struct GNUNET_NETWORK_Handle *
349 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
350 struct sockaddr *address,
351 socklen_t *address_len)
353 struct GNUNET_NETWORK_Handle *ret;
355 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
358 struct sockaddr name;
359 socklen_t namelen = sizeof (name);
360 int gsn = getsockname (desc->fd, &name, &namelen);
363 LOG (GNUNET_ERROR_TYPE_DEBUG,
364 "Accepting connection on `%s'\n",
365 GNUNET_a2s (&name, namelen));
368 ret->fd = accept (desc->fd, address, address_len);
374 if (GNUNET_OK != initialize_network_handle (ret,
375 (NULL != address) ? address->sa_family : desc->af,
383 * Bind a socket to a particular address.
385 * @param desc socket to bind
386 * @param address address to be bound
387 * @param address_len length of @a address
388 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
391 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
392 const struct sockaddr *address,
393 socklen_t address_len)
396 socklen_t bind_address_len = address_len;
399 if (AF_UNIX == address->sa_family)
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");
434 ret = bind (desc->fd, address, bind_address_len);
436 if (SOCKET_ERROR == ret)
437 SetErrnoFromWinsockError (WSAGetLastError ());
440 return GNUNET_SYSERR;
442 desc->addr = GNUNET_malloc (address_len);
443 memcpy (desc->addr, address, address_len);
444 desc->addrlen = address_len;
454 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
457 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
465 ret = closesocket (desc->fd);
466 error = WSAGetLastError ();
467 SetErrnoFromWinsockError (error);
468 LOG (GNUNET_ERROR_TYPE_DEBUG,
469 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
472 ret = close (desc->fd);
475 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
477 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
479 if (0 != unlink (un->sun_path))
480 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
485 GNUNET_NETWORK_socket_free_memory_only_ (desc);
486 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
491 * Only free memory of a socket, keep the file descriptor untouched.
496 GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc)
498 GNUNET_free_non_null (desc->addr);
504 * Box a native socket (and check that it is a socket).
506 * @param fd socket to box
507 * @return NULL on error (including not supported on target platform)
509 struct GNUNET_NETWORK_Handle *
510 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
512 struct GNUNET_NETWORK_Handle *ret;
516 /* FIXME: Find a better call to check that FD is valid */
517 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
518 return NULL; /* invalid FD */
519 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
524 if (fcntl (fd, F_GETFD) < 0)
525 return NULL; /* invalid FD */
526 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
535 * Connect a socket to some remote address.
538 * @param address peer address
539 * @param address_len length of @a address
540 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
543 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
544 const struct sockaddr *address,
545 socklen_t address_len)
550 if (address->sa_family == AF_UNIX)
552 const struct sockaddr_un *address_un = (const struct sockaddr_un *)address;
553 if(address_un->sun_path[0] == '\0')
555 sizeof (struct sockaddr_un) \
556 - sizeof (address_un->sun_path) \
557 + strnlen (address_un->sun_path + 1, sizeof (address_un->sun_path) - 1) \
561 ret = connect (desc->fd, address, address_len);
564 if (SOCKET_ERROR == ret)
566 SetErrnoFromWinsockError (WSAGetLastError ());
567 if (errno == EWOULDBLOCK)
571 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
579 * @param level protocol level of the option
580 * @param optname identifier of the option
581 * @param optval options
582 * @param optlen length of @a optval
583 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
586 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
587 int level, int optname, void *optval,
592 ret = getsockopt (desc->fd, level, optname, optval, optlen);
595 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
596 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
598 else if (SOCKET_ERROR == ret)
599 SetErrnoFromWinsockError (WSAGetLastError ());
601 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
609 * @param backlog length of the listen queue
610 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
613 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
618 ret = listen (desc->fd, backlog);
621 if (SOCKET_ERROR == ret)
622 SetErrnoFromWinsockError (WSAGetLastError ());
625 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
630 * How much data is available to be read on this descriptor?
633 * @returns #GNUNET_NO if no data is available, or on error!
636 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
641 /* How much is there to be read? */
645 error = ioctl (desc->fd, FIONREAD, &pending);
647 return (ssize_t) pending;
652 error = ioctlsocket (desc->fd, FIONREAD, &pending);
653 if (error != SOCKET_ERROR)
654 return (ssize_t) pending;
661 * Read data from a socket (always non-blocking).
664 * @param buffer buffer
665 * @param length length of @a buffer
666 * @param src_addr either the source to recv from, or all zeroes
667 * to be filled in by recvfrom
668 * @param addrlen length of the @a src_addr
671 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
672 void *buffer, size_t length,
673 struct sockaddr *src_addr, socklen_t *addrlen)
681 flags |= MSG_DONTWAIT;
684 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
686 if (SOCKET_ERROR == ret)
687 SetErrnoFromWinsockError (WSAGetLastError ());
694 * Read data from a connected socket (always non-blocking).
697 * @param buffer buffer
698 * @param length length of @a buffer
701 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
702 void *buffer, size_t length)
710 flags |= MSG_DONTWAIT;
712 ret = recv (desc->fd, buffer, length, flags);
714 if (SOCKET_ERROR == ret)
715 SetErrnoFromWinsockError (WSAGetLastError ());
722 * Send data (always non-blocking).
725 * @param buffer data to send
726 * @param length size of the @a buffer
727 * @return number of bytes sent, #GNUNET_SYSERR on error
730 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
731 const void *buffer, size_t length)
739 flags |= MSG_DONTWAIT;
743 flags |= MSG_NOSIGNAL;
746 ret = send (desc->fd, buffer, length, flags);
749 if (SOCKET_ERROR == ret)
750 SetErrnoFromWinsockError (WSAGetLastError ());
758 * Send data to a particular destination (always non-blocking).
759 * This function only works for UDP sockets.
762 * @param message data to send
763 * @param length size of the data
764 * @param dest_addr destination address
765 * @param dest_len length of @a address
766 * @return number of bytes sent, #GNUNET_SYSERR on error
769 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
770 const void *message, size_t length,
771 const struct sockaddr * dest_addr,
780 flags |= MSG_DONTWAIT;
783 flags |= MSG_NOSIGNAL;
786 if (dest_addr->sa_family == AF_UNIX)
788 const struct sockaddr_un *dest_addr_un = (const struct sockaddr_un *)dest_addr;
789 if (dest_addr_un->sun_path[0] == '\0')
791 sizeof (struct sockaddr) \
792 - sizeof (dest_addr_un->sun_path) \
793 + strnlen (dest_addr_un->sun_path + 1, sizeof (dest_addr_un->sun_path) - 1) \
797 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
799 if (SOCKET_ERROR == ret)
800 SetErrnoFromWinsockError (WSAGetLastError ());
810 * @param level protocol level of the option
811 * @param option_name option identifier
812 * @param option_value value to set
813 * @param option_len size of option_value
814 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
817 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
818 int option_name, const void *option_value,
819 socklen_t option_len)
823 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
825 if (SOCKET_ERROR == ret)
826 SetErrnoFromWinsockError (WSAGetLastError ());
828 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
833 * Create a new socket. Configure it for non-blocking IO and
834 * mark it as non-inheritable to child processes (set the
835 * close-on-exec flag).
837 * @param domain domain of the socket
838 * @param type socket type
839 * @param protocol network protocol
840 * @return new socket, NULL on error
842 struct GNUNET_NETWORK_Handle *
843 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
845 struct GNUNET_NETWORK_Handle *ret;
847 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
848 ret->fd = socket (domain, type, protocol);
855 initialize_network_handle (ret, domain, type))
862 * Shut down socket operations
864 * @param how type of shutdown
865 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
868 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
872 ret = shutdown (desc->fd, how);
875 SetErrnoFromWinsockError (WSAGetLastError ());
877 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
882 * Disable the "CORK" feature for communication with the given socket,
883 * forcing the OS to immediately flush the buffer on transmission
884 * instead of potentially buffering multiple messages. Essentially
885 * reduces the OS send buffers to zero.
888 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
891 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
900 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
902 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
905 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
907 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
913 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
914 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
917 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
918 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
920 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
930 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
935 GNUNET_CONTAINER_slist_clear (fds->handles);
941 * Add a socket to the FD set
944 * @param desc socket to add
947 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
948 const struct GNUNET_NETWORK_Handle *desc)
950 FD_SET (desc->fd, &fds->sds);
951 if (desc->fd + 1 > fds->nsds)
952 fds->nsds = desc->fd + 1;
957 * Check whether a socket is part of the fd set
961 * @return 0 if the FD is not set
964 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
965 const struct GNUNET_NETWORK_Handle *desc)
967 return FD_ISSET (desc->fd, &fds->sds);
972 * Add one fd set to another
974 * @param dst the fd set to add to
975 * @param src the fd set to add from
978 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
979 const struct GNUNET_NETWORK_FDSet *src)
984 for (nfds = src->nsds; nfds > 0; nfds--)
985 if (FD_ISSET (nfds, &src->sds))
988 FD_SET (nfds, &dst->sds);
989 if (nfds + 1 > dst->nsds)
990 dst->nsds = nfds + 1;
993 /* This is MinGW32-specific implementation that relies on the code that
994 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
995 * that fd being added is not already in the set.
996 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
999 for (i = 0; i < src->sds.fd_count; i++)
1000 FD_SET (src->sds.fd_array[i], &dst->sds);
1001 if (src->nsds > dst->nsds)
1002 dst->nsds = src->nsds;
1004 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
1010 * Copy one fd set to another
1012 * @param to destination
1013 * @param from source
1016 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
1017 const struct GNUNET_NETWORK_FDSet *from)
1019 FD_COPY (&from->sds, &to->sds);
1020 to->nsds = from->nsds;
1023 GNUNET_CONTAINER_slist_clear (to->handles);
1024 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
1030 * Return file descriptor for this network handle
1032 * @param desc wrapper to process
1033 * @return POSIX file descriptor
1036 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
1043 * Return sockaddr for this network handle
1045 * @param desc wrapper to process
1049 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1056 * Return sockaddr length for this network handle
1058 * @param desc wrapper to process
1059 * @return socklen_t for sockaddr
1062 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1064 return desc->addrlen;
1069 * Copy a native fd set
1071 * @param to destination
1072 * @param from native source set
1073 * @param nfds the biggest socket number in from + 1
1076 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1077 const fd_set * from, int nfds)
1079 FD_COPY (from, &to->sds);
1085 * Set a native fd in a set
1087 * @param to destination
1088 * @param nfd native FD to set
1091 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1093 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1094 FD_SET (nfd, &to->sds);
1095 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1100 * Test native fd in a set
1102 * @param to set to test, NULL for empty set
1103 * @param nfd native FD to test, or -1 for none
1104 * @return #GNUNET_YES if FD is set in the set
1107 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1110 if ((nfd == -1) || (to == NULL))
1112 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1117 * Add a file handle to the fd set
1119 * @param h the file handle to add
1122 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1123 const struct GNUNET_DISK_FileHandle *h)
1126 GNUNET_CONTAINER_slist_add (fds->handles,
1127 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1128 sizeof (struct GNUNET_DISK_FileHandle));
1133 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1134 FD_SET (fd, &fds->sds);
1135 if (fd + 1 > fds->nsds)
1143 * Check if a file handle is part of an fd set
1145 * @param h file handle
1146 * @return #GNUNET_YES if the file handle is part of the set
1149 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1150 const struct GNUNET_DISK_FileHandle *h)
1154 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1156 GNUNET_DISK_FileHandle));
1158 return FD_ISSET (h->fd, &fds->sds);
1164 * Checks if two fd sets overlap
1165 * @param fds1 first fd set
1166 * @param fds2 second fd set
1167 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1170 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1171 const struct GNUNET_NETWORK_FDSet *fds2)
1177 if (nfds > fds2->nsds)
1182 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1186 struct GNUNET_CONTAINER_SList_Iterator it;
1187 struct GNUNET_DISK_FileHandle *h;
1191 /*This code is somewhat hacky, we are not supposed to know what's
1192 * inside of fd_set; also the O(n^2) is really bad... */
1194 for (i = 0; i < fds1->sds.fd_count; i++)
1196 for (j = 0; j < fds2->sds.fd_count; j++)
1198 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1202 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1203 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1206 struct GNUNET_CONTAINER_SList_Iterator t;
1208 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1211 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1213 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1214 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1215 GNUNET_CONTAINER_slist_next (&t))
1217 struct GNUNET_DISK_FileHandle *fh;
1219 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1221 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1224 if (GNUNET_CONTAINER_slist_contains
1225 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1229 GNUNET_CONTAINER_slist_next (&it);
1239 * @return a new fd set
1241 struct GNUNET_NETWORK_FDSet *
1242 GNUNET_NETWORK_fdset_create ()
1244 struct GNUNET_NETWORK_FDSet *fds;
1246 fds = GNUNET_new (struct GNUNET_NETWORK_FDSet);
1248 fds->handles = GNUNET_CONTAINER_slist_create ();
1250 GNUNET_NETWORK_fdset_zero (fds);
1256 * Releases the associated memory of an fd set
1261 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1264 GNUNET_CONTAINER_slist_destroy (fds->handles);
1270 struct _select_params
1278 SOCKET wakeup_socket;
1283 _selector (LPVOID p)
1285 struct _select_params *sp = p;
1289 WaitForSingleObject (sp->standby, INFINITE);
1290 ResetEvent (sp->standby);
1291 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1292 if (FD_ISSET (sp->wakeup_socket, sp->r))
1294 FD_CLR (sp->wakeup_socket, sp->r);
1297 SetEvent (sp->wakeup);
1305 * Check if sockets or pipes meet certain conditions
1306 * @param rfds set of sockets or pipes to be checked for readability
1307 * @param wfds set of sockets or pipes to be checked for writability
1308 * @param efds set of sockets or pipes to be checked for exceptions
1309 * @param timeout relative value when to return
1310 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1313 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1314 struct GNUNET_NETWORK_FDSet *wfds,
1315 struct GNUNET_NETWORK_FDSet *efds,
1316 const struct GNUNET_TIME_Relative timeout)
1322 int read_handles = 0;
1323 int write_handles = 0;
1327 uint64_t mcs_total = 0;
1328 DWORD ms_rounded = 0;
1332 static HANDLE hEventPipeWrite = 0;
1333 static HANDLE hEventReadReady = 0;
1335 static struct _select_params sp;
1336 static HANDLE select_thread = NULL;
1337 static HANDLE select_finished_event = NULL;
1338 static HANDLE select_standby_event = NULL;
1339 static SOCKET select_wakeup_socket = -1;
1340 static SOCKET select_send_socket = -1;
1341 static struct timeval select_timeout;
1344 int writePipePos = 0;
1346 HANDLE handle_array[FD_SETSIZE + 2];
1347 int returncode = -1;
1348 int returnedpos = 0;
1350 struct GNUNET_CONTAINER_SList *handles_read;
1351 struct GNUNET_CONTAINER_SList *handles_write;
1352 struct GNUNET_CONTAINER_SList *handles_except;
1366 /* TODO: Make this growable */
1367 struct GNUNET_DISK_FileHandle *readArray[50];
1375 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1378 struct GNUNET_CONTAINER_SList_Iterator t;
1380 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1381 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1382 GNUNET_CONTAINER_slist_next (&t))
1384 struct GNUNET_DISK_FileHandle *fh;
1386 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1388 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1397 nfds = GNUNET_MAX (nfds, wfds->nsds);
1399 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1404 nfds = GNUNET_MAX (nfds, efds->nsds);
1406 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1411 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1418 LOG (GNUNET_ERROR_TYPE_ERROR,
1420 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1424 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1426 (timeout.rel_value_us -
1427 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1428 return select (nfds,
1429 (NULL != rfds) ? &rfds->sds : NULL,
1430 (NULL != wfds) ? &wfds->sds : NULL,
1431 (NULL != efds) ? &efds->sds : NULL,
1432 (timeout.rel_value_us ==
1433 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1436 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1437 /* calculate how long we need to wait in microseconds */
1438 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1440 mcs_total = INFINITE;
1441 ms_rounded = INFINITE;
1445 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1446 ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1447 if (mcs_total > 0 && ms_rounded == 0)
1450 /* select() may be used as a portable way to sleep */
1451 if (!(rfds || wfds || efds))
1457 if (NULL == select_thread)
1459 SOCKET select_listening_socket = -1;
1460 struct sockaddr_in s_in;
1465 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1466 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1468 select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1470 select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1473 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1474 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1476 alen = sizeof (s_in);
1477 s_in.sin_family = AF_INET;
1479 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1480 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1481 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1482 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1483 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1484 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1486 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1487 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1489 res = listen (select_listening_socket, SOMAXCONN);
1490 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1492 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1493 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1495 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1497 closesocket (select_listening_socket);
1499 sp.wakeup = select_finished_event;
1500 sp.standby = select_standby_event;
1501 sp.wakeup_socket = select_wakeup_socket;
1503 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1507 handles_read = GNUNET_CONTAINER_slist_create ();
1508 handles_write = GNUNET_CONTAINER_slist_create ();
1509 handles_except = GNUNET_CONTAINER_slist_create ();
1520 FD_COPY (&rfds->sds, &aread);
1522 FD_COPY (&rfds->sds, &bread);
1527 FD_COPY (&wfds->sds, &awrite);
1529 FD_COPY (&wfds->sds, &bwrite);
1534 FD_COPY (&efds->sds, &aexcept);
1536 FD_COPY (&efds->sds, &bexcept);
1540 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1541 By profiling we detected that to be true in 90% of the cases.
1544 /* Do the select now */
1545 select_timeout.tv_sec = 0;
1546 select_timeout.tv_usec = 0;
1548 /* Copy all the writes to the except, so we can detect connect() errors */
1549 for (i = 0; i < awrite.fd_count; i++)
1550 FD_SET (awrite.fd_array[i], &aexcept);
1551 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1552 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1553 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1556 if (selectret == -1)
1558 /* Throw an error early on, while we still have the context. */
1559 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1560 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1564 /* Check aexcept, add its contents to awrite
1565 This is technically wrong (aexcept might have its own descriptors), we should
1566 have checked that descriptors were in awrite originally before re-adding them from
1567 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1568 for (i = 0; i < aexcept.fd_count; i++)
1569 FD_SET (aexcept.fd_array[i], &awrite);
1571 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1572 /* Sadly, it means code duplication :( */
1573 if ((selectret > 0) || (mcs_total == 0))
1576 if (rfds && read_handles)
1578 struct GNUNET_CONTAINER_SList_Iterator i;
1581 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1582 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1583 GNUNET_CONTAINER_slist_next (&i), c++)
1585 struct GNUNET_DISK_FileHandle *fh;
1587 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1588 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1594 DWORD waitstatus = 0;
1595 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1596 error = GetLastError ();
1597 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1598 c, fh->h, bret, waitstatus, error);
1601 /* TODO: either add more errors to this condition, or eliminate it
1602 * entirely (failed to peek -> pipe is in serious trouble, should
1603 * be selected as readable).
1605 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1608 else if (waitstatus <= 0)
1610 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1611 fh, sizeof (struct GNUNET_DISK_FileHandle));
1613 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1618 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1619 fh, sizeof (struct GNUNET_DISK_FileHandle));
1624 if (wfds && write_handles)
1626 LOG (GNUNET_ERROR_TYPE_DEBUG,
1627 "Adding the write ready event to the array as %d\n", nhandles);
1628 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1629 retcode += write_handles;
1631 if (efds && ex_handles)
1633 struct GNUNET_CONTAINER_SList_Iterator i;
1635 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1636 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1637 GNUNET_CONTAINER_slist_next (&i))
1639 struct GNUNET_DISK_FileHandle *fh;
1642 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1643 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1645 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1647 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1648 fh, sizeof (struct GNUNET_DISK_FileHandle));
1654 /* Add our select() result.*/
1656 retcode += selectret;
1660 GNUNET_NETWORK_fdset_zero (rfds);
1661 if (selectret != -1)
1662 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1663 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1667 GNUNET_NETWORK_fdset_zero (wfds);
1668 if (selectret != -1)
1669 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1670 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1674 GNUNET_NETWORK_fdset_zero (efds);
1675 if (selectret != -1)
1676 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1677 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1679 GNUNET_CONTAINER_slist_destroy (handles_read);
1680 GNUNET_CONTAINER_slist_destroy (handles_write);
1681 GNUNET_CONTAINER_slist_destroy (handles_except);
1683 if (selectret == -1)
1688 /* If we got this far, use slower implementation that is able to do a waiting select
1689 on both sockets and pipes simultaneously */
1691 /* Events for pipes */
1692 if (!hEventReadReady)
1693 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1694 if (!hEventPipeWrite)
1695 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1711 FD_COPY (&rfds->sds, &aread);
1713 FD_COPY (&rfds->sds, &bread);
1718 FD_COPY (&wfds->sds, &awrite);
1720 FD_COPY (&wfds->sds, &bwrite);
1725 FD_COPY (&efds->sds, &aexcept);
1727 FD_COPY (&efds->sds, &bexcept);
1730 /* We will first Add the PIPES to the events */
1732 if (rfds && read_handles)
1734 struct GNUNET_CONTAINER_SList_Iterator i;
1736 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1737 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1738 GNUNET_CONTAINER_slist_next (&i))
1740 struct GNUNET_DISK_FileHandle *fh;
1742 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1744 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1746 /* Read zero bytes to check the status of the pipe */
1747 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1749 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1751 DWORD error_code = GetLastError ();
1753 if (error_code == ERROR_IO_PENDING)
1755 LOG (GNUNET_ERROR_TYPE_DEBUG,
1756 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1758 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1759 readArray[readPipes++] = fh;
1763 LOG (GNUNET_ERROR_TYPE_DEBUG,
1764 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1765 handle_array[nhandles++] = hEventReadReady;
1766 readArray[readPipes++] = fh;
1771 LOG (GNUNET_ERROR_TYPE_DEBUG,
1772 "Adding the read ready event to the array as %d\n", nhandles);
1773 handle_array[nhandles++] = hEventReadReady;
1774 readArray[readPipes++] = fh;
1779 GNUNET_CONTAINER_slist_add (handles_read,
1780 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1781 fh, sizeof (struct GNUNET_DISK_FileHandle));
1785 if (wfds && write_handles)
1787 LOG (GNUNET_ERROR_TYPE_DEBUG,
1788 "Adding the write ready event to the array as %d\n", nhandles);
1789 handle_array[nhandles++] = hEventPipeWrite;
1790 writePipePos = nhandles;
1792 if (efds && ex_handles)
1794 struct GNUNET_CONTAINER_SList_Iterator i;
1796 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1797 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1798 GNUNET_CONTAINER_slist_next (&i))
1800 struct GNUNET_DISK_FileHandle *fh;
1803 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1805 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1807 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1809 GNUNET_CONTAINER_slist_add (handles_except,
1810 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1812 sizeof (struct GNUNET_DISK_FileHandle));
1822 LOG (GNUNET_ERROR_TYPE_DEBUG,
1823 "Adding the socket event to the array as %d\n",
1825 handle_array[nhandles++] = select_finished_event;
1826 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1830 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1831 select_timeout.tv_usec =(timeout.rel_value_us -
1832 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1833 sp.tv = &select_timeout;
1835 FD_SET (select_wakeup_socket, &aread);
1838 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1843 /* Failed connections cause sockets to be set in errorfds on W32,
1844 * but on POSIX it should set them in writefds.
1845 * First copy all awrite sockets to aexcept, later we'll
1846 * check aexcept and set its contents in awrite as well
1847 * Sockets are also set in errorfds when OOB data is available,
1848 * but we don't use OOB data.
1850 for (i = 0; i < awrite.fd_count; i++)
1851 FD_SET (awrite.fd_array[i], &aexcept);
1852 ResetEvent (select_finished_event);
1853 SetEvent (select_standby_event);
1856 handle_array[nhandles] = NULL;
1857 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
1858 nfds, nhandles, mcs_total);
1862 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
1863 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode);
1867 GNUNET_break (0); /* This branch shouldn't actually be executed...*/
1868 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1869 returncode = WAIT_TIMEOUT;
1873 /* Shouldn't come this far. If it does - investigate. */
1879 /* Don't wake up select-thread when delay is 0, it should return immediately
1880 * and wake up by itself.
1883 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1884 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1885 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1890 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1893 /* Check aexcept, add its contents to awrite */
1894 for (i = 0; i < aexcept.fd_count; i++)
1895 FD_SET (aexcept.fd_array[i], &awrite);
1898 returnedpos = returncode - WAIT_OBJECT_0;
1899 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1901 if (nhandles && (returnedpos < nhandles))
1906 retcode += sp.status;
1908 if ((writePipePos != -1) && (returnedpos < writePipePos))
1910 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1911 retcode += write_handles;
1912 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1914 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1915 /* We have some pipes ready for read. */
1916 if (returnedpos < readPipes)
1918 for (i = 0; i < readPipes; i++)
1926 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1927 error = GetLastError ();
1928 LOG (GNUNET_ERROR_TYPE_DEBUG,
1929 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1930 i, readArray[i]->h, bret, waitstatus, error);
1933 /* TODO: either add more errors to this condition, or eliminate it
1934 * entirely (failed to peek -> pipe is in serious trouble, should
1935 * be selected as readable).
1937 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1940 else if (waitstatus <= 0)
1942 GNUNET_CONTAINER_slist_add (handles_read,
1943 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1945 sizeof (struct GNUNET_DISK_FileHandle));
1947 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1948 readArray[i], readArray[i]->h);
1952 if (!nhandles || (returnedpos >= nhandles))
1953 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1956 struct GNUNET_CONTAINER_SList_Iterator t;
1958 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1959 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1960 GNUNET_CONTAINER_slist_next (&t))
1962 struct GNUNET_DISK_FileHandle *fh;
1964 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1966 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1971 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1972 GNUNET_NETWORK_fdset_zero (rfds);
1973 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1974 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1975 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1979 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1980 GNUNET_NETWORK_fdset_zero (wfds);
1981 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1982 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1983 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1987 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1988 GNUNET_NETWORK_fdset_zero (efds);
1989 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1990 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1991 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1993 GNUNET_CONTAINER_slist_destroy (handles_read);
1994 GNUNET_CONTAINER_slist_destroy (handles_write);
1995 GNUNET_CONTAINER_slist_destroy (handles_except);
1999 struct GNUNET_CONTAINER_SList_Iterator t;
2001 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
2002 for (i = 0; i < rfds->sds.fd_count; i++)
2004 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
2006 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
2007 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
2008 GNUNET_CONTAINER_slist_next (&t))
2010 struct GNUNET_DISK_FileHandle *fh;
2012 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
2014 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
2019 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
2020 for (i = 0; i < wfds->sds.fd_count; i++)
2022 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
2027 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
2028 for (i = 0; i < efds->sds.fd_count; i++)
2030 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
2033 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
2035 if (nhandles && (returnedpos < nhandles))
2042 /* end of network.c */