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,
385 if (desc->af == AF_INET6)
386 if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
387 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
395 /* This is required, and required here, but only on UNIX */
396 if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
397 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
402 if (address->sa_family == AF_UNIX && (flags & GNUNET_BIND_EXCLUSIVE) == 0)
404 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
406 (void) unlink (un->sun_path);
410 ret = bind (desc->fd, address, address_len);
412 if (SOCKET_ERROR == ret)
413 SetErrnoFromWinsockError (WSAGetLastError ());
416 return GNUNET_SYSERR;
419 desc->addr = GNUNET_malloc (address_len);
420 memcpy (desc->addr, address, address_len);
421 desc->addrlen = address_len;
431 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
434 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
442 ret = closesocket (desc->fd);
443 error = WSAGetLastError ();
444 SetErrnoFromWinsockError (error);
445 LOG (GNUNET_ERROR_TYPE_DEBUG,
446 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
449 ret = close (desc->fd);
453 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
455 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
457 if (0 != unlink (un->sun_path))
458 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
462 GNUNET_free_non_null (desc->addr);
464 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
469 * Box a native socket (and check that it is a socket).
471 * @param fd socket to box
472 * @return NULL on error (including not supported on target platform)
474 struct GNUNET_NETWORK_Handle *
475 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
477 struct GNUNET_NETWORK_Handle *ret;
481 /* FIXME: Find a better call to check that FD is valid */
482 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
483 return NULL; /* invalid FD */
484 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
489 if (fcntl (fd, F_GETFD) < 0)
490 return NULL; /* invalid FD */
491 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
502 * @param address peer address
503 * @param address_len length of address
504 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
507 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
508 const struct sockaddr *address,
509 socklen_t address_len)
513 ret = connect (desc->fd, address, address_len);
516 if (SOCKET_ERROR == ret)
518 SetErrnoFromWinsockError (WSAGetLastError ());
519 if (errno == EWOULDBLOCK)
523 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
531 * @param level protocol level of the option
532 * @param optname identifier of the option
533 * @param optval options
534 * @param optlen length of optval
535 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
538 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
539 int level, int optname, void *optval,
544 ret = getsockopt (desc->fd, level, optname, optval, optlen);
547 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
548 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
550 else if (SOCKET_ERROR == ret)
551 SetErrnoFromWinsockError (WSAGetLastError ());
553 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
560 * @param backlog length of the listen queue
561 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
564 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
569 ret = listen (desc->fd, backlog);
572 if (SOCKET_ERROR == ret)
573 SetErrnoFromWinsockError (WSAGetLastError ());
576 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
581 * How much data is available to be read on this descriptor?
583 * Returns GNUNET_NO if no data is available, or on error!
587 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
592 /* How much is there to be read? */
596 error = ioctl (desc->fd, FIONREAD, &pending);
598 return (ssize_t) pending;
603 error = ioctlsocket (desc->fd, FIONREAD, &pending);
604 if (error != SOCKET_ERROR)
605 return (ssize_t) pending;
612 * Read data from a connected socket (always non-blocking).
614 * @param buffer buffer
615 * @param length length of buffer
616 * @param src_addr either the source to recv from, or all zeroes
617 * to be filled in by recvfrom
618 * @param addrlen length of the addr
621 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
622 void *buffer, size_t length,
623 struct sockaddr * src_addr, socklen_t * addrlen)
631 flags |= MSG_DONTWAIT;
634 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
636 if (SOCKET_ERROR == ret)
637 SetErrnoFromWinsockError (WSAGetLastError ());
644 * Read data from a connected socket (always non-blocking).
646 * @param buffer buffer
647 * @param length length of buffer
650 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
651 void *buffer, size_t length)
659 flags |= MSG_DONTWAIT;
661 ret = recv (desc->fd, buffer, length, flags);
663 if (SOCKET_ERROR == ret)
664 SetErrnoFromWinsockError (WSAGetLastError ());
671 * Send data (always non-blocking).
674 * @param buffer data to send
675 * @param length size of the buffer
676 * @return number of bytes sent, GNUNET_SYSERR on error
679 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
680 const void *buffer, size_t length)
688 flags |= MSG_DONTWAIT;
692 flags |= MSG_NOSIGNAL;
695 ret = send (desc->fd, buffer, length, flags);
698 if (SOCKET_ERROR == ret)
699 SetErrnoFromWinsockError (WSAGetLastError ());
707 * Send data to a particular destination (always non-blocking).
708 * This function only works for UDP sockets.
711 * @param message data to send
712 * @param length size of the data
713 * @param dest_addr destination address
714 * @param dest_len length of address
715 * @return number of bytes sent, GNUNET_SYSERR on error
718 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
719 const void *message, size_t length,
720 const struct sockaddr * dest_addr,
729 flags |= MSG_DONTWAIT;
732 flags |= MSG_NOSIGNAL;
734 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
736 if (SOCKET_ERROR == ret)
737 SetErrnoFromWinsockError (WSAGetLastError ());
746 * @param level protocol level of the option
747 * @param option_name option identifier
748 * @param option_value value to set
749 * @param option_len size of option_value
750 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
753 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
754 int option_name, const void *option_value,
755 socklen_t option_len)
759 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
761 if (SOCKET_ERROR == ret)
762 SetErrnoFromWinsockError (WSAGetLastError ());
764 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
769 * Create a new socket. Configure it for non-blocking IO and
770 * mark it as non-inheritable to child processes (set the
771 * close-on-exec flag).
773 * @param domain domain of the socket
774 * @param type socket type
775 * @param protocol network protocol
776 * @return new socket, NULL on error
778 struct GNUNET_NETWORK_Handle *
779 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
781 struct GNUNET_NETWORK_Handle *ret;
783 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
784 ret->fd = socket (domain, type, protocol);
786 initialize_network_handle (ret, domain, type))
793 * Shut down socket operations
795 * @param how type of shutdown
796 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
799 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
803 ret = shutdown (desc->fd, how);
806 SetErrnoFromWinsockError (WSAGetLastError ());
808 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
813 * Disable the "CORK" feature for communication with the given socket,
814 * forcing the OS to immediately flush the buffer on transmission
815 * instead of potentially buffering multiple messages. Essentially
816 * reduces the OS send buffers to zero.
819 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
822 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
831 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
833 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
836 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
838 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
844 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
845 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
848 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
849 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
851 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
860 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
865 GNUNET_CONTAINER_slist_clear (fds->handles);
870 * Add a socket to the FD set
872 * @param desc socket to add
875 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
876 const struct GNUNET_NETWORK_Handle *desc)
878 FD_SET (desc->fd, &fds->sds);
879 if (desc->fd + 1 > fds->nsds)
880 fds->nsds = desc->fd + 1;
885 * Check whether a socket is part of the fd set
888 * @return 0 if the FD is not set
891 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
892 const struct GNUNET_NETWORK_Handle *desc)
894 return FD_ISSET (desc->fd, &fds->sds);
899 * Add one fd set to another
900 * @param dst the fd set to add to
901 * @param src the fd set to add from
904 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
905 const struct GNUNET_NETWORK_FDSet *src)
910 for (nfds = src->nsds; nfds > 0; nfds--)
911 if (FD_ISSET (nfds, &src->sds))
914 FD_SET (nfds, &dst->sds);
915 if (nfds + 1 > dst->nsds)
916 dst->nsds = nfds + 1;
919 /* This is MinGW32-specific implementation that relies on the code that
920 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
921 * that fd being added is not already in the set.
922 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
925 for (i = 0; i < src->sds.fd_count; i++)
926 FD_SET (src->sds.fd_array[i], &dst->sds);
927 if (src->nsds > dst->nsds)
928 dst->nsds = src->nsds;
930 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
936 * Copy one fd set to another
938 * @param to destination
942 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
943 const struct GNUNET_NETWORK_FDSet *from)
945 FD_COPY (&from->sds, &to->sds);
946 to->nsds = from->nsds;
949 GNUNET_CONTAINER_slist_clear (to->handles);
950 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
956 * Return file descriptor for this network handle
958 * @param desc wrapper to process
959 * @return POSIX file descriptor
962 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
968 * Return sockaddr for this network handle
970 * @param desc wrapper to process
974 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
980 * Return sockaddr length for this network handle
982 * @param desc wrapper to process
983 * @return socklen_t for sockaddr
986 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
988 return desc->addrlen;
991 * Copy a native fd set
993 * @param to destination
994 * @param from native source set
995 * @param nfds the biggest socket number in from + 1
998 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
999 const fd_set * from, int nfds)
1001 FD_COPY (from, &to->sds);
1007 * Set a native fd in a set
1009 * @param to destination
1010 * @param nfd native FD to set
1013 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1015 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1016 FD_SET (nfd, &to->sds);
1017 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1022 * Test native fd in a set
1024 * @param to set to test, NULL for empty set
1025 * @param nfd native FD to test, or -1 for none
1026 * @return GNUNET_YES if FD is set in the set
1029 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1032 if ((nfd == -1) || (to == NULL))
1034 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1039 * Add a file handle to the fd set
1041 * @param h the file handle to add
1044 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1045 const struct GNUNET_DISK_FileHandle *h)
1048 GNUNET_CONTAINER_slist_add (fds->handles,
1049 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1050 sizeof (struct GNUNET_DISK_FileHandle));
1055 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1056 FD_SET (fd, &fds->sds);
1057 if (fd + 1 > fds->nsds)
1065 * Check if a file handle is part of an fd set
1067 * @param h file handle
1068 * @return GNUNET_YES if the file handle is part of the set
1071 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1072 const struct GNUNET_DISK_FileHandle *h)
1076 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1078 GNUNET_DISK_FileHandle));
1080 return FD_ISSET (h->fd, &fds->sds);
1086 * Checks if two fd sets overlap
1087 * @param fds1 first fd set
1088 * @param fds2 second fd set
1089 * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
1092 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1093 const struct GNUNET_NETWORK_FDSet *fds2)
1099 if (nfds > fds2->nsds)
1104 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1108 struct GNUNET_CONTAINER_SList_Iterator it;
1109 struct GNUNET_DISK_FileHandle *h;
1113 /*This code is somewhat hacky, we are not supposed to know what's
1114 * inside of fd_set; also the O(n^2) is really bad... */
1116 for (i = 0; i < fds1->sds.fd_count; i++)
1118 for (j = 0; j < fds2->sds.fd_count; j++)
1120 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1124 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1125 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1128 struct GNUNET_CONTAINER_SList_Iterator t;
1130 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1133 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1135 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1136 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1137 GNUNET_CONTAINER_slist_next (&t))
1139 struct GNUNET_DISK_FileHandle *fh;
1141 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1143 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1146 if (GNUNET_CONTAINER_slist_contains
1147 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1151 GNUNET_CONTAINER_slist_next (&it);
1160 * @return a new fd set
1162 struct GNUNET_NETWORK_FDSet *
1163 GNUNET_NETWORK_fdset_create ()
1165 struct GNUNET_NETWORK_FDSet *fds;
1167 fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1169 fds->handles = GNUNET_CONTAINER_slist_create ();
1171 GNUNET_NETWORK_fdset_zero (fds);
1177 * Releases the associated memory of an fd set
1181 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1184 GNUNET_CONTAINER_slist_destroy (fds->handles);
1190 struct _select_params
1198 SOCKET wakeup_socket;
1203 _selector (LPVOID p)
1205 struct _select_params *sp = p;
1209 WaitForSingleObject (sp->standby, INFINITE);
1210 ResetEvent (sp->standby);
1211 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1212 if (FD_ISSET (sp->wakeup_socket, sp->r))
1214 FD_CLR (sp->wakeup_socket, sp->r);
1217 SetEvent (sp->wakeup);
1224 * Check if sockets or pipes meet certain conditions
1225 * @param rfds set of sockets or pipes to be checked for readability
1226 * @param wfds set of sockets or pipes to be checked for writability
1227 * @param efds set of sockets or pipes to be checked for exceptions
1228 * @param timeout relative value when to return
1229 * @return number of selected sockets or pipes, GNUNET_SYSERR on error
1232 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1233 struct GNUNET_NETWORK_FDSet *wfds,
1234 struct GNUNET_NETWORK_FDSet *efds,
1235 const struct GNUNET_TIME_Relative timeout)
1241 int read_handles = 0;
1242 int write_handles = 0;
1250 static HANDLE hEventPipeWrite = 0;
1251 static HANDLE hEventReadReady = 0;
1253 static struct _select_params sp;
1254 static HANDLE select_thread = NULL;
1255 static HANDLE select_finished_event = NULL;
1256 static HANDLE select_standby_event = NULL;
1257 static SOCKET select_wakeup_socket = -1;
1258 static SOCKET select_send_socket = -1;
1259 static struct timeval select_timeout;
1262 int writePipePos = 0;
1264 HANDLE handle_array[FD_SETSIZE + 2];
1265 int returncode = -1;
1266 int returnedpos = 0;
1268 struct GNUNET_CONTAINER_SList *handles_read;
1269 struct GNUNET_CONTAINER_SList *handles_write;
1270 struct GNUNET_CONTAINER_SList *handles_except;
1284 /* TODO: Make this growable */
1285 struct GNUNET_DISK_FileHandle *readArray[50];
1293 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1296 struct GNUNET_CONTAINER_SList_Iterator t;
1298 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1299 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1300 GNUNET_CONTAINER_slist_next (&t))
1302 struct GNUNET_DISK_FileHandle *fh;
1304 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1306 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1315 nfds = GNUNET_MAX (nfds, wfds->nsds);
1317 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1322 nfds = GNUNET_MAX (nfds, efds->nsds);
1324 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1329 (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1336 LOG (GNUNET_ERROR_TYPE_ERROR,
1338 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1342 tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1344 1000 * (timeout.rel_value -
1345 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1346 return select (nfds, (rfds != NULL) ? &rfds->sds : NULL,
1347 (wfds != NULL) ? &wfds->sds : NULL,
1348 (efds != NULL) ? &efds->sds : NULL,
1349 (timeout.rel_value ==
1350 GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ? NULL : &tv);
1353 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1354 /* calculate how long we need to wait in milliseconds */
1355 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1356 ms_total = INFINITE;
1359 ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1360 if (timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value > 0xFFFFFFFFLL - 1)
1363 ms_total = 0xFFFFFFFF - 1;
1366 /* select() may be used as a portable way to sleep */
1367 if (!(rfds || wfds || efds))
1373 if (select_thread == NULL)
1375 SOCKET select_listening_socket = -1;
1376 struct sockaddr_in s_in;
1381 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1382 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1384 select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1386 select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1389 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1390 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1392 alen = sizeof (s_in);
1393 s_in.sin_family = AF_INET;
1395 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1396 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1397 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1398 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1399 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1400 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1402 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1403 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1405 res = listen (select_listening_socket, SOMAXCONN);
1406 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1408 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1409 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1411 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1413 closesocket (select_listening_socket);
1415 sp.wakeup = select_finished_event;
1416 sp.standby = select_standby_event;
1417 sp.wakeup_socket = select_wakeup_socket;
1419 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1423 handles_read = GNUNET_CONTAINER_slist_create ();
1424 handles_write = GNUNET_CONTAINER_slist_create ();
1425 handles_except = GNUNET_CONTAINER_slist_create ();
1436 FD_COPY (&rfds->sds, &aread);
1438 FD_COPY (&rfds->sds, &bread);
1443 FD_COPY (&wfds->sds, &awrite);
1445 FD_COPY (&wfds->sds, &bwrite);
1450 FD_COPY (&efds->sds, &aexcept);
1452 FD_COPY (&efds->sds, &bexcept);
1456 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1457 By profiling we detected that to be true in 90% of the cases.
1460 /* Do the select now */
1461 select_timeout.tv_sec = 0;
1462 select_timeout.tv_usec = 0;
1464 /* Copy all the writes to the except, so we can detect connect() errors */
1465 for (i = 0; i < awrite.fd_count; i++)
1466 FD_SET (awrite.fd_array[i], &aexcept);
1467 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1468 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1469 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1472 if (selectret == -1)
1474 /* Throw an error early on, while we still have the context. */
1475 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1476 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1480 /* Check aexcept, add its contents to awrite
1481 This is technically wrong (aexcept might have its own descriptors), we should
1482 have checked that descriptors were in awrite originally before re-adding them from
1483 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1484 for (i = 0; i < aexcept.fd_count; i++)
1485 FD_SET (aexcept.fd_array[i], &awrite);
1487 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1488 /* Sadly, it means code duplication :( */
1489 if ((selectret > 0) || (ms_total == 0))
1492 if (rfds && read_handles)
1494 struct GNUNET_CONTAINER_SList_Iterator i;
1497 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1498 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1499 GNUNET_CONTAINER_slist_next (&i), c++)
1501 struct GNUNET_DISK_FileHandle *fh;
1503 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1504 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1510 DWORD waitstatus = 0;
1511 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1512 error = GetLastError ();
1513 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1514 c, fh->h, bret, waitstatus, error);
1517 /* TODO: either add more errors to this condition, or eliminate it
1518 * entirely (failed to peek -> pipe is in serious trouble, should
1519 * be selected as readable).
1521 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1524 else if (waitstatus <= 0)
1526 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1527 fh, sizeof (struct GNUNET_DISK_FileHandle));
1529 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1534 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1535 fh, sizeof (struct GNUNET_DISK_FileHandle));
1540 if (wfds && write_handles)
1542 LOG (GNUNET_ERROR_TYPE_DEBUG,
1543 "Adding the write ready event to the array as %d\n", nhandles);
1544 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1545 retcode += write_handles;
1547 if (efds && ex_handles)
1549 struct GNUNET_CONTAINER_SList_Iterator i;
1551 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1552 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1553 GNUNET_CONTAINER_slist_next (&i))
1555 struct GNUNET_DISK_FileHandle *fh;
1558 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1559 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1561 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1563 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1564 fh, sizeof (struct GNUNET_DISK_FileHandle));
1570 /* Add our select() result.*/
1572 retcode += selectret;
1576 GNUNET_NETWORK_fdset_zero (rfds);
1577 if (selectret != -1)
1578 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1579 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1583 GNUNET_NETWORK_fdset_zero (wfds);
1584 if (selectret != -1)
1585 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1586 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1590 GNUNET_NETWORK_fdset_zero (efds);
1591 if (selectret != -1)
1592 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1593 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1595 GNUNET_CONTAINER_slist_destroy (handles_read);
1596 GNUNET_CONTAINER_slist_destroy (handles_write);
1597 GNUNET_CONTAINER_slist_destroy (handles_except);
1599 if (selectret == -1)
1604 /* If we got this far, use slower implementation that is able to do a waiting select
1605 on both sockets and pipes simultaneously */
1607 /* Events for pipes */
1608 if (!hEventReadReady)
1609 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1610 if (!hEventPipeWrite)
1611 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1627 FD_COPY (&rfds->sds, &aread);
1629 FD_COPY (&rfds->sds, &bread);
1634 FD_COPY (&wfds->sds, &awrite);
1636 FD_COPY (&wfds->sds, &bwrite);
1641 FD_COPY (&efds->sds, &aexcept);
1643 FD_COPY (&efds->sds, &bexcept);
1646 /* We will first Add the PIPES to the events */
1648 if (rfds && read_handles)
1650 struct GNUNET_CONTAINER_SList_Iterator i;
1652 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1653 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1654 GNUNET_CONTAINER_slist_next (&i))
1656 struct GNUNET_DISK_FileHandle *fh;
1658 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1660 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1662 /* Read zero bytes to check the status of the pipe */
1663 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1665 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1667 DWORD error_code = GetLastError ();
1669 if (error_code == ERROR_IO_PENDING)
1671 LOG (GNUNET_ERROR_TYPE_DEBUG,
1672 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1674 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1675 readArray[readPipes++] = fh;
1679 LOG (GNUNET_ERROR_TYPE_DEBUG,
1680 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1681 handle_array[nhandles++] = hEventReadReady;
1682 readArray[readPipes++] = fh;
1687 LOG (GNUNET_ERROR_TYPE_DEBUG,
1688 "Adding the read ready event to the array as %d\n", nhandles);
1689 handle_array[nhandles++] = hEventReadReady;
1690 readArray[readPipes++] = fh;
1695 GNUNET_CONTAINER_slist_add (handles_read,
1696 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1697 fh, sizeof (struct GNUNET_DISK_FileHandle));
1701 if (wfds && write_handles)
1703 LOG (GNUNET_ERROR_TYPE_DEBUG,
1704 "Adding the write ready event to the array as %d\n", nhandles);
1705 handle_array[nhandles++] = hEventPipeWrite;
1706 writePipePos = nhandles;
1708 if (efds && ex_handles)
1710 struct GNUNET_CONTAINER_SList_Iterator i;
1712 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1713 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1714 GNUNET_CONTAINER_slist_next (&i))
1716 struct GNUNET_DISK_FileHandle *fh;
1719 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1721 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1723 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1725 GNUNET_CONTAINER_slist_add (handles_except,
1726 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1728 sizeof (struct GNUNET_DISK_FileHandle));
1738 LOG (GNUNET_ERROR_TYPE_DEBUG,
1739 "Adding the socket event to the array as %d\n", nhandles);
1740 handle_array[nhandles++] = select_finished_event;
1741 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1745 select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1746 select_timeout.tv_usec = 1000 * (timeout.rel_value -
1747 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1748 sp.tv = &select_timeout;
1750 FD_SET (select_wakeup_socket, &aread);
1754 /* Failed connections cause sockets to be set in errorfds on W32,
1755 * but on POSIX it should set them in writefds.
1756 * First copy all awrite sockets to aexcept, later we'll
1757 * check aexcept and set its contents in awrite as well
1758 * Sockets are also set in errorfds when OOB data is available,
1759 * but we don't use OOB data.
1761 for (i = 0; i < awrite.fd_count; i++)
1762 FD_SET (awrite.fd_array[i], &aexcept);
1763 ResetEvent (select_finished_event);
1764 SetEvent (select_standby_event);
1767 handle_array[nhandles] = NULL;
1768 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n",
1769 nfds, nhandles, (unsigned long long) ms_total);
1773 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1774 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1779 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1780 returncode = WAIT_TIMEOUT;
1784 /* Shouldn't come this far. If it does - investigate. */
1790 /* Don't wake up select-thread when delay is 0, it should return immediately
1791 * and wake up by itself.
1794 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1795 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1796 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1801 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1804 /* Check aexcept, add its contents to awrite */
1805 for (i = 0; i < aexcept.fd_count; i++)
1806 FD_SET (aexcept.fd_array[i], &awrite);
1809 returnedpos = returncode - WAIT_OBJECT_0;
1810 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1812 if (nhandles && (returnedpos < nhandles))
1817 retcode += sp.status;
1819 if ((writePipePos != -1) && (returnedpos < writePipePos))
1821 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1822 retcode += write_handles;
1823 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1825 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1826 /* We have some pipes ready for read. */
1827 if (returnedpos < readPipes)
1829 for (i = 0; i < readPipes; i++)
1837 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1838 error = GetLastError ();
1839 LOG (GNUNET_ERROR_TYPE_DEBUG,
1840 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1841 i, readArray[i]->h, bret, waitstatus, error);
1844 /* TODO: either add more errors to this condition, or eliminate it
1845 * entirely (failed to peek -> pipe is in serious trouble, should
1846 * be selected as readable).
1848 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1851 else if (waitstatus <= 0)
1853 GNUNET_CONTAINER_slist_add (handles_read,
1854 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1856 sizeof (struct GNUNET_DISK_FileHandle));
1858 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1859 readArray[i], readArray[i]->h);
1863 if (!nhandles || (returnedpos >= nhandles))
1864 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1867 struct GNUNET_CONTAINER_SList_Iterator t;
1869 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1870 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1871 GNUNET_CONTAINER_slist_next (&t))
1873 struct GNUNET_DISK_FileHandle *fh;
1875 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1877 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1882 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1883 GNUNET_NETWORK_fdset_zero (rfds);
1884 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1885 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1886 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1890 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1891 GNUNET_NETWORK_fdset_zero (wfds);
1892 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1893 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1894 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1898 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1899 GNUNET_NETWORK_fdset_zero (efds);
1900 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1901 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1902 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1904 GNUNET_CONTAINER_slist_destroy (handles_read);
1905 GNUNET_CONTAINER_slist_destroy (handles_write);
1906 GNUNET_CONTAINER_slist_destroy (handles_except);
1910 struct GNUNET_CONTAINER_SList_Iterator t;
1912 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1913 for (i = 0; i < rfds->sds.fd_count; i++)
1915 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1917 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1918 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1919 GNUNET_CONTAINER_slist_next (&t))
1921 struct GNUNET_DISK_FileHandle *fh;
1923 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1925 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1930 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1931 for (i = 0; i < wfds->sds.fd_count; i++)
1933 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1938 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1939 for (i = 0; i < efds->sds.fd_count; i++)
1941 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1944 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1946 if (nhandles && (returnedpos < nhandles))
1953 /* end of network.c */