2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file util/network.c
23 * @brief basic, low-level networking interface
25 * @author Christian Grothoff
29 #include "gnunet_util_lib.h"
31 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
32 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
33 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
35 #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
38 #ifndef INVALID_SOCKET
39 #define INVALID_SOCKET -1
43 struct GNUNET_NETWORK_Handle
52 * Address family / domain.
62 * Number of bytes in addr.
67 * Address we were bound to, or NULL.
69 struct sockaddr *addr;
75 * Test if the given protocol family is supported by this system.
77 * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
78 * @return #GNUNET_OK if the PF is supported
81 GNUNET_NETWORK_test_pf (int pf)
85 s = socket (pf, SOCK_STREAM, 0);
88 if (EAFNOSUPPORT == errno)
90 fprintf (stderr, "Failed to create test socket: %s\n", STRERROR (errno));
103 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
104 * shorten it to an acceptable length while keeping it unique
105 * and making sure it remains a valid filename (if possible).
107 * @param unixpath long path, will be freed (or same pointer returned
108 * with moved 0-termination).
109 * @return shortened unixpath, NULL on error
112 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
114 struct sockaddr_un dummy;
117 struct GNUNET_HashCode sh;
118 struct GNUNET_CRYPTO_HashAsciiEncoded ae;
121 upm = sizeof (dummy.sun_path);
122 slen = strlen (unixpath);
124 return unixpath; /* no shortening required */
125 GNUNET_CRYPTO_hash (unixpath, slen, &sh);
126 while (sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) +
127 strlen (unixpath) >= upm)
129 if (NULL == (end = strrchr (unixpath, '/')))
131 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
132 _("Unable to shorten unix path `%s' while keeping name unique\n"),
134 GNUNET_free (unixpath);
139 GNUNET_CRYPTO_hash_to_enc (&sh, &ae);
140 strcat (unixpath, (char*) ae.encoding);
146 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
151 * Set if a socket should use blocking or non-blocking IO.
154 * @param doBlock blocking mode
155 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
158 GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
165 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
168 SetErrnoFromWinsockError (WSAGetLastError ());
169 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
170 return GNUNET_SYSERR;
176 int flags = fcntl (fd->fd, F_GETFL);
181 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
182 return GNUNET_SYSERR;
185 flags &= ~O_NONBLOCK;
189 if (0 != fcntl (fd->fd, F_SETFL, flags))
192 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
193 return GNUNET_SYSERR;
201 * Make a socket non-inheritable to child processes
203 * @param h the socket to make non-inheritable
204 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
205 * @warning Not implemented on Windows
208 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
212 i = fcntl (h->fd, F_GETFD);
214 return GNUNET_SYSERR;
215 if (i == (i | FD_CLOEXEC))
218 if (fcntl (h->fd, F_SETFD, i) < 0)
219 return GNUNET_SYSERR;
223 b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
226 SetErrnoFromWinsockError (WSAGetLastError ());
227 return GNUNET_SYSERR;
236 * The MSG_NOSIGNAL equivalent on Mac OS X
238 * @param h the socket to make non-delaying
241 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
246 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE,
247 (const void *) &abs_value,
249 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
255 * Disable delays when sending data via the socket.
256 * (GNUnet makes sure that messages are as big as
259 * @param h the socket to make non-delaying
262 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
267 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
268 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
270 const char *abs_value = "1";
273 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY,
274 (const void *) abs_value,
276 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
282 * Perform proper canonical initialization for a network handle.
283 * Set it to non-blocking, make it non-inheritable to child
284 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
285 * stream socket) and check that it is smaller than FD_SETSIZE.
287 * @param h socket to initialize
288 * @param af address family of the socket
289 * @param type socket type
290 * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
291 * failed and the handle was destroyed
294 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
299 if (h->fd == INVALID_SOCKET)
302 SetErrnoFromWinsockError (WSAGetLastError ());
305 return GNUNET_SYSERR;
308 if (h->fd >= FD_SETSIZE)
310 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
312 return GNUNET_SYSERR;
315 if (GNUNET_OK != socket_set_inheritable (h))
316 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
317 "socket_set_inheritable");
319 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
322 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
323 return GNUNET_SYSERR;
326 socket_set_nosigpipe (h);
328 if ( (type == SOCK_STREAM)
333 socket_set_nodelay (h);
339 * accept a new connection on a socket
341 * @param desc bound socket
342 * @param address address of the connecting peer, may be NULL
343 * @param address_len length of address
344 * @return client socket
346 struct GNUNET_NETWORK_Handle *
347 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
348 struct sockaddr *address, socklen_t * address_len)
350 struct GNUNET_NETWORK_Handle *ret;
352 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
355 struct sockaddr name;
356 socklen_t namelen = sizeof (name);
357 int gsn = getsockname (desc->fd, &name, &namelen);
360 LOG (GNUNET_ERROR_TYPE_DEBUG, "Accepting connection on `%s'\n",
361 GNUNET_a2s (&name, namelen));
364 ret->fd = accept (desc->fd, address, address_len);
365 if (GNUNET_OK != initialize_network_handle (ret,
366 (NULL != address) ? address->sa_family : desc->af,
374 * Bind a socket to a particular address.
376 * @param desc socket to bind
377 * @param address address to be bound
378 * @param address_len length of address
379 * @param flags flags affecting bind behaviour
380 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
383 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
384 const struct sockaddr *address,
385 socklen_t address_len,
395 if (desc->af == AF_INET6)
396 if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY,
399 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
407 /* This is required here for TCP sockets, but only on UNIX */
408 if ((SOCK_STREAM == desc->type)
409 && (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))))
410 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
415 if (address->sa_family == AF_UNIX && (flags & GNUNET_BIND_EXCLUSIVE) == 0)
417 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
419 (void) unlink (un->sun_path);
423 ret = bind (desc->fd, address, address_len);
425 if (SOCKET_ERROR == ret)
426 SetErrnoFromWinsockError (WSAGetLastError ());
429 return GNUNET_SYSERR;
432 desc->addr = GNUNET_malloc (address_len);
433 memcpy (desc->addr, address, address_len);
434 desc->addrlen = address_len;
445 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
448 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
456 ret = closesocket (desc->fd);
457 error = WSAGetLastError ();
458 SetErrnoFromWinsockError (error);
459 LOG (GNUNET_ERROR_TYPE_DEBUG,
460 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
463 ret = close (desc->fd);
467 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
469 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
471 if (0 != unlink (un->sun_path))
472 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
476 GNUNET_free_non_null (desc->addr);
478 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
483 * Box a native socket (and check that it is a socket).
485 * @param fd socket to box
486 * @return NULL on error (including not supported on target platform)
488 struct GNUNET_NETWORK_Handle *
489 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
491 struct GNUNET_NETWORK_Handle *ret;
495 /* FIXME: Find a better call to check that FD is valid */
496 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
497 return NULL; /* invalid FD */
498 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
503 if (fcntl (fd, F_GETFD) < 0)
504 return NULL; /* invalid FD */
505 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
514 * Connect a socket to some remote address.
517 * @param address peer address
518 * @param address_len length of address
519 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
522 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
523 const struct sockaddr *address,
524 socklen_t address_len)
528 ret = connect (desc->fd, address, address_len);
531 if (SOCKET_ERROR == ret)
533 SetErrnoFromWinsockError (WSAGetLastError ());
534 if (errno == EWOULDBLOCK)
538 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
546 * @param level protocol level of the option
547 * @param optname identifier of the option
548 * @param optval options
549 * @param optlen length of optval
550 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
553 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
554 int level, int optname, void *optval,
559 ret = getsockopt (desc->fd, level, optname, optval, optlen);
562 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
563 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
565 else if (SOCKET_ERROR == ret)
566 SetErrnoFromWinsockError (WSAGetLastError ());
568 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
576 * @param backlog length of the listen queue
577 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
580 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
585 ret = listen (desc->fd, backlog);
588 if (SOCKET_ERROR == ret)
589 SetErrnoFromWinsockError (WSAGetLastError ());
592 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
597 * How much data is available to be read on this descriptor?
600 * @returns #GNUNET_NO if no data is available, or on error!
603 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
608 /* How much is there to be read? */
612 error = ioctl (desc->fd, FIONREAD, &pending);
614 return (ssize_t) pending;
619 error = ioctlsocket (desc->fd, FIONREAD, &pending);
620 if (error != SOCKET_ERROR)
621 return (ssize_t) pending;
628 * Read data from a socket (always non-blocking).
631 * @param buffer buffer
632 * @param length length of buffer
633 * @param src_addr either the source to recv from, or all zeroes
634 * to be filled in by recvfrom
635 * @param addrlen length of the addr
638 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
639 void *buffer, size_t length,
640 struct sockaddr *src_addr, socklen_t *addrlen)
648 flags |= MSG_DONTWAIT;
651 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
653 if (SOCKET_ERROR == ret)
654 SetErrnoFromWinsockError (WSAGetLastError ());
661 * Read data from a connected socket (always non-blocking).
664 * @param buffer buffer
665 * @param length length of buffer
668 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
669 void *buffer, size_t length)
677 flags |= MSG_DONTWAIT;
679 ret = recv (desc->fd, buffer, length, flags);
681 if (SOCKET_ERROR == ret)
682 SetErrnoFromWinsockError (WSAGetLastError ());
689 * Send data (always non-blocking).
692 * @param buffer data to send
693 * @param length size of the buffer
694 * @return number of bytes sent, GNUNET_SYSERR on error
697 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
698 const void *buffer, size_t length)
706 flags |= MSG_DONTWAIT;
710 flags |= MSG_NOSIGNAL;
713 ret = send (desc->fd, buffer, length, flags);
716 if (SOCKET_ERROR == ret)
717 SetErrnoFromWinsockError (WSAGetLastError ());
725 * Send data to a particular destination (always non-blocking).
726 * This function only works for UDP sockets.
729 * @param message data to send
730 * @param length size of the data
731 * @param dest_addr destination address
732 * @param dest_len length of address
733 * @return number of bytes sent, #GNUNET_SYSERR on error
736 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
737 const void *message, size_t length,
738 const struct sockaddr * dest_addr,
747 flags |= MSG_DONTWAIT;
750 flags |= MSG_NOSIGNAL;
752 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
754 if (SOCKET_ERROR == ret)
755 SetErrnoFromWinsockError (WSAGetLastError ());
765 * @param level protocol level of the option
766 * @param option_name option identifier
767 * @param option_value value to set
768 * @param option_len size of option_value
769 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
772 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
773 int option_name, const void *option_value,
774 socklen_t option_len)
778 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
780 if (SOCKET_ERROR == ret)
781 SetErrnoFromWinsockError (WSAGetLastError ());
783 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
788 * Create a new socket. Configure it for non-blocking IO and
789 * mark it as non-inheritable to child processes (set the
790 * close-on-exec flag).
792 * @param domain domain of the socket
793 * @param type socket type
794 * @param protocol network protocol
795 * @return new socket, NULL on error
797 struct GNUNET_NETWORK_Handle *
798 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
800 struct GNUNET_NETWORK_Handle *ret;
802 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
803 ret->fd = socket (domain, type, protocol);
805 initialize_network_handle (ret, domain, type))
812 * Shut down socket operations
814 * @param how type of shutdown
815 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
818 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
822 ret = shutdown (desc->fd, how);
825 SetErrnoFromWinsockError (WSAGetLastError ());
827 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
832 * Disable the "CORK" feature for communication with the given socket,
833 * forcing the OS to immediately flush the buffer on transmission
834 * instead of potentially buffering multiple messages. Essentially
835 * reduces the OS send buffers to zero.
838 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
841 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
850 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
852 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
855 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
857 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
863 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
864 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
867 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
868 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
870 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
880 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
885 GNUNET_CONTAINER_slist_clear (fds->handles);
891 * Add a socket to the FD set
894 * @param desc socket to add
897 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
898 const struct GNUNET_NETWORK_Handle *desc)
900 FD_SET (desc->fd, &fds->sds);
901 if (desc->fd + 1 > fds->nsds)
902 fds->nsds = desc->fd + 1;
907 * Check whether a socket is part of the fd set
911 * @return 0 if the FD is not set
914 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
915 const struct GNUNET_NETWORK_Handle *desc)
917 return FD_ISSET (desc->fd, &fds->sds);
922 * Add one fd set to another
924 * @param dst the fd set to add to
925 * @param src the fd set to add from
928 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
929 const struct GNUNET_NETWORK_FDSet *src)
934 for (nfds = src->nsds; nfds > 0; nfds--)
935 if (FD_ISSET (nfds, &src->sds))
938 FD_SET (nfds, &dst->sds);
939 if (nfds + 1 > dst->nsds)
940 dst->nsds = nfds + 1;
943 /* This is MinGW32-specific implementation that relies on the code that
944 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
945 * that fd being added is not already in the set.
946 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
949 for (i = 0; i < src->sds.fd_count; i++)
950 FD_SET (src->sds.fd_array[i], &dst->sds);
951 if (src->nsds > dst->nsds)
952 dst->nsds = src->nsds;
954 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
960 * Copy one fd set to another
962 * @param to destination
966 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
967 const struct GNUNET_NETWORK_FDSet *from)
969 FD_COPY (&from->sds, &to->sds);
970 to->nsds = from->nsds;
973 GNUNET_CONTAINER_slist_clear (to->handles);
974 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
980 * Return file descriptor for this network handle
982 * @param desc wrapper to process
983 * @return POSIX file descriptor
986 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
993 * Return sockaddr for this network handle
995 * @param desc wrapper to process
999 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1006 * Return sockaddr length for this network handle
1008 * @param desc wrapper to process
1009 * @return socklen_t for sockaddr
1012 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1014 return desc->addrlen;
1019 * Copy a native fd set
1021 * @param to destination
1022 * @param from native source set
1023 * @param nfds the biggest socket number in from + 1
1026 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1027 const fd_set * from, int nfds)
1029 FD_COPY (from, &to->sds);
1035 * Set a native fd in a set
1037 * @param to destination
1038 * @param nfd native FD to set
1041 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1043 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1044 FD_SET (nfd, &to->sds);
1045 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1050 * Test native fd in a set
1052 * @param to set to test, NULL for empty set
1053 * @param nfd native FD to test, or -1 for none
1054 * @return #GNUNET_YES if FD is set in the set
1057 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1060 if ((nfd == -1) || (to == NULL))
1062 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1067 * Add a file handle to the fd set
1069 * @param h the file handle to add
1072 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1073 const struct GNUNET_DISK_FileHandle *h)
1076 GNUNET_CONTAINER_slist_add (fds->handles,
1077 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1078 sizeof (struct GNUNET_DISK_FileHandle));
1083 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1084 FD_SET (fd, &fds->sds);
1085 if (fd + 1 > fds->nsds)
1093 * Check if a file handle is part of an fd set
1095 * @param h file handle
1096 * @return #GNUNET_YES if the file handle is part of the set
1099 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1100 const struct GNUNET_DISK_FileHandle *h)
1104 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1106 GNUNET_DISK_FileHandle));
1108 return FD_ISSET (h->fd, &fds->sds);
1114 * Checks if two fd sets overlap
1115 * @param fds1 first fd set
1116 * @param fds2 second fd set
1117 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1120 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1121 const struct GNUNET_NETWORK_FDSet *fds2)
1127 if (nfds > fds2->nsds)
1132 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1136 struct GNUNET_CONTAINER_SList_Iterator it;
1137 struct GNUNET_DISK_FileHandle *h;
1141 /*This code is somewhat hacky, we are not supposed to know what's
1142 * inside of fd_set; also the O(n^2) is really bad... */
1144 for (i = 0; i < fds1->sds.fd_count; i++)
1146 for (j = 0; j < fds2->sds.fd_count; j++)
1148 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1152 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1153 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1156 struct GNUNET_CONTAINER_SList_Iterator t;
1158 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1161 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1163 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1164 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1165 GNUNET_CONTAINER_slist_next (&t))
1167 struct GNUNET_DISK_FileHandle *fh;
1169 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1171 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1174 if (GNUNET_CONTAINER_slist_contains
1175 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1179 GNUNET_CONTAINER_slist_next (&it);
1189 * @return a new fd set
1191 struct GNUNET_NETWORK_FDSet *
1192 GNUNET_NETWORK_fdset_create ()
1194 struct GNUNET_NETWORK_FDSet *fds;
1196 fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1198 fds->handles = GNUNET_CONTAINER_slist_create ();
1200 GNUNET_NETWORK_fdset_zero (fds);
1206 * Releases the associated memory of an fd set
1211 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1214 GNUNET_CONTAINER_slist_destroy (fds->handles);
1220 struct _select_params
1228 SOCKET wakeup_socket;
1233 _selector (LPVOID p)
1235 struct _select_params *sp = p;
1239 WaitForSingleObject (sp->standby, INFINITE);
1240 ResetEvent (sp->standby);
1241 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1242 if (FD_ISSET (sp->wakeup_socket, sp->r))
1244 FD_CLR (sp->wakeup_socket, sp->r);
1247 SetEvent (sp->wakeup);
1255 * Check if sockets or pipes meet certain conditions
1256 * @param rfds set of sockets or pipes to be checked for readability
1257 * @param wfds set of sockets or pipes to be checked for writability
1258 * @param efds set of sockets or pipes to be checked for exceptions
1259 * @param timeout relative value when to return
1260 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1263 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1264 struct GNUNET_NETWORK_FDSet *wfds,
1265 struct GNUNET_NETWORK_FDSet *efds,
1266 const struct GNUNET_TIME_Relative timeout)
1272 int read_handles = 0;
1273 int write_handles = 0;
1277 uint64_t mcs_total = 0;
1278 DWORD ms_rounded = 0;
1282 static HANDLE hEventPipeWrite = 0;
1283 static HANDLE hEventReadReady = 0;
1285 static struct _select_params sp;
1286 static HANDLE select_thread = NULL;
1287 static HANDLE select_finished_event = NULL;
1288 static HANDLE select_standby_event = NULL;
1289 static SOCKET select_wakeup_socket = -1;
1290 static SOCKET select_send_socket = -1;
1291 static struct timeval select_timeout;
1294 int writePipePos = 0;
1296 HANDLE handle_array[FD_SETSIZE + 2];
1297 int returncode = -1;
1298 int returnedpos = 0;
1300 struct GNUNET_CONTAINER_SList *handles_read;
1301 struct GNUNET_CONTAINER_SList *handles_write;
1302 struct GNUNET_CONTAINER_SList *handles_except;
1316 /* TODO: Make this growable */
1317 struct GNUNET_DISK_FileHandle *readArray[50];
1325 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1328 struct GNUNET_CONTAINER_SList_Iterator t;
1330 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1331 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1332 GNUNET_CONTAINER_slist_next (&t))
1334 struct GNUNET_DISK_FileHandle *fh;
1336 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1338 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1347 nfds = GNUNET_MAX (nfds, wfds->nsds);
1349 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1354 nfds = GNUNET_MAX (nfds, efds->nsds);
1356 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1361 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1368 LOG (GNUNET_ERROR_TYPE_ERROR,
1370 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1374 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1376 (timeout.rel_value_us -
1377 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1378 return select (nfds,
1379 (NULL != rfds) ? &rfds->sds : NULL,
1380 (NULL != wfds) ? &wfds->sds : NULL,
1381 (NULL != efds) ? &efds->sds : NULL,
1382 (timeout.rel_value_us ==
1383 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1386 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1387 /* calculate how long we need to wait in microseconds */
1388 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1390 mcs_total = INFINITE;
1391 ms_rounded = INFINITE;
1395 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1396 ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1397 if (mcs_total > 0 && ms_rounded == 0)
1400 /* select() may be used as a portable way to sleep */
1401 if (!(rfds || wfds || efds))
1407 if (NULL == select_thread)
1409 SOCKET select_listening_socket = -1;
1410 struct sockaddr_in s_in;
1415 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1416 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1418 select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1420 select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1423 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1424 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1426 alen = sizeof (s_in);
1427 s_in.sin_family = AF_INET;
1429 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1430 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1431 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1432 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1433 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1434 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1436 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1437 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1439 res = listen (select_listening_socket, SOMAXCONN);
1440 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1442 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1443 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1445 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1447 closesocket (select_listening_socket);
1449 sp.wakeup = select_finished_event;
1450 sp.standby = select_standby_event;
1451 sp.wakeup_socket = select_wakeup_socket;
1453 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1457 handles_read = GNUNET_CONTAINER_slist_create ();
1458 handles_write = GNUNET_CONTAINER_slist_create ();
1459 handles_except = GNUNET_CONTAINER_slist_create ();
1470 FD_COPY (&rfds->sds, &aread);
1472 FD_COPY (&rfds->sds, &bread);
1477 FD_COPY (&wfds->sds, &awrite);
1479 FD_COPY (&wfds->sds, &bwrite);
1484 FD_COPY (&efds->sds, &aexcept);
1486 FD_COPY (&efds->sds, &bexcept);
1490 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1491 By profiling we detected that to be true in 90% of the cases.
1494 /* Do the select now */
1495 select_timeout.tv_sec = 0;
1496 select_timeout.tv_usec = 0;
1498 /* Copy all the writes to the except, so we can detect connect() errors */
1499 for (i = 0; i < awrite.fd_count; i++)
1500 FD_SET (awrite.fd_array[i], &aexcept);
1501 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1502 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1503 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1506 if (selectret == -1)
1508 /* Throw an error early on, while we still have the context. */
1509 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1510 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1514 /* Check aexcept, add its contents to awrite
1515 This is technically wrong (aexcept might have its own descriptors), we should
1516 have checked that descriptors were in awrite originally before re-adding them from
1517 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1518 for (i = 0; i < aexcept.fd_count; i++)
1519 FD_SET (aexcept.fd_array[i], &awrite);
1521 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1522 /* Sadly, it means code duplication :( */
1523 if ((selectret > 0) || (mcs_total == 0))
1526 if (rfds && read_handles)
1528 struct GNUNET_CONTAINER_SList_Iterator i;
1531 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1532 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1533 GNUNET_CONTAINER_slist_next (&i), c++)
1535 struct GNUNET_DISK_FileHandle *fh;
1537 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1538 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1544 DWORD waitstatus = 0;
1545 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1546 error = GetLastError ();
1547 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1548 c, fh->h, bret, waitstatus, error);
1551 /* TODO: either add more errors to this condition, or eliminate it
1552 * entirely (failed to peek -> pipe is in serious trouble, should
1553 * be selected as readable).
1555 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1558 else if (waitstatus <= 0)
1560 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1561 fh, sizeof (struct GNUNET_DISK_FileHandle));
1563 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1568 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1569 fh, sizeof (struct GNUNET_DISK_FileHandle));
1574 if (wfds && write_handles)
1576 LOG (GNUNET_ERROR_TYPE_DEBUG,
1577 "Adding the write ready event to the array as %d\n", nhandles);
1578 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1579 retcode += write_handles;
1581 if (efds && ex_handles)
1583 struct GNUNET_CONTAINER_SList_Iterator i;
1585 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1586 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1587 GNUNET_CONTAINER_slist_next (&i))
1589 struct GNUNET_DISK_FileHandle *fh;
1592 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1593 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1595 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1597 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1598 fh, sizeof (struct GNUNET_DISK_FileHandle));
1604 /* Add our select() result.*/
1606 retcode += selectret;
1610 GNUNET_NETWORK_fdset_zero (rfds);
1611 if (selectret != -1)
1612 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1613 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1617 GNUNET_NETWORK_fdset_zero (wfds);
1618 if (selectret != -1)
1619 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1620 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1624 GNUNET_NETWORK_fdset_zero (efds);
1625 if (selectret != -1)
1626 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1627 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1629 GNUNET_CONTAINER_slist_destroy (handles_read);
1630 GNUNET_CONTAINER_slist_destroy (handles_write);
1631 GNUNET_CONTAINER_slist_destroy (handles_except);
1633 if (selectret == -1)
1638 /* If we got this far, use slower implementation that is able to do a waiting select
1639 on both sockets and pipes simultaneously */
1641 /* Events for pipes */
1642 if (!hEventReadReady)
1643 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1644 if (!hEventPipeWrite)
1645 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1661 FD_COPY (&rfds->sds, &aread);
1663 FD_COPY (&rfds->sds, &bread);
1668 FD_COPY (&wfds->sds, &awrite);
1670 FD_COPY (&wfds->sds, &bwrite);
1675 FD_COPY (&efds->sds, &aexcept);
1677 FD_COPY (&efds->sds, &bexcept);
1680 /* We will first Add the PIPES to the events */
1682 if (rfds && read_handles)
1684 struct GNUNET_CONTAINER_SList_Iterator i;
1686 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1687 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1688 GNUNET_CONTAINER_slist_next (&i))
1690 struct GNUNET_DISK_FileHandle *fh;
1692 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1694 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1696 /* Read zero bytes to check the status of the pipe */
1697 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1699 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1701 DWORD error_code = GetLastError ();
1703 if (error_code == ERROR_IO_PENDING)
1705 LOG (GNUNET_ERROR_TYPE_DEBUG,
1706 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1708 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1709 readArray[readPipes++] = fh;
1713 LOG (GNUNET_ERROR_TYPE_DEBUG,
1714 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1715 handle_array[nhandles++] = hEventReadReady;
1716 readArray[readPipes++] = fh;
1721 LOG (GNUNET_ERROR_TYPE_DEBUG,
1722 "Adding the read ready event to the array as %d\n", nhandles);
1723 handle_array[nhandles++] = hEventReadReady;
1724 readArray[readPipes++] = fh;
1729 GNUNET_CONTAINER_slist_add (handles_read,
1730 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1731 fh, sizeof (struct GNUNET_DISK_FileHandle));
1735 if (wfds && write_handles)
1737 LOG (GNUNET_ERROR_TYPE_DEBUG,
1738 "Adding the write ready event to the array as %d\n", nhandles);
1739 handle_array[nhandles++] = hEventPipeWrite;
1740 writePipePos = nhandles;
1742 if (efds && ex_handles)
1744 struct GNUNET_CONTAINER_SList_Iterator i;
1746 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1747 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1748 GNUNET_CONTAINER_slist_next (&i))
1750 struct GNUNET_DISK_FileHandle *fh;
1753 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1755 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1757 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1759 GNUNET_CONTAINER_slist_add (handles_except,
1760 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1762 sizeof (struct GNUNET_DISK_FileHandle));
1772 LOG (GNUNET_ERROR_TYPE_DEBUG,
1773 "Adding the socket event to the array as %d\n",
1775 handle_array[nhandles++] = select_finished_event;
1776 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1780 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1781 select_timeout.tv_usec =(timeout.rel_value_us -
1782 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1783 sp.tv = &select_timeout;
1785 FD_SET (select_wakeup_socket, &aread);
1788 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1793 /* Failed connections cause sockets to be set in errorfds on W32,
1794 * but on POSIX it should set them in writefds.
1795 * First copy all awrite sockets to aexcept, later we'll
1796 * check aexcept and set its contents in awrite as well
1797 * Sockets are also set in errorfds when OOB data is available,
1798 * but we don't use OOB data.
1800 for (i = 0; i < awrite.fd_count; i++)
1801 FD_SET (awrite.fd_array[i], &aexcept);
1802 ResetEvent (select_finished_event);
1803 SetEvent (select_standby_event);
1806 handle_array[nhandles] = NULL;
1807 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
1808 nfds, nhandles, mcs_total);
1812 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
1813 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode);
1817 GNUNET_break (0); /* This branch shouldn't actually be executed...*/
1818 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1819 returncode = WAIT_TIMEOUT;
1823 /* Shouldn't come this far. If it does - investigate. */
1829 /* Don't wake up select-thread when delay is 0, it should return immediately
1830 * and wake up by itself.
1833 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1834 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1835 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1840 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1843 /* Check aexcept, add its contents to awrite */
1844 for (i = 0; i < aexcept.fd_count; i++)
1845 FD_SET (aexcept.fd_array[i], &awrite);
1848 returnedpos = returncode - WAIT_OBJECT_0;
1849 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1851 if (nhandles && (returnedpos < nhandles))
1856 retcode += sp.status;
1858 if ((writePipePos != -1) && (returnedpos < writePipePos))
1860 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1861 retcode += write_handles;
1862 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1864 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1865 /* We have some pipes ready for read. */
1866 if (returnedpos < readPipes)
1868 for (i = 0; i < readPipes; i++)
1876 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1877 error = GetLastError ();
1878 LOG (GNUNET_ERROR_TYPE_DEBUG,
1879 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1880 i, readArray[i]->h, bret, waitstatus, error);
1883 /* TODO: either add more errors to this condition, or eliminate it
1884 * entirely (failed to peek -> pipe is in serious trouble, should
1885 * be selected as readable).
1887 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1890 else if (waitstatus <= 0)
1892 GNUNET_CONTAINER_slist_add (handles_read,
1893 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1895 sizeof (struct GNUNET_DISK_FileHandle));
1897 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1898 readArray[i], readArray[i]->h);
1902 if (!nhandles || (returnedpos >= nhandles))
1903 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1906 struct GNUNET_CONTAINER_SList_Iterator t;
1908 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1909 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1910 GNUNET_CONTAINER_slist_next (&t))
1912 struct GNUNET_DISK_FileHandle *fh;
1914 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1916 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1921 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1922 GNUNET_NETWORK_fdset_zero (rfds);
1923 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1924 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1925 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1929 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1930 GNUNET_NETWORK_fdset_zero (wfds);
1931 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1932 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1933 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1937 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1938 GNUNET_NETWORK_fdset_zero (efds);
1939 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1940 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1941 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1943 GNUNET_CONTAINER_slist_destroy (handles_read);
1944 GNUNET_CONTAINER_slist_destroy (handles_write);
1945 GNUNET_CONTAINER_slist_destroy (handles_except);
1949 struct GNUNET_CONTAINER_SList_Iterator t;
1951 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1952 for (i = 0; i < rfds->sds.fd_count; i++)
1954 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1956 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1957 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1958 GNUNET_CONTAINER_slist_next (&t))
1960 struct GNUNET_DISK_FileHandle *fh;
1962 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1964 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1969 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1970 for (i = 0; i < wfds->sds.fd_count; i++)
1972 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1977 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1978 for (i = 0; i < efds->sds.fd_count; i++)
1980 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1983 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1985 if (nhandles && (returnedpos < nhandles))
1992 /* end of network.c */