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
28 #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 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
91 "Failed to create test socket: %s\n",
105 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
106 * shorten it to an acceptable length while keeping it unique
107 * and making sure it remains a valid filename (if possible).
109 * @param unixpath long path, will be freed (or same pointer returned
110 * with moved 0-termination).
111 * @return shortened unixpath, NULL on error
114 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
116 struct sockaddr_un dummy;
119 struct GNUNET_HashCode sh;
120 struct GNUNET_CRYPTO_HashAsciiEncoded ae;
123 upm = sizeof (dummy.sun_path);
124 slen = strlen (unixpath);
126 return unixpath; /* no shortening required */
127 GNUNET_CRYPTO_hash (unixpath, slen, &sh);
129 strlen (unixpath) >= upm)
131 if (NULL == (end = strrchr (unixpath, '/')))
133 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
134 _("Unable to shorten unix path `%s' while keeping name unique\n"),
136 GNUNET_free (unixpath);
141 GNUNET_CRYPTO_hash_to_enc (&sh, &ae);
142 strncat (unixpath, (char*) ae.encoding, 16);
148 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
153 * Set if a socket should use blocking or non-blocking IO.
156 * @param doBlock blocking mode
157 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
160 GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
167 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
170 SetErrnoFromWinsockError (WSAGetLastError ());
171 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
172 return GNUNET_SYSERR;
178 int flags = fcntl (fd->fd, F_GETFL);
183 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
184 return GNUNET_SYSERR;
187 flags &= ~O_NONBLOCK;
191 if (0 != fcntl (fd->fd, F_SETFL, flags))
194 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
195 return GNUNET_SYSERR;
203 * Make a socket non-inheritable to child processes
205 * @param h the socket to make non-inheritable
206 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
207 * @warning Not implemented on Windows
210 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
214 i = fcntl (h->fd, F_GETFD);
216 return GNUNET_SYSERR;
217 if (i == (i | FD_CLOEXEC))
220 if (fcntl (h->fd, F_SETFD, i) < 0)
221 return GNUNET_SYSERR;
225 b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
228 SetErrnoFromWinsockError (WSAGetLastError ());
229 return GNUNET_SYSERR;
238 * The MSG_NOSIGNAL equivalent on Mac OS X
240 * @param h the socket to make non-delaying
243 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
248 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE,
249 (const void *) &abs_value,
251 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
257 * Disable delays when sending data via the socket.
258 * (GNUnet makes sure that messages are as big as
261 * @param h the socket to make non-delaying
264 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
269 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
270 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
272 const char *abs_value = "1";
275 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY,
276 (const void *) abs_value,
278 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
284 * Perform proper canonical initialization for a network handle.
285 * Set it to non-blocking, make it non-inheritable to child
286 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
287 * stream socket) and check that it is smaller than FD_SETSIZE.
289 * @param h socket to initialize
290 * @param af address family of the socket
291 * @param type socket type
292 * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
293 * failed and the handle was destroyed
296 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
301 if (h->fd == INVALID_SOCKET)
304 SetErrnoFromWinsockError (WSAGetLastError ());
307 return GNUNET_SYSERR;
310 if (h->fd >= FD_SETSIZE)
312 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
314 return GNUNET_SYSERR;
317 if (GNUNET_OK != socket_set_inheritable (h))
318 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
319 "socket_set_inheritable");
321 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
324 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
325 return GNUNET_SYSERR;
328 socket_set_nosigpipe (h);
330 if ( (type == SOCK_STREAM)
335 socket_set_nodelay (h);
341 * accept a new connection on a socket
343 * @param desc bound socket
344 * @param address address of the connecting peer, may be NULL
345 * @param address_len length of @a address
346 * @return client socket
348 struct GNUNET_NETWORK_Handle *
349 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
350 struct sockaddr *address,
351 socklen_t *address_len)
353 struct GNUNET_NETWORK_Handle *ret;
355 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
358 struct sockaddr name;
359 socklen_t namelen = sizeof (name);
360 int gsn = getsockname (desc->fd, &name, &namelen);
363 LOG (GNUNET_ERROR_TYPE_DEBUG,
364 "Accepting connection on `%s'\n",
365 GNUNET_a2s (&name, namelen));
368 ret->fd = accept (desc->fd, address, address_len);
374 if (GNUNET_OK != initialize_network_handle (ret,
375 (NULL != address) ? address->sa_family : desc->af,
383 * Bind a socket to a particular address.
385 * @param desc socket to bind
386 * @param address address to be bound
387 * @param address_len length of @a address
388 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
391 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
392 const struct sockaddr *address,
393 socklen_t address_len)
402 if (AF_INET6 == desc->af)
403 if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY,
406 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
414 /* This is required here for TCP sockets, but only on UNIX */
415 if ((SOCK_STREAM == desc->type)
416 && (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))))
417 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
422 /* set permissions of newly created UNIX domain socket to "user-only"; applications
423 can choose to relax this later */
424 mode_t old_mask = 0; /* assigned to make compiler happy */
426 if (AF_UNIX == address->sa_family)
427 old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH);
430 ret = bind (desc->fd, address, address_len);
432 if (AF_UNIX == address->sa_family)
433 (void) umask (old_mask);
437 if (SOCKET_ERROR == ret)
438 SetErrnoFromWinsockError (WSAGetLastError ());
441 return GNUNET_SYSERR;
443 desc->addr = GNUNET_malloc (address_len);
444 memcpy (desc->addr, address, address_len);
445 desc->addrlen = address_len;
455 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
458 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
466 ret = closesocket (desc->fd);
467 error = WSAGetLastError ();
468 SetErrnoFromWinsockError (error);
469 LOG (GNUNET_ERROR_TYPE_DEBUG,
470 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
473 ret = close (desc->fd);
476 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
478 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
479 char *dirname = GNUNET_strndup (un->sun_path,
480 sizeof (un->sun_path));
482 if (0 != unlink (dirname))
484 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
492 len = strlen (dirname);
493 while ((len > 0) && (dirname[len] != DIR_SEPARATOR))
496 if (0 != rmdir (dirname))
503 /* these are normal and can just be ignored */
506 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
513 GNUNET_free (dirname);
516 GNUNET_NETWORK_socket_free_memory_only_ (desc);
517 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
522 * Only free memory of a socket, keep the file descriptor untouched.
527 GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc)
529 GNUNET_free_non_null (desc->addr);
535 * Box a native socket (and check that it is a socket).
537 * @param fd socket to box
538 * @return NULL on error (including not supported on target platform)
540 struct GNUNET_NETWORK_Handle *
541 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
543 struct GNUNET_NETWORK_Handle *ret;
547 /* FIXME: Find a better call to check that FD is valid */
548 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
549 return NULL; /* invalid FD */
550 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
555 if (fcntl (fd, F_GETFD) < 0)
556 return NULL; /* invalid FD */
557 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
566 * Connect a socket to some remote address.
569 * @param address peer address
570 * @param address_len length of @a address
571 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
574 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
575 const struct sockaddr *address,
576 socklen_t address_len)
580 ret = connect (desc->fd, address, address_len);
583 if (SOCKET_ERROR == ret)
585 SetErrnoFromWinsockError (WSAGetLastError ());
586 if (errno == EWOULDBLOCK)
590 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
598 * @param level protocol level of the option
599 * @param optname identifier of the option
600 * @param optval options
601 * @param optlen length of @a optval
602 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
605 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
606 int level, int optname, void *optval,
611 ret = getsockopt (desc->fd, level, optname, optval, optlen);
614 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
615 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
617 else if (SOCKET_ERROR == ret)
618 SetErrnoFromWinsockError (WSAGetLastError ());
620 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
628 * @param backlog length of the listen queue
629 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
632 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
637 ret = listen (desc->fd, backlog);
640 if (SOCKET_ERROR == ret)
641 SetErrnoFromWinsockError (WSAGetLastError ());
644 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
649 * How much data is available to be read on this descriptor?
652 * @returns #GNUNET_NO if no data is available, or on error!
655 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
660 /* How much is there to be read? */
664 error = ioctl (desc->fd, FIONREAD, &pending);
666 return (ssize_t) pending;
671 error = ioctlsocket (desc->fd, FIONREAD, &pending);
672 if (error != SOCKET_ERROR)
673 return (ssize_t) pending;
680 * Read data from a socket (always non-blocking).
683 * @param buffer buffer
684 * @param length length of @a buffer
685 * @param src_addr either the source to recv from, or all zeroes
686 * to be filled in by recvfrom
687 * @param addrlen length of the @a src_addr
690 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
691 void *buffer, size_t length,
692 struct sockaddr *src_addr, socklen_t *addrlen)
700 flags |= MSG_DONTWAIT;
703 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
705 if (SOCKET_ERROR == ret)
706 SetErrnoFromWinsockError (WSAGetLastError ());
713 * Read data from a connected socket (always non-blocking).
716 * @param buffer buffer
717 * @param length length of @a buffer
720 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
721 void *buffer, size_t length)
729 flags |= MSG_DONTWAIT;
731 ret = recv (desc->fd, buffer, length, flags);
733 if (SOCKET_ERROR == ret)
734 SetErrnoFromWinsockError (WSAGetLastError ());
741 * Send data (always non-blocking).
744 * @param buffer data to send
745 * @param length size of the @a buffer
746 * @return number of bytes sent, #GNUNET_SYSERR on error
749 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
750 const void *buffer, size_t length)
758 flags |= MSG_DONTWAIT;
762 flags |= MSG_NOSIGNAL;
765 ret = send (desc->fd, buffer, length, flags);
768 if (SOCKET_ERROR == ret)
769 SetErrnoFromWinsockError (WSAGetLastError ());
777 * Send data to a particular destination (always non-blocking).
778 * This function only works for UDP sockets.
781 * @param message data to send
782 * @param length size of the data
783 * @param dest_addr destination address
784 * @param dest_len length of @a address
785 * @return number of bytes sent, #GNUNET_SYSERR on error
788 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
789 const void *message, size_t length,
790 const struct sockaddr * dest_addr,
799 flags |= MSG_DONTWAIT;
802 flags |= MSG_NOSIGNAL;
804 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
806 if (SOCKET_ERROR == ret)
807 SetErrnoFromWinsockError (WSAGetLastError ());
817 * @param level protocol level of the option
818 * @param option_name option identifier
819 * @param option_value value to set
820 * @param option_len size of option_value
821 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
824 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
825 int option_name, const void *option_value,
826 socklen_t option_len)
830 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
832 if (SOCKET_ERROR == ret)
833 SetErrnoFromWinsockError (WSAGetLastError ());
835 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
840 * Create a new socket. Configure it for non-blocking IO and
841 * mark it as non-inheritable to child processes (set the
842 * close-on-exec flag).
844 * @param domain domain of the socket
845 * @param type socket type
846 * @param protocol network protocol
847 * @return new socket, NULL on error
849 struct GNUNET_NETWORK_Handle *
850 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
852 struct GNUNET_NETWORK_Handle *ret;
854 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
855 ret->fd = socket (domain, type, protocol);
862 initialize_network_handle (ret, domain, type))
869 * Shut down socket operations
871 * @param how type of shutdown
872 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
875 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
879 ret = shutdown (desc->fd, how);
882 SetErrnoFromWinsockError (WSAGetLastError ());
884 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
889 * Disable the "CORK" feature for communication with the given socket,
890 * forcing the OS to immediately flush the buffer on transmission
891 * instead of potentially buffering multiple messages. Essentially
892 * reduces the OS send buffers to zero.
895 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
898 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
907 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
909 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
912 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
914 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
920 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
921 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
924 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
925 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
927 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
937 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
942 GNUNET_CONTAINER_slist_clear (fds->handles);
948 * Add a socket to the FD set
951 * @param desc socket to add
954 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
955 const struct GNUNET_NETWORK_Handle *desc)
957 FD_SET (desc->fd, &fds->sds);
958 if (desc->fd + 1 > fds->nsds)
959 fds->nsds = desc->fd + 1;
964 * Check whether a socket is part of the fd set
968 * @return 0 if the FD is not set
971 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
972 const struct GNUNET_NETWORK_Handle *desc)
974 return FD_ISSET (desc->fd, &fds->sds);
979 * Add one fd set to another
981 * @param dst the fd set to add to
982 * @param src the fd set to add from
985 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
986 const struct GNUNET_NETWORK_FDSet *src)
991 for (nfds = src->nsds; nfds >= 0; nfds--)
992 if (FD_ISSET (nfds, &src->sds))
995 FD_SET (nfds, &dst->sds);
996 if (nfds + 1 > dst->nsds)
997 dst->nsds = nfds + 1;
1000 /* This is MinGW32-specific implementation that relies on the code that
1001 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
1002 * that fd being added is not already in the set.
1003 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
1006 for (i = 0; i < src->sds.fd_count; i++)
1007 FD_SET (src->sds.fd_array[i], &dst->sds);
1008 if (src->nsds > dst->nsds)
1009 dst->nsds = src->nsds;
1011 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
1017 * Copy one fd set to another
1019 * @param to destination
1020 * @param from source
1023 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
1024 const struct GNUNET_NETWORK_FDSet *from)
1026 FD_COPY (&from->sds, &to->sds);
1027 to->nsds = from->nsds;
1030 GNUNET_CONTAINER_slist_clear (to->handles);
1031 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
1037 * Return file descriptor for this network handle
1039 * @param desc wrapper to process
1040 * @return POSIX file descriptor
1043 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
1050 * Return sockaddr for this network handle
1052 * @param desc wrapper to process
1056 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1063 * Return sockaddr length for this network handle
1065 * @param desc wrapper to process
1066 * @return socklen_t for sockaddr
1069 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1071 return desc->addrlen;
1076 * Copy a native fd set
1078 * @param to destination
1079 * @param from native source set
1080 * @param nfds the biggest socket number in from + 1
1083 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1084 const fd_set * from, int nfds)
1086 FD_COPY (from, &to->sds);
1092 * Set a native fd in a set
1094 * @param to destination
1095 * @param nfd native FD to set
1098 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1100 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1101 FD_SET (nfd, &to->sds);
1102 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1107 * Test native fd in a set
1109 * @param to set to test, NULL for empty set
1110 * @param nfd native FD to test, or -1 for none
1111 * @return #GNUNET_YES if FD is set in the set
1114 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1117 if ((nfd == -1) || (to == NULL))
1119 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1124 * Add a file handle to the fd set
1126 * @param h the file handle to add
1129 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1130 const struct GNUNET_DISK_FileHandle *h)
1133 GNUNET_CONTAINER_slist_add (fds->handles,
1134 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1135 sizeof (struct GNUNET_DISK_FileHandle));
1140 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1141 FD_SET (fd, &fds->sds);
1142 if (fd + 1 > fds->nsds)
1150 * Check if a file handle is part of an fd set
1152 * @param h file handle
1153 * @return #GNUNET_YES if the file handle is part of the set
1156 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1157 const struct GNUNET_DISK_FileHandle *h)
1161 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1163 GNUNET_DISK_FileHandle));
1165 return FD_ISSET (h->fd, &fds->sds);
1171 * Checks if two fd sets overlap
1172 * @param fds1 first fd set
1173 * @param fds2 second fd set
1174 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1177 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1178 const struct GNUNET_NETWORK_FDSet *fds2)
1184 if (nfds > fds2->nsds)
1189 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1193 struct GNUNET_CONTAINER_SList_Iterator it;
1194 struct GNUNET_DISK_FileHandle *h;
1198 /*This code is somewhat hacky, we are not supposed to know what's
1199 * inside of fd_set; also the O(n^2) is really bad... */
1201 for (i = 0; i < fds1->sds.fd_count; i++)
1203 for (j = 0; j < fds2->sds.fd_count; j++)
1205 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1209 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1210 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1213 struct GNUNET_CONTAINER_SList_Iterator t;
1215 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1218 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1220 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1221 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1222 GNUNET_CONTAINER_slist_next (&t))
1224 struct GNUNET_DISK_FileHandle *fh;
1226 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1228 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1231 if (GNUNET_CONTAINER_slist_contains
1232 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1236 GNUNET_CONTAINER_slist_next (&it);
1246 * @return a new fd set
1248 struct GNUNET_NETWORK_FDSet *
1249 GNUNET_NETWORK_fdset_create ()
1251 struct GNUNET_NETWORK_FDSet *fds;
1253 fds = GNUNET_new (struct GNUNET_NETWORK_FDSet);
1255 fds->handles = GNUNET_CONTAINER_slist_create ();
1257 GNUNET_NETWORK_fdset_zero (fds);
1263 * Releases the associated memory of an fd set
1268 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1271 GNUNET_CONTAINER_slist_destroy (fds->handles);
1277 struct _select_params
1285 SOCKET wakeup_socket;
1290 _selector (LPVOID p)
1292 struct _select_params *sp = p;
1296 WaitForSingleObject (sp->standby, INFINITE);
1297 ResetEvent (sp->standby);
1298 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1299 if (FD_ISSET (sp->wakeup_socket, sp->r))
1301 FD_CLR (sp->wakeup_socket, sp->r);
1304 SetEvent (sp->wakeup);
1312 * Check if sockets or pipes meet certain conditions
1314 * @param rfds set of sockets or pipes to be checked for readability
1315 * @param wfds set of sockets or pipes to be checked for writability
1316 * @param efds set of sockets or pipes to be checked for exceptions
1317 * @param timeout relative value when to return
1318 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1321 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1322 struct GNUNET_NETWORK_FDSet *wfds,
1323 struct GNUNET_NETWORK_FDSet *efds,
1324 const struct GNUNET_TIME_Relative timeout)
1330 int read_handles = 0;
1331 int write_handles = 0;
1335 uint64_t mcs_total = 0;
1336 DWORD ms_rounded = 0;
1340 static HANDLE hEventPipeWrite = 0;
1341 static HANDLE hEventReadReady = 0;
1343 static struct _select_params sp;
1344 static HANDLE select_thread = NULL;
1345 static HANDLE select_finished_event = NULL;
1346 static HANDLE select_standby_event = NULL;
1347 static SOCKET select_wakeup_socket = -1;
1348 static SOCKET select_send_socket = -1;
1349 static struct timeval select_timeout;
1352 int writePipePos = 0;
1354 HANDLE handle_array[FD_SETSIZE + 2];
1355 int returncode = -1;
1356 int returnedpos = 0;
1358 struct GNUNET_CONTAINER_SList *handles_read;
1359 struct GNUNET_CONTAINER_SList *handles_write;
1360 struct GNUNET_CONTAINER_SList *handles_except;
1374 /* TODO: Make this growable */
1375 struct GNUNET_DISK_FileHandle *readArray[50];
1383 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1386 struct GNUNET_CONTAINER_SList_Iterator t;
1388 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1389 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1390 GNUNET_CONTAINER_slist_next (&t))
1392 struct GNUNET_DISK_FileHandle *fh;
1394 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1396 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1405 nfds = GNUNET_MAX (nfds, wfds->nsds);
1407 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1412 nfds = GNUNET_MAX (nfds, efds->nsds);
1414 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1419 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1426 LOG (GNUNET_ERROR_TYPE_ERROR,
1427 _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1431 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1433 (timeout.rel_value_us -
1434 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1435 return select (nfds,
1436 (NULL != rfds) ? &rfds->sds : NULL,
1437 (NULL != wfds) ? &wfds->sds : NULL,
1438 (NULL != efds) ? &efds->sds : NULL,
1439 (timeout.rel_value_us ==
1440 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1443 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1444 /* calculate how long we need to wait in microseconds */
1445 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1447 mcs_total = INFINITE;
1448 ms_rounded = INFINITE;
1452 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1453 ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1454 if (mcs_total > 0 && ms_rounded == 0)
1457 /* select() may be used as a portable way to sleep */
1458 if (!(rfds || wfds || efds))
1464 if (NULL == select_thread)
1466 SOCKET select_listening_socket = -1;
1467 struct sockaddr_in s_in;
1472 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1473 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1475 select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1477 select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1480 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1481 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1483 alen = sizeof (s_in);
1484 s_in.sin_family = AF_INET;
1486 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1487 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1488 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1489 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1490 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1491 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1493 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1494 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1496 res = listen (select_listening_socket, SOMAXCONN);
1497 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1499 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1500 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1502 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1504 closesocket (select_listening_socket);
1506 sp.wakeup = select_finished_event;
1507 sp.standby = select_standby_event;
1508 sp.wakeup_socket = select_wakeup_socket;
1510 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1514 handles_read = GNUNET_CONTAINER_slist_create ();
1515 handles_write = GNUNET_CONTAINER_slist_create ();
1516 handles_except = GNUNET_CONTAINER_slist_create ();
1527 FD_COPY (&rfds->sds, &aread);
1529 FD_COPY (&rfds->sds, &bread);
1534 FD_COPY (&wfds->sds, &awrite);
1536 FD_COPY (&wfds->sds, &bwrite);
1541 FD_COPY (&efds->sds, &aexcept);
1543 FD_COPY (&efds->sds, &bexcept);
1547 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1548 By profiling we detected that to be true in 90% of the cases.
1551 /* Do the select now */
1552 select_timeout.tv_sec = 0;
1553 select_timeout.tv_usec = 0;
1555 /* Copy all the writes to the except, so we can detect connect() errors */
1556 for (i = 0; i < awrite.fd_count; i++)
1557 FD_SET (awrite.fd_array[i], &aexcept);
1558 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1559 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1560 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1563 if (selectret == -1)
1565 /* Throw an error early on, while we still have the context. */
1566 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1567 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1571 /* Check aexcept, add its contents to awrite
1572 This is technically wrong (aexcept might have its own descriptors), we should
1573 have checked that descriptors were in awrite originally before re-adding them from
1574 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1575 for (i = 0; i < aexcept.fd_count; i++)
1576 FD_SET (aexcept.fd_array[i], &awrite);
1578 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1579 /* Sadly, it means code duplication :( */
1580 if ((selectret > 0) || (mcs_total == 0))
1583 if (rfds && read_handles)
1585 struct GNUNET_CONTAINER_SList_Iterator i;
1588 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1589 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1590 GNUNET_CONTAINER_slist_next (&i), c++)
1592 struct GNUNET_DISK_FileHandle *fh;
1594 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1595 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1601 DWORD waitstatus = 0;
1602 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1603 error = GetLastError ();
1604 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1605 c, fh->h, bret, waitstatus, error);
1608 /* TODO: either add more errors to this condition, or eliminate it
1609 * entirely (failed to peek -> pipe is in serious trouble, should
1610 * be selected as readable).
1612 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1615 else if (waitstatus <= 0)
1617 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1618 fh, sizeof (struct GNUNET_DISK_FileHandle));
1620 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1625 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1626 fh, sizeof (struct GNUNET_DISK_FileHandle));
1631 if (wfds && write_handles)
1633 LOG (GNUNET_ERROR_TYPE_DEBUG,
1634 "Adding the write ready event to the array as %d\n", nhandles);
1635 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1636 retcode += write_handles;
1638 if (efds && ex_handles)
1640 struct GNUNET_CONTAINER_SList_Iterator i;
1642 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1643 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1644 GNUNET_CONTAINER_slist_next (&i))
1646 struct GNUNET_DISK_FileHandle *fh;
1649 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1650 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1652 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1654 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1655 fh, sizeof (struct GNUNET_DISK_FileHandle));
1661 /* Add our select() result.*/
1663 retcode += selectret;
1667 GNUNET_NETWORK_fdset_zero (rfds);
1668 if (selectret != -1)
1669 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1670 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1674 GNUNET_NETWORK_fdset_zero (wfds);
1675 if (selectret != -1)
1676 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1677 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1681 GNUNET_NETWORK_fdset_zero (efds);
1682 if (selectret != -1)
1683 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1684 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1686 GNUNET_CONTAINER_slist_destroy (handles_read);
1687 GNUNET_CONTAINER_slist_destroy (handles_write);
1688 GNUNET_CONTAINER_slist_destroy (handles_except);
1690 if (selectret == -1)
1695 /* If we got this far, use slower implementation that is able to do a waiting select
1696 on both sockets and pipes simultaneously */
1698 /* Events for pipes */
1699 if (!hEventReadReady)
1700 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1701 if (!hEventPipeWrite)
1702 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1718 FD_COPY (&rfds->sds, &aread);
1720 FD_COPY (&rfds->sds, &bread);
1725 FD_COPY (&wfds->sds, &awrite);
1727 FD_COPY (&wfds->sds, &bwrite);
1732 FD_COPY (&efds->sds, &aexcept);
1734 FD_COPY (&efds->sds, &bexcept);
1737 /* We will first Add the PIPES to the events */
1739 if (rfds && read_handles)
1741 struct GNUNET_CONTAINER_SList_Iterator i;
1743 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1744 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1745 GNUNET_CONTAINER_slist_next (&i))
1747 struct GNUNET_DISK_FileHandle *fh;
1749 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1751 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1753 /* Read zero bytes to check the status of the pipe */
1754 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1756 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1758 DWORD error_code = GetLastError ();
1760 if (error_code == ERROR_IO_PENDING)
1762 LOG (GNUNET_ERROR_TYPE_DEBUG,
1763 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1765 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1766 readArray[readPipes++] = fh;
1770 LOG (GNUNET_ERROR_TYPE_DEBUG,
1771 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1772 handle_array[nhandles++] = hEventReadReady;
1773 readArray[readPipes++] = fh;
1778 LOG (GNUNET_ERROR_TYPE_DEBUG,
1779 "Adding the read ready event to the array as %d\n", nhandles);
1780 handle_array[nhandles++] = hEventReadReady;
1781 readArray[readPipes++] = fh;
1786 GNUNET_CONTAINER_slist_add (handles_read,
1787 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1788 fh, sizeof (struct GNUNET_DISK_FileHandle));
1792 if (wfds && write_handles)
1794 LOG (GNUNET_ERROR_TYPE_DEBUG,
1795 "Adding the write ready event to the array as %d\n", nhandles);
1796 handle_array[nhandles++] = hEventPipeWrite;
1797 writePipePos = nhandles;
1799 if (efds && ex_handles)
1801 struct GNUNET_CONTAINER_SList_Iterator i;
1803 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1804 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1805 GNUNET_CONTAINER_slist_next (&i))
1807 struct GNUNET_DISK_FileHandle *fh;
1810 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1812 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1814 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1816 GNUNET_CONTAINER_slist_add (handles_except,
1817 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1819 sizeof (struct GNUNET_DISK_FileHandle));
1829 LOG (GNUNET_ERROR_TYPE_DEBUG,
1830 "Adding the socket event to the array as %d\n",
1832 handle_array[nhandles++] = select_finished_event;
1833 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1837 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1838 select_timeout.tv_usec =(timeout.rel_value_us -
1839 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1840 sp.tv = &select_timeout;
1842 FD_SET (select_wakeup_socket, &aread);
1845 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1850 /* Failed connections cause sockets to be set in errorfds on W32,
1851 * but on POSIX it should set them in writefds.
1852 * First copy all awrite sockets to aexcept, later we'll
1853 * check aexcept and set its contents in awrite as well
1854 * Sockets are also set in errorfds when OOB data is available,
1855 * but we don't use OOB data.
1857 for (i = 0; i < awrite.fd_count; i++)
1858 FD_SET (awrite.fd_array[i], &aexcept);
1859 ResetEvent (select_finished_event);
1860 SetEvent (select_standby_event);
1863 handle_array[nhandles] = NULL;
1864 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
1865 nfds, nhandles, mcs_total);
1869 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
1870 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode);
1874 GNUNET_break (0); /* This branch shouldn't actually be executed...*/
1875 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1876 returncode = WAIT_TIMEOUT;
1880 /* Shouldn't come this far. If it does - investigate. */
1886 /* Don't wake up select-thread when delay is 0, it should return immediately
1887 * and wake up by itself.
1890 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1891 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1892 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1897 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1900 /* Check aexcept, add its contents to awrite */
1901 for (i = 0; i < aexcept.fd_count; i++)
1902 FD_SET (aexcept.fd_array[i], &awrite);
1905 returnedpos = returncode - WAIT_OBJECT_0;
1906 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1908 if (nhandles && (returnedpos < nhandles))
1913 retcode += sp.status;
1915 if ((writePipePos != -1) && (returnedpos < writePipePos))
1917 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1918 retcode += write_handles;
1919 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1921 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1922 /* We have some pipes ready for read. */
1923 if (returnedpos < readPipes)
1925 for (i = 0; i < readPipes; i++)
1933 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1934 error = GetLastError ();
1935 LOG (GNUNET_ERROR_TYPE_DEBUG,
1936 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1937 i, readArray[i]->h, bret, waitstatus, error);
1940 /* TODO: either add more errors to this condition, or eliminate it
1941 * entirely (failed to peek -> pipe is in serious trouble, should
1942 * be selected as readable).
1944 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1947 else if (waitstatus <= 0)
1949 GNUNET_CONTAINER_slist_add (handles_read,
1950 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1952 sizeof (struct GNUNET_DISK_FileHandle));
1954 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1955 readArray[i], readArray[i]->h);
1959 if (!nhandles || (returnedpos >= nhandles))
1960 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1963 struct GNUNET_CONTAINER_SList_Iterator t;
1965 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1966 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1967 GNUNET_CONTAINER_slist_next (&t))
1969 struct GNUNET_DISK_FileHandle *fh;
1971 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1973 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1978 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1979 GNUNET_NETWORK_fdset_zero (rfds);
1980 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1981 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1982 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1986 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1987 GNUNET_NETWORK_fdset_zero (wfds);
1988 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1989 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1990 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1994 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1995 GNUNET_NETWORK_fdset_zero (efds);
1996 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1997 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1998 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
2000 GNUNET_CONTAINER_slist_destroy (handles_read);
2001 GNUNET_CONTAINER_slist_destroy (handles_write);
2002 GNUNET_CONTAINER_slist_destroy (handles_except);
2006 struct GNUNET_CONTAINER_SList_Iterator t;
2008 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
2009 for (i = 0; i < rfds->sds.fd_count; i++)
2011 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
2013 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
2014 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
2015 GNUNET_CONTAINER_slist_next (&t))
2017 struct GNUNET_DISK_FileHandle *fh;
2019 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
2021 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
2026 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
2027 for (i = 0; i < wfds->sds.fd_count; i++)
2029 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
2034 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
2035 for (i = 0; i < efds->sds.fd_count; i++)
2037 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
2040 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
2042 if (nhandles && (returnedpos < nhandles))
2049 /* end of network.c */