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.
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,
242 (const void *) &abs_value,
244 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
250 * Disable delays when sending data via the socket.
251 * (GNUnet makes sure that messages are as big as
254 * @param h the socket to make non-delaying
257 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
262 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
263 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
265 const char *abs_value = "1";
268 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY,
269 (const void *) abs_value,
271 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
277 * Perform proper canonical initialization for a network handle.
278 * Set it to non-blocking, make it non-inheritable to child
279 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
280 * stream socket) and check that it is smaller than FS_SETSIZE.
282 * @param h socket to initialize
283 * @param af address family of the socket
284 * @param type socket type
285 * @return GNUNET_OK on success, GNUNET_SYSERR if initialization
286 * failed and the handle was destroyed
289 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
293 if (h->fd == INVALID_SOCKET)
296 SetErrnoFromWinsockError (WSAGetLastError ());
299 return GNUNET_SYSERR;
302 if (h->fd >= FD_SETSIZE)
304 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
306 return GNUNET_SYSERR;
309 if (GNUNET_OK != socket_set_inheritable (h))
310 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
311 "socket_set_inheritable");
313 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
316 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
317 return GNUNET_SYSERR;
320 socket_set_nosigpipe (h);
322 if ( (type == SOCK_STREAM)
327 socket_set_nodelay (h);
333 * accept a new connection on a socket
335 * @param desc bound socket
336 * @param address address of the connecting peer, may be NULL
337 * @param address_len length of address
338 * @return client socket
340 struct GNUNET_NETWORK_Handle *
341 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
342 struct sockaddr *address, socklen_t * address_len)
344 struct GNUNET_NETWORK_Handle *ret;
346 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
349 struct sockaddr name;
350 socklen_t namelen = sizeof (name);
351 int gsn = getsockname (desc->fd, &name, &namelen);
354 LOG (GNUNET_ERROR_TYPE_DEBUG, "Accepting connection on `%s'\n",
355 GNUNET_a2s (&name, namelen));
358 ret->fd = accept (desc->fd, address, address_len);
359 if (GNUNET_OK != initialize_network_handle (ret,
360 (NULL != address) ? address->sa_family : desc->af,
368 * Bind to a connected socket
370 * @param desc socket to bind
371 * @param address address to be bound
372 * @param address_len length of address
373 * @param flags flags affecting bind behaviour
374 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
377 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
378 const struct sockaddr *address,
379 socklen_t address_len,
389 if (desc->af == AF_INET6)
390 if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY,
393 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
401 /* This is required, and required here, but only on UNIX */
402 if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
403 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
408 if (address->sa_family == AF_UNIX && (flags & GNUNET_BIND_EXCLUSIVE) == 0)
410 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
412 (void) unlink (un->sun_path);
416 ret = bind (desc->fd, address, address_len);
418 if (SOCKET_ERROR == ret)
419 SetErrnoFromWinsockError (WSAGetLastError ());
422 return GNUNET_SYSERR;
425 desc->addr = GNUNET_malloc (address_len);
426 memcpy (desc->addr, address, address_len);
427 desc->addrlen = address_len;
437 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
440 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
448 ret = closesocket (desc->fd);
449 error = WSAGetLastError ();
450 SetErrnoFromWinsockError (error);
451 LOG (GNUNET_ERROR_TYPE_DEBUG,
452 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
455 ret = close (desc->fd);
459 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
461 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
463 if (0 != unlink (un->sun_path))
464 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
468 GNUNET_free_non_null (desc->addr);
470 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
475 * Box a native socket (and check that it is a socket).
477 * @param fd socket to box
478 * @return NULL on error (including not supported on target platform)
480 struct GNUNET_NETWORK_Handle *
481 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
483 struct GNUNET_NETWORK_Handle *ret;
487 /* FIXME: Find a better call to check that FD is valid */
488 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
489 return NULL; /* invalid FD */
490 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
495 if (fcntl (fd, F_GETFD) < 0)
496 return NULL; /* invalid FD */
497 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
508 * @param address peer address
509 * @param address_len length of address
510 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
513 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
514 const struct sockaddr *address,
515 socklen_t address_len)
519 ret = connect (desc->fd, address, address_len);
522 if (SOCKET_ERROR == ret)
524 SetErrnoFromWinsockError (WSAGetLastError ());
525 if (errno == EWOULDBLOCK)
529 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
537 * @param level protocol level of the option
538 * @param optname identifier of the option
539 * @param optval options
540 * @param optlen length of optval
541 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
544 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
545 int level, int optname, void *optval,
550 ret = getsockopt (desc->fd, level, optname, optval, optlen);
553 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
554 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
556 else if (SOCKET_ERROR == ret)
557 SetErrnoFromWinsockError (WSAGetLastError ());
559 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
566 * @param backlog length of the listen queue
567 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
570 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
575 ret = listen (desc->fd, backlog);
578 if (SOCKET_ERROR == ret)
579 SetErrnoFromWinsockError (WSAGetLastError ());
582 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
587 * How much data is available to be read on this descriptor?
589 * Returns GNUNET_NO if no data is available, or on error!
593 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
598 /* How much is there to be read? */
602 error = ioctl (desc->fd, FIONREAD, &pending);
604 return (ssize_t) pending;
609 error = ioctlsocket (desc->fd, FIONREAD, &pending);
610 if (error != SOCKET_ERROR)
611 return (ssize_t) pending;
618 * Read data from a connected socket (always non-blocking).
620 * @param buffer buffer
621 * @param length length of buffer
622 * @param src_addr either the source to recv from, or all zeroes
623 * to be filled in by recvfrom
624 * @param addrlen length of the addr
627 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
628 void *buffer, size_t length,
629 struct sockaddr * src_addr, socklen_t * addrlen)
637 flags |= MSG_DONTWAIT;
640 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
642 if (SOCKET_ERROR == ret)
643 SetErrnoFromWinsockError (WSAGetLastError ());
650 * Read data from a connected socket (always non-blocking).
652 * @param buffer buffer
653 * @param length length of buffer
656 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
657 void *buffer, size_t length)
665 flags |= MSG_DONTWAIT;
667 ret = recv (desc->fd, buffer, length, flags);
669 if (SOCKET_ERROR == ret)
670 SetErrnoFromWinsockError (WSAGetLastError ());
677 * Send data (always non-blocking).
680 * @param buffer data to send
681 * @param length size of the buffer
682 * @return number of bytes sent, GNUNET_SYSERR on error
685 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
686 const void *buffer, size_t length)
694 flags |= MSG_DONTWAIT;
698 flags |= MSG_NOSIGNAL;
701 ret = send (desc->fd, buffer, length, flags);
704 if (SOCKET_ERROR == ret)
705 SetErrnoFromWinsockError (WSAGetLastError ());
713 * Send data to a particular destination (always non-blocking).
714 * This function only works for UDP sockets.
717 * @param message data to send
718 * @param length size of the data
719 * @param dest_addr destination address
720 * @param dest_len length of address
721 * @return number of bytes sent, GNUNET_SYSERR on error
724 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
725 const void *message, size_t length,
726 const struct sockaddr * dest_addr,
735 flags |= MSG_DONTWAIT;
738 flags |= MSG_NOSIGNAL;
740 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
742 if (SOCKET_ERROR == ret)
743 SetErrnoFromWinsockError (WSAGetLastError ());
752 * @param level protocol level of the option
753 * @param option_name option identifier
754 * @param option_value value to set
755 * @param option_len size of option_value
756 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
759 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
760 int option_name, const void *option_value,
761 socklen_t option_len)
765 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
767 if (SOCKET_ERROR == ret)
768 SetErrnoFromWinsockError (WSAGetLastError ());
770 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
775 * Create a new socket. Configure it for non-blocking IO and
776 * mark it as non-inheritable to child processes (set the
777 * close-on-exec flag).
779 * @param domain domain of the socket
780 * @param type socket type
781 * @param protocol network protocol
782 * @return new socket, NULL on error
784 struct GNUNET_NETWORK_Handle *
785 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
787 struct GNUNET_NETWORK_Handle *ret;
789 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
790 ret->fd = socket (domain, type, protocol);
792 initialize_network_handle (ret, domain, type))
799 * Shut down socket operations
801 * @param how type of shutdown
802 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
805 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
809 ret = shutdown (desc->fd, how);
812 SetErrnoFromWinsockError (WSAGetLastError ());
814 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
819 * Disable the "CORK" feature for communication with the given socket,
820 * forcing the OS to immediately flush the buffer on transmission
821 * instead of potentially buffering multiple messages. Essentially
822 * reduces the OS send buffers to zero.
825 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
828 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
837 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
839 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
842 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
844 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
850 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
851 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
854 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
855 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
857 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
866 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
871 GNUNET_CONTAINER_slist_clear (fds->handles);
876 * Add a socket to the FD set
878 * @param desc socket to add
881 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
882 const struct GNUNET_NETWORK_Handle *desc)
884 FD_SET (desc->fd, &fds->sds);
885 if (desc->fd + 1 > fds->nsds)
886 fds->nsds = desc->fd + 1;
891 * Check whether a socket is part of the fd set
894 * @return 0 if the FD is not set
897 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
898 const struct GNUNET_NETWORK_Handle *desc)
900 return FD_ISSET (desc->fd, &fds->sds);
905 * Add one fd set to another
906 * @param dst the fd set to add to
907 * @param src the fd set to add from
910 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
911 const struct GNUNET_NETWORK_FDSet *src)
916 for (nfds = src->nsds; nfds > 0; nfds--)
917 if (FD_ISSET (nfds, &src->sds))
920 FD_SET (nfds, &dst->sds);
921 if (nfds + 1 > dst->nsds)
922 dst->nsds = nfds + 1;
925 /* This is MinGW32-specific implementation that relies on the code that
926 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
927 * that fd being added is not already in the set.
928 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
931 for (i = 0; i < src->sds.fd_count; i++)
932 FD_SET (src->sds.fd_array[i], &dst->sds);
933 if (src->nsds > dst->nsds)
934 dst->nsds = src->nsds;
936 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
942 * Copy one fd set to another
944 * @param to destination
948 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
949 const struct GNUNET_NETWORK_FDSet *from)
951 FD_COPY (&from->sds, &to->sds);
952 to->nsds = from->nsds;
955 GNUNET_CONTAINER_slist_clear (to->handles);
956 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
962 * Return file descriptor for this network handle
964 * @param desc wrapper to process
965 * @return POSIX file descriptor
968 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
974 * Return sockaddr for this network handle
976 * @param desc wrapper to process
980 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
986 * Return sockaddr length for this network handle
988 * @param desc wrapper to process
989 * @return socklen_t for sockaddr
992 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
994 return desc->addrlen;
997 * Copy a native fd set
999 * @param to destination
1000 * @param from native source set
1001 * @param nfds the biggest socket number in from + 1
1004 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1005 const fd_set * from, int nfds)
1007 FD_COPY (from, &to->sds);
1013 * Set a native fd in a set
1015 * @param to destination
1016 * @param nfd native FD to set
1019 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1021 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1022 FD_SET (nfd, &to->sds);
1023 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1028 * Test native fd in a set
1030 * @param to set to test, NULL for empty set
1031 * @param nfd native FD to test, or -1 for none
1032 * @return GNUNET_YES if FD is set in the set
1035 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1038 if ((nfd == -1) || (to == NULL))
1040 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1045 * Add a file handle to the fd set
1047 * @param h the file handle to add
1050 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1051 const struct GNUNET_DISK_FileHandle *h)
1054 GNUNET_CONTAINER_slist_add (fds->handles,
1055 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1056 sizeof (struct GNUNET_DISK_FileHandle));
1061 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1062 FD_SET (fd, &fds->sds);
1063 if (fd + 1 > fds->nsds)
1071 * Check if a file handle is part of an fd set
1073 * @param h file handle
1074 * @return GNUNET_YES if the file handle is part of the set
1077 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1078 const struct GNUNET_DISK_FileHandle *h)
1082 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1084 GNUNET_DISK_FileHandle));
1086 return FD_ISSET (h->fd, &fds->sds);
1092 * Checks if two fd sets overlap
1093 * @param fds1 first fd set
1094 * @param fds2 second fd set
1095 * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
1098 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1099 const struct GNUNET_NETWORK_FDSet *fds2)
1105 if (nfds > fds2->nsds)
1110 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1114 struct GNUNET_CONTAINER_SList_Iterator it;
1115 struct GNUNET_DISK_FileHandle *h;
1119 /*This code is somewhat hacky, we are not supposed to know what's
1120 * inside of fd_set; also the O(n^2) is really bad... */
1122 for (i = 0; i < fds1->sds.fd_count; i++)
1124 for (j = 0; j < fds2->sds.fd_count; j++)
1126 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1130 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1131 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1134 struct GNUNET_CONTAINER_SList_Iterator t;
1136 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1139 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1141 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1142 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1143 GNUNET_CONTAINER_slist_next (&t))
1145 struct GNUNET_DISK_FileHandle *fh;
1147 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1149 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1152 if (GNUNET_CONTAINER_slist_contains
1153 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1157 GNUNET_CONTAINER_slist_next (&it);
1166 * @return a new fd set
1168 struct GNUNET_NETWORK_FDSet *
1169 GNUNET_NETWORK_fdset_create ()
1171 struct GNUNET_NETWORK_FDSet *fds;
1173 fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1175 fds->handles = GNUNET_CONTAINER_slist_create ();
1177 GNUNET_NETWORK_fdset_zero (fds);
1183 * Releases the associated memory of an fd set
1187 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1190 GNUNET_CONTAINER_slist_destroy (fds->handles);
1196 struct _select_params
1204 SOCKET wakeup_socket;
1209 _selector (LPVOID p)
1211 struct _select_params *sp = p;
1215 WaitForSingleObject (sp->standby, INFINITE);
1216 ResetEvent (sp->standby);
1217 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1218 if (FD_ISSET (sp->wakeup_socket, sp->r))
1220 FD_CLR (sp->wakeup_socket, sp->r);
1223 SetEvent (sp->wakeup);
1230 * Check if sockets or pipes meet certain conditions
1231 * @param rfds set of sockets or pipes to be checked for readability
1232 * @param wfds set of sockets or pipes to be checked for writability
1233 * @param efds set of sockets or pipes to be checked for exceptions
1234 * @param timeout relative value when to return
1235 * @return number of selected sockets or pipes, GNUNET_SYSERR on error
1238 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1239 struct GNUNET_NETWORK_FDSet *wfds,
1240 struct GNUNET_NETWORK_FDSet *efds,
1241 const struct GNUNET_TIME_Relative timeout)
1247 int read_handles = 0;
1248 int write_handles = 0;
1256 static HANDLE hEventPipeWrite = 0;
1257 static HANDLE hEventReadReady = 0;
1259 static struct _select_params sp;
1260 static HANDLE select_thread = NULL;
1261 static HANDLE select_finished_event = NULL;
1262 static HANDLE select_standby_event = NULL;
1263 static SOCKET select_wakeup_socket = -1;
1264 static SOCKET select_send_socket = -1;
1265 static struct timeval select_timeout;
1268 int writePipePos = 0;
1270 HANDLE handle_array[FD_SETSIZE + 2];
1271 int returncode = -1;
1272 int returnedpos = 0;
1274 struct GNUNET_CONTAINER_SList *handles_read;
1275 struct GNUNET_CONTAINER_SList *handles_write;
1276 struct GNUNET_CONTAINER_SList *handles_except;
1290 /* TODO: Make this growable */
1291 struct GNUNET_DISK_FileHandle *readArray[50];
1299 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1302 struct GNUNET_CONTAINER_SList_Iterator t;
1304 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1305 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1306 GNUNET_CONTAINER_slist_next (&t))
1308 struct GNUNET_DISK_FileHandle *fh;
1310 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1312 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1321 nfds = GNUNET_MAX (nfds, wfds->nsds);
1323 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1328 nfds = GNUNET_MAX (nfds, efds->nsds);
1330 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1335 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1342 LOG (GNUNET_ERROR_TYPE_ERROR,
1344 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1348 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1350 (timeout.rel_value_us -
1351 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1352 return select (nfds,
1353 (NULL != rfds) ? &rfds->sds : NULL,
1354 (NULL != wfds) ? &wfds->sds : NULL,
1355 (NULL != efds) ? &efds->sds : NULL,
1356 (timeout.rel_value_us ==
1357 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1360 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1361 /* calculate how long we need to wait in milliseconds */
1362 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1363 ms_total = INFINITE;
1366 ms_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
1367 if (timeout.rel_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us > 0xFFFFFFFFLL - 1)
1370 ms_total = 0xFFFFFFFF - 1;
1373 /* select() may be used as a portable way to sleep */
1374 if (!(rfds || wfds || efds))
1380 if (NULL == select_thread)
1382 SOCKET select_listening_socket = -1;
1383 struct sockaddr_in s_in;
1388 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1389 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1391 select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1393 select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1396 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1397 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1399 alen = sizeof (s_in);
1400 s_in.sin_family = AF_INET;
1402 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1403 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1404 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1405 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1406 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1407 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1409 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1410 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1412 res = listen (select_listening_socket, SOMAXCONN);
1413 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1415 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1416 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1418 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1420 closesocket (select_listening_socket);
1422 sp.wakeup = select_finished_event;
1423 sp.standby = select_standby_event;
1424 sp.wakeup_socket = select_wakeup_socket;
1426 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1430 handles_read = GNUNET_CONTAINER_slist_create ();
1431 handles_write = GNUNET_CONTAINER_slist_create ();
1432 handles_except = GNUNET_CONTAINER_slist_create ();
1443 FD_COPY (&rfds->sds, &aread);
1445 FD_COPY (&rfds->sds, &bread);
1450 FD_COPY (&wfds->sds, &awrite);
1452 FD_COPY (&wfds->sds, &bwrite);
1457 FD_COPY (&efds->sds, &aexcept);
1459 FD_COPY (&efds->sds, &bexcept);
1463 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1464 By profiling we detected that to be true in 90% of the cases.
1467 /* Do the select now */
1468 select_timeout.tv_sec = 0;
1469 select_timeout.tv_usec = 0;
1471 /* Copy all the writes to the except, so we can detect connect() errors */
1472 for (i = 0; i < awrite.fd_count; i++)
1473 FD_SET (awrite.fd_array[i], &aexcept);
1474 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1475 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1476 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1479 if (selectret == -1)
1481 /* Throw an error early on, while we still have the context. */
1482 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1483 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1487 /* Check aexcept, add its contents to awrite
1488 This is technically wrong (aexcept might have its own descriptors), we should
1489 have checked that descriptors were in awrite originally before re-adding them from
1490 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1491 for (i = 0; i < aexcept.fd_count; i++)
1492 FD_SET (aexcept.fd_array[i], &awrite);
1494 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1495 /* Sadly, it means code duplication :( */
1496 if ((selectret > 0) || (ms_total == 0))
1499 if (rfds && read_handles)
1501 struct GNUNET_CONTAINER_SList_Iterator i;
1504 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1505 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1506 GNUNET_CONTAINER_slist_next (&i), c++)
1508 struct GNUNET_DISK_FileHandle *fh;
1510 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1511 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1517 DWORD waitstatus = 0;
1518 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1519 error = GetLastError ();
1520 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1521 c, fh->h, bret, waitstatus, error);
1524 /* TODO: either add more errors to this condition, or eliminate it
1525 * entirely (failed to peek -> pipe is in serious trouble, should
1526 * be selected as readable).
1528 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1531 else if (waitstatus <= 0)
1533 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1534 fh, sizeof (struct GNUNET_DISK_FileHandle));
1536 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1541 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1542 fh, sizeof (struct GNUNET_DISK_FileHandle));
1547 if (wfds && write_handles)
1549 LOG (GNUNET_ERROR_TYPE_DEBUG,
1550 "Adding the write ready event to the array as %d\n", nhandles);
1551 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1552 retcode += write_handles;
1554 if (efds && ex_handles)
1556 struct GNUNET_CONTAINER_SList_Iterator i;
1558 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1559 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1560 GNUNET_CONTAINER_slist_next (&i))
1562 struct GNUNET_DISK_FileHandle *fh;
1565 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1566 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1568 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1570 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1571 fh, sizeof (struct GNUNET_DISK_FileHandle));
1577 /* Add our select() result.*/
1579 retcode += selectret;
1583 GNUNET_NETWORK_fdset_zero (rfds);
1584 if (selectret != -1)
1585 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1586 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1590 GNUNET_NETWORK_fdset_zero (wfds);
1591 if (selectret != -1)
1592 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1593 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1597 GNUNET_NETWORK_fdset_zero (efds);
1598 if (selectret != -1)
1599 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1600 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1602 GNUNET_CONTAINER_slist_destroy (handles_read);
1603 GNUNET_CONTAINER_slist_destroy (handles_write);
1604 GNUNET_CONTAINER_slist_destroy (handles_except);
1606 if (selectret == -1)
1611 /* If we got this far, use slower implementation that is able to do a waiting select
1612 on both sockets and pipes simultaneously */
1614 /* Events for pipes */
1615 if (!hEventReadReady)
1616 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1617 if (!hEventPipeWrite)
1618 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1634 FD_COPY (&rfds->sds, &aread);
1636 FD_COPY (&rfds->sds, &bread);
1641 FD_COPY (&wfds->sds, &awrite);
1643 FD_COPY (&wfds->sds, &bwrite);
1648 FD_COPY (&efds->sds, &aexcept);
1650 FD_COPY (&efds->sds, &bexcept);
1653 /* We will first Add the PIPES to the events */
1655 if (rfds && read_handles)
1657 struct GNUNET_CONTAINER_SList_Iterator i;
1659 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1660 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1661 GNUNET_CONTAINER_slist_next (&i))
1663 struct GNUNET_DISK_FileHandle *fh;
1665 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1667 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1669 /* Read zero bytes to check the status of the pipe */
1670 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1672 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1674 DWORD error_code = GetLastError ();
1676 if (error_code == ERROR_IO_PENDING)
1678 LOG (GNUNET_ERROR_TYPE_DEBUG,
1679 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1681 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1682 readArray[readPipes++] = fh;
1686 LOG (GNUNET_ERROR_TYPE_DEBUG,
1687 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1688 handle_array[nhandles++] = hEventReadReady;
1689 readArray[readPipes++] = fh;
1694 LOG (GNUNET_ERROR_TYPE_DEBUG,
1695 "Adding the read ready event to the array as %d\n", nhandles);
1696 handle_array[nhandles++] = hEventReadReady;
1697 readArray[readPipes++] = fh;
1702 GNUNET_CONTAINER_slist_add (handles_read,
1703 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1704 fh, sizeof (struct GNUNET_DISK_FileHandle));
1708 if (wfds && write_handles)
1710 LOG (GNUNET_ERROR_TYPE_DEBUG,
1711 "Adding the write ready event to the array as %d\n", nhandles);
1712 handle_array[nhandles++] = hEventPipeWrite;
1713 writePipePos = nhandles;
1715 if (efds && ex_handles)
1717 struct GNUNET_CONTAINER_SList_Iterator i;
1719 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1720 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1721 GNUNET_CONTAINER_slist_next (&i))
1723 struct GNUNET_DISK_FileHandle *fh;
1726 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1728 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1730 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1732 GNUNET_CONTAINER_slist_add (handles_except,
1733 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1735 sizeof (struct GNUNET_DISK_FileHandle));
1745 LOG (GNUNET_ERROR_TYPE_DEBUG,
1746 "Adding the socket event to the array as %d\n",
1748 handle_array[nhandles++] = select_finished_event;
1749 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1753 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1754 select_timeout.tv_usec =(timeout.rel_value_us -
1755 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1756 sp.tv = &select_timeout;
1758 FD_SET (select_wakeup_socket, &aread);
1762 /* Failed connections cause sockets to be set in errorfds on W32,
1763 * but on POSIX it should set them in writefds.
1764 * First copy all awrite sockets to aexcept, later we'll
1765 * check aexcept and set its contents in awrite as well
1766 * Sockets are also set in errorfds when OOB data is available,
1767 * but we don't use OOB data.
1769 for (i = 0; i < awrite.fd_count; i++)
1770 FD_SET (awrite.fd_array[i], &aexcept);
1771 ResetEvent (select_finished_event);
1772 SetEvent (select_standby_event);
1775 handle_array[nhandles] = NULL;
1776 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n",
1777 nfds, nhandles, (unsigned long long) ms_total);
1781 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1782 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1787 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1788 returncode = WAIT_TIMEOUT;
1792 /* Shouldn't come this far. If it does - investigate. */
1798 /* Don't wake up select-thread when delay is 0, it should return immediately
1799 * and wake up by itself.
1802 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1803 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1804 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1809 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1812 /* Check aexcept, add its contents to awrite */
1813 for (i = 0; i < aexcept.fd_count; i++)
1814 FD_SET (aexcept.fd_array[i], &awrite);
1817 returnedpos = returncode - WAIT_OBJECT_0;
1818 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1820 if (nhandles && (returnedpos < nhandles))
1825 retcode += sp.status;
1827 if ((writePipePos != -1) && (returnedpos < writePipePos))
1829 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1830 retcode += write_handles;
1831 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1833 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1834 /* We have some pipes ready for read. */
1835 if (returnedpos < readPipes)
1837 for (i = 0; i < readPipes; i++)
1845 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1846 error = GetLastError ();
1847 LOG (GNUNET_ERROR_TYPE_DEBUG,
1848 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1849 i, readArray[i]->h, bret, waitstatus, error);
1852 /* TODO: either add more errors to this condition, or eliminate it
1853 * entirely (failed to peek -> pipe is in serious trouble, should
1854 * be selected as readable).
1856 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1859 else if (waitstatus <= 0)
1861 GNUNET_CONTAINER_slist_add (handles_read,
1862 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1864 sizeof (struct GNUNET_DISK_FileHandle));
1866 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1867 readArray[i], readArray[i]->h);
1871 if (!nhandles || (returnedpos >= nhandles))
1872 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1875 struct GNUNET_CONTAINER_SList_Iterator t;
1877 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1878 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1879 GNUNET_CONTAINER_slist_next (&t))
1881 struct GNUNET_DISK_FileHandle *fh;
1883 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1885 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1890 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1891 GNUNET_NETWORK_fdset_zero (rfds);
1892 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1893 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1894 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1898 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1899 GNUNET_NETWORK_fdset_zero (wfds);
1900 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1901 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1902 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1906 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1907 GNUNET_NETWORK_fdset_zero (efds);
1908 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1909 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1910 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1912 GNUNET_CONTAINER_slist_destroy (handles_read);
1913 GNUNET_CONTAINER_slist_destroy (handles_write);
1914 GNUNET_CONTAINER_slist_destroy (handles_except);
1918 struct GNUNET_CONTAINER_SList_Iterator t;
1920 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1921 for (i = 0; i < rfds->sds.fd_count; i++)
1923 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1925 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1926 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1927 GNUNET_CONTAINER_slist_next (&t))
1929 struct GNUNET_DISK_FileHandle *fh;
1931 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1933 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1938 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1939 for (i = 0; i < wfds->sds.fd_count; i++)
1941 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1946 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1947 for (i = 0; i < efds->sds.fd_count; i++)
1949 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1952 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1954 if (nhandles && (returnedpos < nhandles))
1961 /* end of network.c */