2 This file is part of GNUnet.
3 (C) 2009, 2012 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 2, 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.
57 * Number of bytes in addr.
62 * Address we were bound to, or NULL.
64 struct sockaddr *addr;
70 * Test if the given protocol family is supported by this system.
72 * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
73 * @return GNUNET_OK if the PF is supported
76 GNUNET_NETWORK_test_pf (int pf)
80 s = socket (pf, SOCK_STREAM, 0);
83 if (EAFNOSUPPORT == errno)
85 fprintf (stderr, "Failed to create test socket: %s\n", STRERROR (errno));
98 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
99 * shorten it to an acceptable length while keeping it unique
100 * and making sure it remains a valid filename (if possible).
102 * @param unixpath long path, will be freed (or same pointer returned
103 * with moved 0-termination).
104 * @return shortened unixpath, NULL on error
107 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
109 struct sockaddr_un dummy;
112 struct GNUNET_CRYPTO_ShortHashCode sh;
113 struct GNUNET_CRYPTO_ShortHashAsciiEncoded ae;
116 upm = sizeof (dummy.sun_path);
117 slen = strlen (unixpath);
119 return unixpath; /* no shortening required */
120 GNUNET_CRYPTO_short_hash (unixpath, slen, &sh);
121 while (sizeof (struct GNUNET_CRYPTO_ShortHashAsciiEncoded) +
122 strlen (unixpath) >= upm)
124 if (NULL == (end = strrchr (unixpath, '/')))
126 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
127 _("Unable to shorten unix path `%s' while keeping name unique\n"),
129 GNUNET_free (unixpath);
134 GNUNET_CRYPTO_short_hash_to_enc (&sh, &ae);
135 strcat (unixpath, (char*) ae.short_encoding);
141 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
146 * Set if a socket should use blocking or non-blocking IO.
149 * @param doBlock blocking mode
150 * @return GNUNET_OK on success, GNUNET_SYSERR on error
153 GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
160 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
163 SetErrnoFromWinsockError (WSAGetLastError ());
164 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
165 return GNUNET_SYSERR;
171 int flags = fcntl (fd->fd, F_GETFL);
176 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
177 return GNUNET_SYSERR;
180 flags &= ~O_NONBLOCK;
184 if (0 != fcntl (fd->fd, F_SETFL, flags))
187 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
188 return GNUNET_SYSERR;
196 * Make a socket non-inheritable to child processes
198 * @param h the socket to make non-inheritable
199 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
200 * @warning Not implemented on Windows
203 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
207 i = fcntl (h->fd, F_GETFD);
209 return GNUNET_SYSERR;
210 if (i == (i | FD_CLOEXEC))
213 if (fcntl (h->fd, F_SETFD, i) < 0)
214 return GNUNET_SYSERR;
218 b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
221 SetErrnoFromWinsockError (WSAGetLastError ());
222 return GNUNET_SYSERR;
231 * The MSG_NOSIGNAL equivalent on Mac OS X
233 * @param h the socket to make non-delaying
236 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
241 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, &abs_value,
243 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
249 * Disable delays when sending data via the socket.
250 * (GNUnet makes sure that messages are as big as
253 * @param h the socket to make non-delaying
256 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
261 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
262 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
264 const char *abs_value = "1";
267 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, abs_value,
269 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
275 * Perform proper canonical initialization for a network handle.
276 * Set it to non-blocking, make it non-inheritable to child
277 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
278 * stream socket) and check that it is smaller than FS_SETSIZE.
280 * @param h socket to initialize
281 * @param af address family of the socket
282 * @param type socket type
283 * @return GNUNET_OK on success, GNUNET_SYSERR if initialization
284 * failed and the handle was destroyed
287 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
291 if (h->fd == INVALID_SOCKET)
294 SetErrnoFromWinsockError (WSAGetLastError ());
297 return GNUNET_SYSERR;
300 if (h->fd >= FD_SETSIZE)
302 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
304 return GNUNET_SYSERR;
307 if (GNUNET_OK != socket_set_inheritable (h))
308 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
309 "socket_set_inheritable");
311 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
314 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
315 return GNUNET_SYSERR;
318 socket_set_nosigpipe (h);
320 if ( (type == SOCK_STREAM)
325 socket_set_nodelay (h);
331 * accept a new connection on a socket
333 * @param desc bound socket
334 * @param address address of the connecting peer, may be NULL
335 * @param address_len length of address
336 * @return client socket
338 struct GNUNET_NETWORK_Handle *
339 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
340 struct sockaddr *address, socklen_t * address_len)
342 struct GNUNET_NETWORK_Handle *ret;
344 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
347 struct sockaddr name;
348 socklen_t namelen = sizeof (name);
349 int gsn = getsockname (desc->fd, &name, &namelen);
352 LOG (GNUNET_ERROR_TYPE_DEBUG, "Accepting connection on `%s'\n",
353 GNUNET_a2s (&name, namelen));
356 ret->fd = accept (desc->fd, address, address_len);
357 if (GNUNET_OK != initialize_network_handle (ret,
358 (NULL != address) ? address->sa_family : desc->af,
366 * Bind to a connected socket
368 * @param desc socket to bind
369 * @param address address to be bound
370 * @param address_len length of address
371 * @param flags flags affecting bind behaviour
372 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
375 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
376 const struct sockaddr *address,
377 socklen_t address_len,
387 if (desc->af == AF_INET6)
388 if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
389 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
397 /* This is required, and required here, but only on UNIX */
398 if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
399 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
404 if (address->sa_family == AF_UNIX && (flags & GNUNET_BIND_EXCLUSIVE) == 0)
406 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
408 (void) unlink (un->sun_path);
412 ret = bind (desc->fd, address, address_len);
414 if (SOCKET_ERROR == ret)
415 SetErrnoFromWinsockError (WSAGetLastError ());
418 return GNUNET_SYSERR;
421 desc->addr = GNUNET_malloc (address_len);
422 memcpy (desc->addr, address, address_len);
423 desc->addrlen = address_len;
433 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
436 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
444 ret = closesocket (desc->fd);
445 error = WSAGetLastError ();
446 SetErrnoFromWinsockError (error);
447 LOG (GNUNET_ERROR_TYPE_DEBUG,
448 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
451 ret = close (desc->fd);
455 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
457 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
459 if (0 != unlink (un->sun_path))
460 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
464 GNUNET_free_non_null (desc->addr);
466 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
471 * Box a native socket (and check that it is a socket).
473 * @param fd socket to box
474 * @return NULL on error (including not supported on target platform)
476 struct GNUNET_NETWORK_Handle *
477 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
479 struct GNUNET_NETWORK_Handle *ret;
483 /* FIXME: Find a better call to check that FD is valid */
484 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
485 return NULL; /* invalid FD */
486 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
491 if (fcntl (fd, F_GETFD) < 0)
492 return NULL; /* invalid FD */
493 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
504 * @param address peer address
505 * @param address_len length of address
506 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
509 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
510 const struct sockaddr *address,
511 socklen_t address_len)
515 ret = connect (desc->fd, address, address_len);
518 if (SOCKET_ERROR == ret)
520 SetErrnoFromWinsockError (WSAGetLastError ());
521 if (errno == EWOULDBLOCK)
525 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
533 * @param level protocol level of the option
534 * @param optname identifier of the option
535 * @param optval options
536 * @param optlen length of optval
537 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
540 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
541 int level, int optname, void *optval,
546 ret = getsockopt (desc->fd, level, optname, optval, optlen);
549 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
550 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
552 else if (SOCKET_ERROR == ret)
553 SetErrnoFromWinsockError (WSAGetLastError ());
555 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
562 * @param backlog length of the listen queue
563 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
566 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
571 ret = listen (desc->fd, backlog);
574 if (SOCKET_ERROR == ret)
575 SetErrnoFromWinsockError (WSAGetLastError ());
578 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
583 * How much data is available to be read on this descriptor?
585 * Returns GNUNET_NO if no data is available, or on error!
589 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
594 /* How much is there to be read? */
598 error = ioctl (desc->fd, FIONREAD, &pending);
600 return (ssize_t) pending;
605 error = ioctlsocket (desc->fd, FIONREAD, &pending);
606 if (error != SOCKET_ERROR)
607 return (ssize_t) pending;
614 * Read data from a connected socket (always non-blocking).
616 * @param buffer buffer
617 * @param length length of buffer
618 * @param src_addr either the source to recv from, or all zeroes
619 * to be filled in by recvfrom
620 * @param addrlen length of the addr
623 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
624 void *buffer, size_t length,
625 struct sockaddr * src_addr, socklen_t * addrlen)
633 flags |= MSG_DONTWAIT;
636 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
638 if (SOCKET_ERROR == ret)
639 SetErrnoFromWinsockError (WSAGetLastError ());
646 * Read data from a connected socket (always non-blocking).
648 * @param buffer buffer
649 * @param length length of buffer
652 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
653 void *buffer, size_t length)
661 flags |= MSG_DONTWAIT;
663 ret = recv (desc->fd, buffer, length, flags);
665 if (SOCKET_ERROR == ret)
666 SetErrnoFromWinsockError (WSAGetLastError ());
673 * Send data (always non-blocking).
676 * @param buffer data to send
677 * @param length size of the buffer
678 * @return number of bytes sent, GNUNET_SYSERR on error
681 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
682 const void *buffer, size_t length)
690 flags |= MSG_DONTWAIT;
694 flags |= MSG_NOSIGNAL;
697 ret = send (desc->fd, buffer, length, flags);
700 if (SOCKET_ERROR == ret)
701 SetErrnoFromWinsockError (WSAGetLastError ());
709 * Send data to a particular destination (always non-blocking).
710 * This function only works for UDP sockets.
713 * @param message data to send
714 * @param length size of the data
715 * @param dest_addr destination address
716 * @param dest_len length of address
717 * @return number of bytes sent, GNUNET_SYSERR on error
720 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
721 const void *message, size_t length,
722 const struct sockaddr * dest_addr,
731 flags |= MSG_DONTWAIT;
734 flags |= MSG_NOSIGNAL;
736 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
738 if (SOCKET_ERROR == ret)
739 SetErrnoFromWinsockError (WSAGetLastError ());
748 * @param level protocol level of the option
749 * @param option_name option identifier
750 * @param option_value value to set
751 * @param option_len size of option_value
752 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
755 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
756 int option_name, const void *option_value,
757 socklen_t option_len)
761 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
763 if (SOCKET_ERROR == ret)
764 SetErrnoFromWinsockError (WSAGetLastError ());
766 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
771 * Create a new socket. Configure it for non-blocking IO and
772 * mark it as non-inheritable to child processes (set the
773 * close-on-exec flag).
775 * @param domain domain of the socket
776 * @param type socket type
777 * @param protocol network protocol
778 * @return new socket, NULL on error
780 struct GNUNET_NETWORK_Handle *
781 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
783 struct GNUNET_NETWORK_Handle *ret;
785 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
786 ret->fd = socket (domain, type, protocol);
788 initialize_network_handle (ret, domain, type))
795 * Shut down socket operations
797 * @param how type of shutdown
798 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
801 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
805 ret = shutdown (desc->fd, how);
808 SetErrnoFromWinsockError (WSAGetLastError ());
810 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
815 * Disable the "CORK" feature for communication with the given socket,
816 * forcing the OS to immediately flush the buffer on transmission
817 * instead of potentially buffering multiple messages. Essentially
818 * reduces the OS send buffers to zero.
821 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
824 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
833 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
835 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
838 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
840 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
846 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
847 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
850 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
851 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
853 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
862 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
867 GNUNET_CONTAINER_slist_clear (fds->handles);
872 * Add a socket to the FD set
874 * @param desc socket to add
877 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
878 const struct GNUNET_NETWORK_Handle *desc)
880 FD_SET (desc->fd, &fds->sds);
881 if (desc->fd + 1 > fds->nsds)
882 fds->nsds = desc->fd + 1;
887 * Check whether a socket is part of the fd set
890 * @return 0 if the FD is not set
893 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
894 const struct GNUNET_NETWORK_Handle *desc)
896 return FD_ISSET (desc->fd, &fds->sds);
901 * Add one fd set to another
902 * @param dst the fd set to add to
903 * @param src the fd set to add from
906 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
907 const struct GNUNET_NETWORK_FDSet *src)
912 for (nfds = src->nsds; nfds > 0; nfds--)
913 if (FD_ISSET (nfds, &src->sds))
916 FD_SET (nfds, &dst->sds);
917 if (nfds + 1 > dst->nsds)
918 dst->nsds = nfds + 1;
921 /* This is MinGW32-specific implementation that relies on the code that
922 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
923 * that fd being added is not already in the set.
924 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
927 for (i = 0; i < src->sds.fd_count; i++)
928 FD_SET (src->sds.fd_array[i], &dst->sds);
929 if (src->nsds > dst->nsds)
930 dst->nsds = src->nsds;
932 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
938 * Copy one fd set to another
940 * @param to destination
944 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
945 const struct GNUNET_NETWORK_FDSet *from)
947 FD_COPY (&from->sds, &to->sds);
948 to->nsds = from->nsds;
951 GNUNET_CONTAINER_slist_clear (to->handles);
952 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
958 * Return file descriptor for this network handle
960 * @param desc wrapper to process
961 * @return POSIX file descriptor
964 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
970 * Return sockaddr for this network handle
972 * @param desc wrapper to process
976 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
982 * Return sockaddr length for this network handle
984 * @param desc wrapper to process
985 * @return socklen_t for sockaddr
988 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
990 return desc->addrlen;
993 * Copy a native fd set
995 * @param to destination
996 * @param from native source set
997 * @param nfds the biggest socket number in from + 1
1000 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1001 const fd_set * from, int nfds)
1003 FD_COPY (from, &to->sds);
1009 * Set a native fd in a set
1011 * @param to destination
1012 * @param nfd native FD to set
1015 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1017 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1018 FD_SET (nfd, &to->sds);
1019 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1024 * Test native fd in a set
1026 * @param to set to test, NULL for empty set
1027 * @param nfd native FD to test, or -1 for none
1028 * @return GNUNET_YES if FD is set in the set
1031 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1034 if ((nfd == -1) || (to == NULL))
1036 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1041 * Add a file handle to the fd set
1043 * @param h the file handle to add
1046 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1047 const struct GNUNET_DISK_FileHandle *h)
1050 GNUNET_CONTAINER_slist_add (fds->handles,
1051 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1052 sizeof (struct GNUNET_DISK_FileHandle));
1057 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1058 FD_SET (fd, &fds->sds);
1059 if (fd + 1 > fds->nsds)
1067 * Check if a file handle is part of an fd set
1069 * @param h file handle
1070 * @return GNUNET_YES if the file handle is part of the set
1073 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1074 const struct GNUNET_DISK_FileHandle *h)
1078 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1080 GNUNET_DISK_FileHandle));
1082 return FD_ISSET (h->fd, &fds->sds);
1088 * Checks if two fd sets overlap
1089 * @param fds1 first fd set
1090 * @param fds2 second fd set
1091 * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
1094 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1095 const struct GNUNET_NETWORK_FDSet *fds2)
1101 if (nfds > fds2->nsds)
1106 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1110 struct GNUNET_CONTAINER_SList_Iterator it;
1111 struct GNUNET_DISK_FileHandle *h;
1115 /*This code is somewhat hacky, we are not supposed to know what's
1116 * inside of fd_set; also the O(n^2) is really bad... */
1118 for (i = 0; i < fds1->sds.fd_count; i++)
1120 for (j = 0; j < fds2->sds.fd_count; j++)
1122 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1126 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1127 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1130 struct GNUNET_CONTAINER_SList_Iterator t;
1132 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1135 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1137 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1138 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1139 GNUNET_CONTAINER_slist_next (&t))
1141 struct GNUNET_DISK_FileHandle *fh;
1143 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1145 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1148 if (GNUNET_CONTAINER_slist_contains
1149 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1153 GNUNET_CONTAINER_slist_next (&it);
1162 * @return a new fd set
1164 struct GNUNET_NETWORK_FDSet *
1165 GNUNET_NETWORK_fdset_create ()
1167 struct GNUNET_NETWORK_FDSet *fds;
1169 fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1171 fds->handles = GNUNET_CONTAINER_slist_create ();
1173 GNUNET_NETWORK_fdset_zero (fds);
1179 * Releases the associated memory of an fd set
1183 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1186 GNUNET_CONTAINER_slist_destroy (fds->handles);
1192 struct _select_params
1200 SOCKET wakeup_socket;
1205 _selector (LPVOID p)
1207 struct _select_params *sp = p;
1211 WaitForSingleObject (sp->standby, INFINITE);
1212 ResetEvent (sp->standby);
1213 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1214 if (FD_ISSET (sp->wakeup_socket, sp->r))
1216 FD_CLR (sp->wakeup_socket, sp->r);
1219 SetEvent (sp->wakeup);
1226 * Check if sockets or pipes meet certain conditions
1227 * @param rfds set of sockets or pipes to be checked for readability
1228 * @param wfds set of sockets or pipes to be checked for writability
1229 * @param efds set of sockets or pipes to be checked for exceptions
1230 * @param timeout relative value when to return
1231 * @return number of selected sockets or pipes, GNUNET_SYSERR on error
1234 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1235 struct GNUNET_NETWORK_FDSet *wfds,
1236 struct GNUNET_NETWORK_FDSet *efds,
1237 const struct GNUNET_TIME_Relative timeout)
1243 int read_handles = 0;
1244 int write_handles = 0;
1252 static HANDLE hEventPipeWrite = 0;
1253 static HANDLE hEventReadReady = 0;
1255 static struct _select_params sp;
1256 static HANDLE select_thread = NULL;
1257 static HANDLE select_finished_event = NULL;
1258 static HANDLE select_standby_event = NULL;
1259 static SOCKET select_wakeup_socket = -1;
1260 static SOCKET select_send_socket = -1;
1261 static struct timeval select_timeout;
1264 int writePipePos = 0;
1266 HANDLE handle_array[FD_SETSIZE + 2];
1267 int returncode = -1;
1268 int returnedpos = 0;
1270 struct GNUNET_CONTAINER_SList *handles_read;
1271 struct GNUNET_CONTAINER_SList *handles_write;
1272 struct GNUNET_CONTAINER_SList *handles_except;
1286 /* TODO: Make this growable */
1287 struct GNUNET_DISK_FileHandle *readArray[50];
1295 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1298 struct GNUNET_CONTAINER_SList_Iterator t;
1300 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1301 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1302 GNUNET_CONTAINER_slist_next (&t))
1304 struct GNUNET_DISK_FileHandle *fh;
1306 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1308 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1317 nfds = GNUNET_MAX (nfds, wfds->nsds);
1319 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1324 nfds = GNUNET_MAX (nfds, efds->nsds);
1326 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1331 (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1338 LOG (GNUNET_ERROR_TYPE_ERROR,
1340 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1344 tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1346 1000 * (timeout.rel_value -
1347 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1348 return select (nfds, (rfds != NULL) ? &rfds->sds : NULL,
1349 (wfds != NULL) ? &wfds->sds : NULL,
1350 (efds != NULL) ? &efds->sds : NULL,
1351 (timeout.rel_value ==
1352 GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ? NULL : &tv);
1355 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1356 /* calculate how long we need to wait in milliseconds */
1357 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1358 ms_total = INFINITE;
1361 ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1362 if (timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value > 0xFFFFFFFFLL - 1)
1365 ms_total = 0xFFFFFFFF - 1;
1368 /* select() may be used as a portable way to sleep */
1369 if (!(rfds || wfds || efds))
1375 if (select_thread == NULL)
1377 SOCKET select_listening_socket = -1;
1378 struct sockaddr_in s_in;
1383 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1384 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1386 select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1388 select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1391 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1392 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1394 alen = sizeof (s_in);
1395 s_in.sin_family = AF_INET;
1397 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1398 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1399 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1400 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1401 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1402 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1404 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1405 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1407 res = listen (select_listening_socket, SOMAXCONN);
1408 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1410 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1411 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1413 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1415 closesocket (select_listening_socket);
1417 sp.wakeup = select_finished_event;
1418 sp.standby = select_standby_event;
1419 sp.wakeup_socket = select_wakeup_socket;
1421 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1425 handles_read = GNUNET_CONTAINER_slist_create ();
1426 handles_write = GNUNET_CONTAINER_slist_create ();
1427 handles_except = GNUNET_CONTAINER_slist_create ();
1438 FD_COPY (&rfds->sds, &aread);
1440 FD_COPY (&rfds->sds, &bread);
1445 FD_COPY (&wfds->sds, &awrite);
1447 FD_COPY (&wfds->sds, &bwrite);
1452 FD_COPY (&efds->sds, &aexcept);
1454 FD_COPY (&efds->sds, &bexcept);
1458 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1459 By profiling we detected that to be true in 90% of the cases.
1462 /* Do the select now */
1463 select_timeout.tv_sec = 0;
1464 select_timeout.tv_usec = 0;
1466 /* Copy all the writes to the except, so we can detect connect() errors */
1467 for (i = 0; i < awrite.fd_count; i++)
1468 FD_SET (awrite.fd_array[i], &aexcept);
1469 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1470 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1471 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1474 if (selectret == -1)
1476 /* Throw an error early on, while we still have the context. */
1477 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1478 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1482 /* Check aexcept, add its contents to awrite
1483 This is technically wrong (aexcept might have its own descriptors), we should
1484 have checked that descriptors were in awrite originally before re-adding them from
1485 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1486 for (i = 0; i < aexcept.fd_count; i++)
1487 FD_SET (aexcept.fd_array[i], &awrite);
1489 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1490 /* Sadly, it means code duplication :( */
1491 if ((selectret > 0) || (ms_total == 0))
1494 if (rfds && read_handles)
1496 struct GNUNET_CONTAINER_SList_Iterator i;
1499 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1500 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1501 GNUNET_CONTAINER_slist_next (&i), c++)
1503 struct GNUNET_DISK_FileHandle *fh;
1505 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1506 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1512 DWORD waitstatus = 0;
1513 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1514 error = GetLastError ();
1515 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1516 c, fh->h, bret, waitstatus, error);
1519 /* TODO: either add more errors to this condition, or eliminate it
1520 * entirely (failed to peek -> pipe is in serious trouble, should
1521 * be selected as readable).
1523 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1526 else if (waitstatus <= 0)
1528 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1529 fh, sizeof (struct GNUNET_DISK_FileHandle));
1531 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1536 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1537 fh, sizeof (struct GNUNET_DISK_FileHandle));
1542 if (wfds && write_handles)
1544 LOG (GNUNET_ERROR_TYPE_DEBUG,
1545 "Adding the write ready event to the array as %d\n", nhandles);
1546 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1547 retcode += write_handles;
1549 if (efds && ex_handles)
1551 struct GNUNET_CONTAINER_SList_Iterator i;
1553 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1554 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1555 GNUNET_CONTAINER_slist_next (&i))
1557 struct GNUNET_DISK_FileHandle *fh;
1560 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1561 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1563 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1565 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1566 fh, sizeof (struct GNUNET_DISK_FileHandle));
1572 /* Add our select() result.*/
1574 retcode += selectret;
1578 GNUNET_NETWORK_fdset_zero (rfds);
1579 if (selectret != -1)
1580 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1581 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1585 GNUNET_NETWORK_fdset_zero (wfds);
1586 if (selectret != -1)
1587 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1588 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1592 GNUNET_NETWORK_fdset_zero (efds);
1593 if (selectret != -1)
1594 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1595 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1597 GNUNET_CONTAINER_slist_destroy (handles_read);
1598 GNUNET_CONTAINER_slist_destroy (handles_write);
1599 GNUNET_CONTAINER_slist_destroy (handles_except);
1601 if (selectret == -1)
1606 /* If we got this far, use slower implementation that is able to do a waiting select
1607 on both sockets and pipes simultaneously */
1609 /* Events for pipes */
1610 if (!hEventReadReady)
1611 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1612 if (!hEventPipeWrite)
1613 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1629 FD_COPY (&rfds->sds, &aread);
1631 FD_COPY (&rfds->sds, &bread);
1636 FD_COPY (&wfds->sds, &awrite);
1638 FD_COPY (&wfds->sds, &bwrite);
1643 FD_COPY (&efds->sds, &aexcept);
1645 FD_COPY (&efds->sds, &bexcept);
1648 /* We will first Add the PIPES to the events */
1650 if (rfds && read_handles)
1652 struct GNUNET_CONTAINER_SList_Iterator i;
1654 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1655 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1656 GNUNET_CONTAINER_slist_next (&i))
1658 struct GNUNET_DISK_FileHandle *fh;
1660 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1662 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1664 /* Read zero bytes to check the status of the pipe */
1665 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1667 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1669 DWORD error_code = GetLastError ();
1671 if (error_code == ERROR_IO_PENDING)
1673 LOG (GNUNET_ERROR_TYPE_DEBUG,
1674 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1676 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1677 readArray[readPipes++] = fh;
1681 LOG (GNUNET_ERROR_TYPE_DEBUG,
1682 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1683 handle_array[nhandles++] = hEventReadReady;
1684 readArray[readPipes++] = fh;
1689 LOG (GNUNET_ERROR_TYPE_DEBUG,
1690 "Adding the read ready event to the array as %d\n", nhandles);
1691 handle_array[nhandles++] = hEventReadReady;
1692 readArray[readPipes++] = fh;
1697 GNUNET_CONTAINER_slist_add (handles_read,
1698 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1699 fh, sizeof (struct GNUNET_DISK_FileHandle));
1703 if (wfds && write_handles)
1705 LOG (GNUNET_ERROR_TYPE_DEBUG,
1706 "Adding the write ready event to the array as %d\n", nhandles);
1707 handle_array[nhandles++] = hEventPipeWrite;
1708 writePipePos = nhandles;
1710 if (efds && ex_handles)
1712 struct GNUNET_CONTAINER_SList_Iterator i;
1714 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1715 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1716 GNUNET_CONTAINER_slist_next (&i))
1718 struct GNUNET_DISK_FileHandle *fh;
1721 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1723 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1725 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1727 GNUNET_CONTAINER_slist_add (handles_except,
1728 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1730 sizeof (struct GNUNET_DISK_FileHandle));
1740 LOG (GNUNET_ERROR_TYPE_DEBUG,
1741 "Adding the socket event to the array as %d\n", nhandles);
1742 handle_array[nhandles++] = select_finished_event;
1743 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1747 select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1748 select_timeout.tv_usec = 1000 * (timeout.rel_value -
1749 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1750 sp.tv = &select_timeout;
1752 FD_SET (select_wakeup_socket, &aread);
1756 /* Failed connections cause sockets to be set in errorfds on W32,
1757 * but on POSIX it should set them in writefds.
1758 * First copy all awrite sockets to aexcept, later we'll
1759 * check aexcept and set its contents in awrite as well
1760 * Sockets are also set in errorfds when OOB data is available,
1761 * but we don't use OOB data.
1763 for (i = 0; i < awrite.fd_count; i++)
1764 FD_SET (awrite.fd_array[i], &aexcept);
1765 ResetEvent (select_finished_event);
1766 SetEvent (select_standby_event);
1769 handle_array[nhandles] = NULL;
1770 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n",
1771 nfds, nhandles, (unsigned long long) ms_total);
1775 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1776 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1781 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1782 returncode = WAIT_TIMEOUT;
1786 /* Shouldn't come this far. If it does - investigate. */
1792 /* Don't wake up select-thread when delay is 0, it should return immediately
1793 * and wake up by itself.
1796 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1797 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1798 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1803 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1806 /* Check aexcept, add its contents to awrite */
1807 for (i = 0; i < aexcept.fd_count; i++)
1808 FD_SET (aexcept.fd_array[i], &awrite);
1811 returnedpos = returncode - WAIT_OBJECT_0;
1812 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1814 if (nhandles && (returnedpos < nhandles))
1819 retcode += sp.status;
1821 if ((writePipePos != -1) && (returnedpos < writePipePos))
1823 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1824 retcode += write_handles;
1825 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1827 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1828 /* We have some pipes ready for read. */
1829 if (returnedpos < readPipes)
1831 for (i = 0; i < readPipes; i++)
1839 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1840 error = GetLastError ();
1841 LOG (GNUNET_ERROR_TYPE_DEBUG,
1842 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1843 i, readArray[i]->h, bret, waitstatus, error);
1846 /* TODO: either add more errors to this condition, or eliminate it
1847 * entirely (failed to peek -> pipe is in serious trouble, should
1848 * be selected as readable).
1850 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1853 else if (waitstatus <= 0)
1855 GNUNET_CONTAINER_slist_add (handles_read,
1856 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1858 sizeof (struct GNUNET_DISK_FileHandle));
1860 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1861 readArray[i], readArray[i]->h);
1865 if (!nhandles || (returnedpos >= nhandles))
1866 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1869 struct GNUNET_CONTAINER_SList_Iterator t;
1871 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1872 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1873 GNUNET_CONTAINER_slist_next (&t))
1875 struct GNUNET_DISK_FileHandle *fh;
1877 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1879 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1884 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1885 GNUNET_NETWORK_fdset_zero (rfds);
1886 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1887 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1888 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1892 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1893 GNUNET_NETWORK_fdset_zero (wfds);
1894 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1895 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1896 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1900 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1901 GNUNET_NETWORK_fdset_zero (efds);
1902 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1903 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1904 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1906 GNUNET_CONTAINER_slist_destroy (handles_read);
1907 GNUNET_CONTAINER_slist_destroy (handles_write);
1908 GNUNET_CONTAINER_slist_destroy (handles_except);
1912 struct GNUNET_CONTAINER_SList_Iterator t;
1914 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1915 for (i = 0; i < rfds->sds.fd_count; i++)
1917 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1919 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1920 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1921 GNUNET_CONTAINER_slist_next (&t))
1923 struct GNUNET_DISK_FileHandle *fh;
1925 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1927 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1932 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1933 for (i = 0; i < wfds->sds.fd_count; i++)
1935 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1940 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1941 for (i = 0; i < efds->sds.fd_count; i++)
1943 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1946 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1948 if (nhandles && (returnedpos < nhandles))
1955 /* end of network.c */