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 address address to be bound
369 * @param address_len length of address
370 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
373 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
374 const struct sockaddr *address,
375 socklen_t address_len)
383 if (desc->af == AF_INET6)
384 if (0 != setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
385 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
389 /* This is required, and required here, but only on UNIX */
390 if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
391 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
395 if (address->sa_family == AF_UNIX)
397 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
399 (void) unlink (un->sun_path);
403 ret = bind (desc->fd, address, address_len);
405 if (SOCKET_ERROR == ret)
406 SetErrnoFromWinsockError (WSAGetLastError ());
409 return GNUNET_SYSERR;
412 desc->addr = GNUNET_malloc (address_len);
413 memcpy (desc->addr, address, address_len);
414 desc->addrlen = address_len;
424 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
427 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
435 ret = closesocket (desc->fd);
436 error = WSAGetLastError ();
437 SetErrnoFromWinsockError (error);
438 LOG (GNUNET_ERROR_TYPE_DEBUG,
439 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
442 ret = close (desc->fd);
446 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
448 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
450 if (0 != unlink (un->sun_path))
451 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
455 GNUNET_free_non_null (desc->addr);
457 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
462 * Box a native socket (and check that it is a socket).
464 * @param fd socket to box
465 * @return NULL on error (including not supported on target platform)
467 struct GNUNET_NETWORK_Handle *
468 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
470 struct GNUNET_NETWORK_Handle *ret;
474 /* FIXME: Find a better call to check that FD is valid */
475 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
476 return NULL; /* invalid FD */
477 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
482 if (fcntl (fd, F_GETFD) < 0)
483 return NULL; /* invalid FD */
484 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
495 * @param address peer address
496 * @param address_len length of address
497 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
500 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
501 const struct sockaddr *address,
502 socklen_t address_len)
506 ret = connect (desc->fd, address, address_len);
509 if (SOCKET_ERROR == ret)
511 SetErrnoFromWinsockError (WSAGetLastError ());
512 if (errno == EWOULDBLOCK)
516 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
524 * @param level protocol level of the option
525 * @param optname identifier of the option
526 * @param optval options
527 * @param optlen length of optval
528 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
531 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
532 int level, int optname, void *optval,
537 ret = getsockopt (desc->fd, level, optname, optval, optlen);
540 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
541 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
543 else if (SOCKET_ERROR == ret)
544 SetErrnoFromWinsockError (WSAGetLastError ());
546 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
553 * @param backlog length of the listen queue
554 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
557 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
562 ret = listen (desc->fd, backlog);
565 if (SOCKET_ERROR == ret)
566 SetErrnoFromWinsockError (WSAGetLastError ());
569 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
574 * How much data is available to be read on this descriptor?
576 * Returns GNUNET_NO if no data is available, or on error!
580 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
585 /* How much is there to be read? */
589 error = ioctl (desc->fd, FIONREAD, &pending);
591 return (ssize_t) pending;
596 error = ioctlsocket (desc->fd, FIONREAD, &pending);
597 if (error != SOCKET_ERROR)
598 return (ssize_t) pending;
605 * Read data from a connected socket (always non-blocking).
607 * @param buffer buffer
608 * @param length length of buffer
609 * @param src_addr either the source to recv from, or all zeroes
610 * to be filled in by recvfrom
611 * @param addrlen length of the addr
614 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
615 void *buffer, size_t length,
616 struct sockaddr * src_addr, socklen_t * addrlen)
624 flags |= MSG_DONTWAIT;
627 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
629 if (SOCKET_ERROR == ret)
630 SetErrnoFromWinsockError (WSAGetLastError ());
637 * Read data from a connected socket (always non-blocking).
639 * @param buffer buffer
640 * @param length length of buffer
643 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
644 void *buffer, size_t length)
652 flags |= MSG_DONTWAIT;
654 ret = recv (desc->fd, buffer, length, flags);
656 if (SOCKET_ERROR == ret)
657 SetErrnoFromWinsockError (WSAGetLastError ());
664 * Send data (always non-blocking).
667 * @param buffer data to send
668 * @param length size of the buffer
669 * @return number of bytes sent, GNUNET_SYSERR on error
672 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
673 const void *buffer, size_t length)
681 flags |= MSG_DONTWAIT;
685 flags |= MSG_NOSIGNAL;
688 ret = send (desc->fd, buffer, length, flags);
691 if (SOCKET_ERROR == ret)
692 SetErrnoFromWinsockError (WSAGetLastError ());
700 * Send data to a particular destination (always non-blocking).
701 * This function only works for UDP sockets.
704 * @param message data to send
705 * @param length size of the data
706 * @param dest_addr destination address
707 * @param dest_len length of address
708 * @return number of bytes sent, GNUNET_SYSERR on error
711 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
712 const void *message, size_t length,
713 const struct sockaddr * dest_addr,
722 flags |= MSG_DONTWAIT;
725 flags |= MSG_NOSIGNAL;
727 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
729 if (SOCKET_ERROR == ret)
730 SetErrnoFromWinsockError (WSAGetLastError ());
739 * @param level protocol level of the option
740 * @param option_name option identifier
741 * @param option_value value to set
742 * @param option_len size of option_value
743 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
746 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
747 int option_name, const void *option_value,
748 socklen_t option_len)
752 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
754 if (SOCKET_ERROR == ret)
755 SetErrnoFromWinsockError (WSAGetLastError ());
757 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
762 * Create a new socket. Configure it for non-blocking IO and
763 * mark it as non-inheritable to child processes (set the
764 * close-on-exec flag).
766 * @param domain domain of the socket
767 * @param type socket type
768 * @param protocol network protocol
769 * @return new socket, NULL on error
771 struct GNUNET_NETWORK_Handle *
772 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
774 struct GNUNET_NETWORK_Handle *ret;
776 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
777 ret->fd = socket (domain, type, protocol);
779 initialize_network_handle (ret, domain, type))
786 * Shut down socket operations
788 * @param how type of shutdown
789 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
792 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
796 ret = shutdown (desc->fd, how);
799 SetErrnoFromWinsockError (WSAGetLastError ());
801 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
806 * Disable the "CORK" feature for communication with the given socket,
807 * forcing the OS to immediately flush the buffer on transmission
808 * instead of potentially buffering multiple messages. Essentially
809 * reduces the OS send buffers to zero.
812 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
815 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
824 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
826 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
829 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
831 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
837 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
838 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
841 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
842 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
844 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
853 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
858 GNUNET_CONTAINER_slist_clear (fds->handles);
863 * Add a socket to the FD set
865 * @param desc socket to add
868 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
869 const struct GNUNET_NETWORK_Handle *desc)
871 FD_SET (desc->fd, &fds->sds);
872 if (desc->fd + 1 > fds->nsds)
873 fds->nsds = desc->fd + 1;
878 * Check whether a socket is part of the fd set
881 * @return 0 if the FD is not set
884 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
885 const struct GNUNET_NETWORK_Handle *desc)
887 return FD_ISSET (desc->fd, &fds->sds);
892 * Add one fd set to another
893 * @param dst the fd set to add to
894 * @param src the fd set to add from
897 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
898 const struct GNUNET_NETWORK_FDSet *src)
903 for (nfds = src->nsds; nfds > 0; nfds--)
904 if (FD_ISSET (nfds, &src->sds))
907 FD_SET (nfds, &dst->sds);
908 if (nfds + 1 > dst->nsds)
909 dst->nsds = nfds + 1;
912 /* This is MinGW32-specific implementation that relies on the code that
913 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
914 * that fd being added is not already in the set.
915 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
918 for (i = 0; i < src->sds.fd_count; i++)
919 FD_SET (src->sds.fd_array[i], &dst->sds);
920 if (src->nsds > dst->nsds)
921 dst->nsds = src->nsds;
923 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
929 * Copy one fd set to another
931 * @param to destination
935 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
936 const struct GNUNET_NETWORK_FDSet *from)
938 FD_COPY (&from->sds, &to->sds);
939 to->nsds = from->nsds;
942 GNUNET_CONTAINER_slist_clear (to->handles);
943 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
949 * Return file descriptor for this network handle
951 * @param desc wrapper to process
952 * @return POSIX file descriptor
955 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
961 * Return sockaddr for this network handle
963 * @param desc wrapper to process
967 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
973 * Return sockaddr length for this network handle
975 * @param desc wrapper to process
976 * @return socklen_t for sockaddr
979 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
981 return desc->addrlen;
984 * Copy a native fd set
986 * @param to destination
987 * @param from native source set
988 * @param nfds the biggest socket number in from + 1
991 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
992 const fd_set * from, int nfds)
994 FD_COPY (from, &to->sds);
1000 * Set a native fd in a set
1002 * @param to destination
1003 * @param nfd native FD to set
1006 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1008 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1009 FD_SET (nfd, &to->sds);
1010 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1015 * Test native fd in a set
1017 * @param to set to test, NULL for empty set
1018 * @param nfd native FD to test, or -1 for none
1019 * @return GNUNET_YES if FD is set in the set
1022 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1025 if ((nfd == -1) || (to == NULL))
1027 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1032 * Add a file handle to the fd set
1034 * @param h the file handle to add
1037 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1038 const struct GNUNET_DISK_FileHandle *h)
1041 GNUNET_CONTAINER_slist_add (fds->handles,
1042 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1043 sizeof (struct GNUNET_DISK_FileHandle));
1048 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1049 FD_SET (fd, &fds->sds);
1050 if (fd + 1 > fds->nsds)
1058 * Check if a file handle is part of an fd set
1060 * @param h file handle
1061 * @return GNUNET_YES if the file handle is part of the set
1064 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1065 const struct GNUNET_DISK_FileHandle *h)
1069 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1071 GNUNET_DISK_FileHandle));
1073 return FD_ISSET (h->fd, &fds->sds);
1079 * Checks if two fd sets overlap
1080 * @param fds1 first fd set
1081 * @param fds2 second fd set
1082 * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
1085 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1086 const struct GNUNET_NETWORK_FDSet *fds2)
1092 if (nfds > fds2->nsds)
1097 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1101 struct GNUNET_CONTAINER_SList_Iterator it;
1102 struct GNUNET_DISK_FileHandle *h;
1106 /*This code is somewhat hacky, we are not supposed to know what's
1107 * inside of fd_set; also the O(n^2) is really bad... */
1109 for (i = 0; i < fds1->sds.fd_count; i++)
1111 for (j = 0; j < fds2->sds.fd_count; j++)
1113 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1117 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1118 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1121 struct GNUNET_CONTAINER_SList_Iterator t;
1123 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1126 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1128 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1129 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1130 GNUNET_CONTAINER_slist_next (&t))
1132 struct GNUNET_DISK_FileHandle *fh;
1134 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1136 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1139 if (GNUNET_CONTAINER_slist_contains
1140 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1144 GNUNET_CONTAINER_slist_next (&it);
1153 * @return a new fd set
1155 struct GNUNET_NETWORK_FDSet *
1156 GNUNET_NETWORK_fdset_create ()
1158 struct GNUNET_NETWORK_FDSet *fds;
1160 fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1162 fds->handles = GNUNET_CONTAINER_slist_create ();
1164 GNUNET_NETWORK_fdset_zero (fds);
1170 * Releases the associated memory of an fd set
1174 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1177 GNUNET_CONTAINER_slist_destroy (fds->handles);
1183 struct _select_params
1191 SOCKET wakeup_socket;
1196 _selector (LPVOID p)
1198 struct _select_params *sp = p;
1202 WaitForSingleObject (sp->standby, INFINITE);
1203 ResetEvent (sp->standby);
1204 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1205 if (FD_ISSET (sp->wakeup_socket, sp->r))
1207 FD_CLR (sp->wakeup_socket, sp->r);
1210 SetEvent (sp->wakeup);
1217 * Check if sockets or pipes meet certain conditions
1218 * @param rfds set of sockets or pipes to be checked for readability
1219 * @param wfds set of sockets or pipes to be checked for writability
1220 * @param efds set of sockets or pipes to be checked for exceptions
1221 * @param timeout relative value when to return
1222 * @return number of selected sockets or pipes, GNUNET_SYSERR on error
1225 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1226 struct GNUNET_NETWORK_FDSet *wfds,
1227 struct GNUNET_NETWORK_FDSet *efds,
1228 const struct GNUNET_TIME_Relative timeout)
1234 int read_handles = 0;
1235 int write_handles = 0;
1243 static HANDLE hEventPipeWrite = 0;
1244 static HANDLE hEventReadReady = 0;
1246 static struct _select_params sp;
1247 static HANDLE select_thread = NULL;
1248 static HANDLE select_finished_event = NULL;
1249 static HANDLE select_standby_event = NULL;
1250 static SOCKET select_wakeup_socket = -1;
1251 static SOCKET select_send_socket = -1;
1252 static struct timeval select_timeout;
1255 int writePipePos = 0;
1257 HANDLE handle_array[FD_SETSIZE + 2];
1258 int returncode = -1;
1259 int returnedpos = 0;
1261 struct GNUNET_CONTAINER_SList *handles_read;
1262 struct GNUNET_CONTAINER_SList *handles_write;
1263 struct GNUNET_CONTAINER_SList *handles_except;
1277 /* TODO: Make this growable */
1278 struct GNUNET_DISK_FileHandle *readArray[50];
1286 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1289 struct GNUNET_CONTAINER_SList_Iterator t;
1291 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1292 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1293 GNUNET_CONTAINER_slist_next (&t))
1295 struct GNUNET_DISK_FileHandle *fh;
1297 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1299 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1308 nfds = GNUNET_MAX (nfds, wfds->nsds);
1310 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1315 nfds = GNUNET_MAX (nfds, efds->nsds);
1317 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1322 (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1329 LOG (GNUNET_ERROR_TYPE_ERROR,
1331 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1335 tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1337 1000 * (timeout.rel_value -
1338 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1339 return select (nfds, (rfds != NULL) ? &rfds->sds : NULL,
1340 (wfds != NULL) ? &wfds->sds : NULL,
1341 (efds != NULL) ? &efds->sds : NULL,
1342 (timeout.rel_value ==
1343 GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ? NULL : &tv);
1346 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1347 /* calculate how long we need to wait in milliseconds */
1348 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1349 ms_total = INFINITE;
1352 ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1353 if (timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value > 0xFFFFFFFFLL - 1)
1356 ms_total = 0xFFFFFFFF - 1;
1359 /* select() may be used as a portable way to sleep */
1360 if (!(rfds || wfds || efds))
1366 if (select_thread == NULL)
1368 SOCKET select_listening_socket = -1;
1369 struct sockaddr_in s_in;
1374 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1375 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1377 select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1379 select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1382 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1383 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1385 alen = sizeof (s_in);
1386 s_in.sin_family = AF_INET;
1388 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1389 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1390 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1391 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1392 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1393 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1395 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1396 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1398 res = listen (select_listening_socket, SOMAXCONN);
1399 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1401 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1402 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1404 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1406 closesocket (select_listening_socket);
1408 sp.wakeup = select_finished_event;
1409 sp.standby = select_standby_event;
1410 sp.wakeup_socket = select_wakeup_socket;
1412 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1416 handles_read = GNUNET_CONTAINER_slist_create ();
1417 handles_write = GNUNET_CONTAINER_slist_create ();
1418 handles_except = GNUNET_CONTAINER_slist_create ();
1429 FD_COPY (&rfds->sds, &aread);
1431 FD_COPY (&rfds->sds, &bread);
1436 FD_COPY (&wfds->sds, &awrite);
1438 FD_COPY (&wfds->sds, &bwrite);
1443 FD_COPY (&efds->sds, &aexcept);
1445 FD_COPY (&efds->sds, &bexcept);
1449 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1450 By profiling we detected that to be true in 90% of the cases.
1453 /* Do the select now */
1454 select_timeout.tv_sec = 0;
1455 select_timeout.tv_usec = 0;
1457 /* Copy all the writes to the except, so we can detect connect() errors */
1458 for (i = 0; i < awrite.fd_count; i++)
1459 FD_SET (awrite.fd_array[i], &aexcept);
1460 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1461 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1462 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1465 if (selectret == -1)
1467 /* Throw an error early on, while we still have the context. */
1468 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1469 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1473 /* Check aexcept, add its contents to awrite
1474 This is technically wrong (aexcept might have its own descriptors), we should
1475 have checked that descriptors were in awrite originally before re-adding them from
1476 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1477 for (i = 0; i < aexcept.fd_count; i++)
1478 FD_SET (aexcept.fd_array[i], &awrite);
1480 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1481 /* Sadly, it means code duplication :( */
1482 if ((selectret > 0) || (ms_total == 0))
1485 if (rfds && read_handles)
1487 struct GNUNET_CONTAINER_SList_Iterator i;
1490 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1491 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1492 GNUNET_CONTAINER_slist_next (&i), c++)
1494 struct GNUNET_DISK_FileHandle *fh;
1496 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1497 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1503 DWORD waitstatus = 0;
1504 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1505 error = GetLastError ();
1506 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1507 c, fh->h, bret, waitstatus, error);
1510 /* TODO: either add more errors to this condition, or eliminate it
1511 * entirely (failed to peek -> pipe is in serious trouble, should
1512 * be selected as readable).
1514 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1517 else if (waitstatus <= 0)
1519 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1520 fh, sizeof (struct GNUNET_DISK_FileHandle));
1522 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1527 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1528 fh, sizeof (struct GNUNET_DISK_FileHandle));
1533 if (wfds && write_handles)
1535 LOG (GNUNET_ERROR_TYPE_DEBUG,
1536 "Adding the write ready event to the array as %d\n", nhandles);
1537 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1538 retcode += write_handles;
1540 if (efds && ex_handles)
1542 struct GNUNET_CONTAINER_SList_Iterator i;
1544 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1545 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1546 GNUNET_CONTAINER_slist_next (&i))
1548 struct GNUNET_DISK_FileHandle *fh;
1551 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1552 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1554 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1556 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1557 fh, sizeof (struct GNUNET_DISK_FileHandle));
1563 /* Add our select() result.*/
1565 retcode += selectret;
1569 GNUNET_NETWORK_fdset_zero (rfds);
1570 if (selectret != -1)
1571 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1572 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1576 GNUNET_NETWORK_fdset_zero (wfds);
1577 if (selectret != -1)
1578 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1579 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1583 GNUNET_NETWORK_fdset_zero (efds);
1584 if (selectret != -1)
1585 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1586 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1588 GNUNET_CONTAINER_slist_destroy (handles_read);
1589 GNUNET_CONTAINER_slist_destroy (handles_write);
1590 GNUNET_CONTAINER_slist_destroy (handles_except);
1592 if (selectret == -1)
1597 /* If we got this far, use slower implementation that is able to do a waiting select
1598 on both sockets and pipes simultaneously */
1600 /* Events for pipes */
1601 if (!hEventReadReady)
1602 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1603 if (!hEventPipeWrite)
1604 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1620 FD_COPY (&rfds->sds, &aread);
1622 FD_COPY (&rfds->sds, &bread);
1627 FD_COPY (&wfds->sds, &awrite);
1629 FD_COPY (&wfds->sds, &bwrite);
1634 FD_COPY (&efds->sds, &aexcept);
1636 FD_COPY (&efds->sds, &bexcept);
1639 /* We will first Add the PIPES to the events */
1641 if (rfds && read_handles)
1643 struct GNUNET_CONTAINER_SList_Iterator i;
1645 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1646 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1647 GNUNET_CONTAINER_slist_next (&i))
1649 struct GNUNET_DISK_FileHandle *fh;
1651 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1653 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1655 /* Read zero bytes to check the status of the pipe */
1656 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1658 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1660 DWORD error_code = GetLastError ();
1662 if (error_code == ERROR_IO_PENDING)
1664 LOG (GNUNET_ERROR_TYPE_DEBUG,
1665 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1667 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1668 readArray[readPipes++] = fh;
1672 LOG (GNUNET_ERROR_TYPE_DEBUG,
1673 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1674 handle_array[nhandles++] = hEventReadReady;
1675 readArray[readPipes++] = fh;
1680 LOG (GNUNET_ERROR_TYPE_DEBUG,
1681 "Adding the read ready event to the array as %d\n", nhandles);
1682 handle_array[nhandles++] = hEventReadReady;
1683 readArray[readPipes++] = fh;
1688 GNUNET_CONTAINER_slist_add (handles_read,
1689 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1690 fh, sizeof (struct GNUNET_DISK_FileHandle));
1694 if (wfds && write_handles)
1696 LOG (GNUNET_ERROR_TYPE_DEBUG,
1697 "Adding the write ready event to the array as %d\n", nhandles);
1698 handle_array[nhandles++] = hEventPipeWrite;
1699 writePipePos = nhandles;
1701 if (efds && ex_handles)
1703 struct GNUNET_CONTAINER_SList_Iterator i;
1705 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1706 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1707 GNUNET_CONTAINER_slist_next (&i))
1709 struct GNUNET_DISK_FileHandle *fh;
1712 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1714 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1716 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1718 GNUNET_CONTAINER_slist_add (handles_except,
1719 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1721 sizeof (struct GNUNET_DISK_FileHandle));
1731 LOG (GNUNET_ERROR_TYPE_DEBUG,
1732 "Adding the socket event to the array as %d\n", nhandles);
1733 handle_array[nhandles++] = select_finished_event;
1734 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1738 select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1739 select_timeout.tv_usec = 1000 * (timeout.rel_value -
1740 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1741 sp.tv = &select_timeout;
1743 FD_SET (select_wakeup_socket, &aread);
1747 /* Failed connections cause sockets to be set in errorfds on W32,
1748 * but on POSIX it should set them in writefds.
1749 * First copy all awrite sockets to aexcept, later we'll
1750 * check aexcept and set its contents in awrite as well
1751 * Sockets are also set in errorfds when OOB data is available,
1752 * but we don't use OOB data.
1754 for (i = 0; i < awrite.fd_count; i++)
1755 FD_SET (awrite.fd_array[i], &aexcept);
1756 ResetEvent (select_finished_event);
1757 SetEvent (select_standby_event);
1760 handle_array[nhandles] = NULL;
1761 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n",
1762 nfds, nhandles, (unsigned long long) ms_total);
1766 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1767 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1772 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1773 returncode = WAIT_TIMEOUT;
1777 /* Shouldn't come this far. If it does - investigate. */
1783 /* Don't wake up select-thread when delay is 0, it should return immediately
1784 * and wake up by itself.
1787 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1788 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1789 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1794 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1797 /* Check aexcept, add its contents to awrite */
1798 for (i = 0; i < aexcept.fd_count; i++)
1799 FD_SET (aexcept.fd_array[i], &awrite);
1802 returnedpos = returncode - WAIT_OBJECT_0;
1803 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1805 if (nhandles && (returnedpos < nhandles))
1810 retcode += sp.status;
1812 if ((writePipePos != -1) && (returnedpos < writePipePos))
1814 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1815 retcode += write_handles;
1816 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1818 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1819 /* We have some pipes ready for read. */
1820 if (returnedpos < readPipes)
1822 for (i = 0; i < readPipes; i++)
1830 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1831 error = GetLastError ();
1832 LOG (GNUNET_ERROR_TYPE_DEBUG,
1833 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1834 i, readArray[i]->h, bret, waitstatus, error);
1837 /* TODO: either add more errors to this condition, or eliminate it
1838 * entirely (failed to peek -> pipe is in serious trouble, should
1839 * be selected as readable).
1841 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1844 else if (waitstatus <= 0)
1846 GNUNET_CONTAINER_slist_add (handles_read,
1847 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1849 sizeof (struct GNUNET_DISK_FileHandle));
1851 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1852 readArray[i], readArray[i]->h);
1856 if (!nhandles || (returnedpos >= nhandles))
1857 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1860 struct GNUNET_CONTAINER_SList_Iterator t;
1862 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1863 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1864 GNUNET_CONTAINER_slist_next (&t))
1866 struct GNUNET_DISK_FileHandle *fh;
1868 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1870 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1875 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1876 GNUNET_NETWORK_fdset_zero (rfds);
1877 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1878 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1879 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1883 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1884 GNUNET_NETWORK_fdset_zero (wfds);
1885 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1886 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1887 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1891 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1892 GNUNET_NETWORK_fdset_zero (efds);
1893 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1894 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1895 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1897 GNUNET_CONTAINER_slist_destroy (handles_read);
1898 GNUNET_CONTAINER_slist_destroy (handles_write);
1899 GNUNET_CONTAINER_slist_destroy (handles_except);
1903 struct GNUNET_CONTAINER_SList_Iterator t;
1905 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1906 for (i = 0; i < rfds->sds.fd_count; i++)
1908 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1910 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1911 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1912 GNUNET_CONTAINER_slist_next (&t))
1914 struct GNUNET_DISK_FileHandle *fh;
1916 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1918 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1923 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1924 for (i = 0; i < wfds->sds.fd_count; i++)
1926 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1931 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1932 for (i = 0; i < efds->sds.fd_count; i++)
1934 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1937 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1939 if (nhandles && (returnedpos < nhandles))
1946 /* end of network.c */