2 This file is part of GNUnet.
3 (C) 2009, 2012 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file util/network.c
23 * @brief basic, low-level networking interface
25 * @author Christian Grothoff
29 #include "gnunet_util_lib.h"
31 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
32 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
33 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
35 #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
38 #ifndef INVALID_SOCKET
39 #define INVALID_SOCKET -1
43 struct GNUNET_NETWORK_Handle
52 * Address family / domain.
57 * Number of bytes in addr.
62 * Address we were bound to, or NULL.
64 struct sockaddr *addr;
70 * Test if the given protocol family is supported by this system.
72 * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
73 * @return GNUNET_OK if the PF is supported
76 GNUNET_NETWORK_test_pf (int pf)
80 s = socket (pf, SOCK_STREAM, 0);
83 if (EAFNOSUPPORT == errno)
85 fprintf (stderr, "Failed to create test socket: %s\n", STRERROR (errno));
98 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
99 * shorten it to an acceptable length while keeping it unique
100 * and making sure it remains a valid filename (if possible).
102 * @param unixpath long path, will be freed (or same pointer returned
103 * with moved 0-termination).
104 * @return shortened unixpath, NULL on error
107 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
109 struct sockaddr_un dummy;
112 struct GNUNET_CRYPTO_ShortHashCode sh;
113 struct GNUNET_CRYPTO_ShortHashAsciiEncoded ae;
116 upm = sizeof (dummy.sun_path);
117 slen = strlen (unixpath);
119 return unixpath; /* no shortening required */
120 GNUNET_CRYPTO_short_hash (unixpath, slen, &sh);
121 while (sizeof (struct GNUNET_CRYPTO_ShortHashAsciiEncoded) +
122 strlen (unixpath) >= upm)
124 if (NULL == (end = strrchr (unixpath, '/')))
126 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
127 _("Unable to shorten unix path `%s' while keeping name unique\n"),
129 GNUNET_free (unixpath);
134 GNUNET_CRYPTO_short_hash_to_enc (&sh, &ae);
135 strcat (unixpath, (char*) ae.short_encoding);
141 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
146 * Set if a socket should use blocking or non-blocking IO.
148 * @param doBlock blocking mode
149 * @return GNUNET_OK on success, GNUNET_SYSERR on error
152 socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
159 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
162 SetErrnoFromWinsockError (WSAGetLastError ());
163 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
164 return GNUNET_SYSERR;
170 int flags = fcntl (fd->fd, F_GETFL);
175 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
176 return GNUNET_SYSERR;
179 flags &= ~O_NONBLOCK;
183 if (0 != fcntl (fd->fd, F_SETFL, flags))
186 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
187 return GNUNET_SYSERR;
195 * Make a socket non-inheritable to child processes
197 * @param h the socket to make non-inheritable
198 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
199 * @warning Not implemented on Windows
202 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
206 i = fcntl (h->fd, F_GETFD);
208 return GNUNET_SYSERR;
209 if (i == (i | FD_CLOEXEC))
212 if (fcntl (h->fd, F_SETFD, i) < 0)
213 return GNUNET_SYSERR;
217 b = SetHandleInformation (h->fd, HANDLE_FLAG_INHERIT, 0);
220 SetErrnoFromWinsockError (WSAGetLastError ());
221 return GNUNET_SYSERR;
230 * The MSG_NOSIGNAL equivalent on Mac OS X
232 * @param h the socket to make non-delaying
235 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
240 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, &abs_value,
242 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
248 * Disable delays when sending data via the socket.
249 * (GNUnet makes sure that messages are as big as
252 * @param h the socket to make non-delaying
255 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
260 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
261 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
263 const char *abs_value = "1";
266 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, abs_value,
268 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
274 * Perform proper canonical initialization for a network handle.
275 * Set it to non-blocking, make it non-inheritable to child
276 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
277 * stream socket) and check that it is smaller than FS_SETSIZE.
279 * @param h socket to initialize
280 * @param af address family of the socket
281 * @param type socket type
282 * @return GNUNET_OK on success, GNUNET_SYSERR if initialization
283 * failed and the handle was destroyed
286 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
290 if (h->fd == INVALID_SOCKET)
293 SetErrnoFromWinsockError (WSAGetLastError ());
296 return GNUNET_SYSERR;
299 if (h->fd >= FD_SETSIZE)
301 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
303 return GNUNET_SYSERR;
306 if (GNUNET_OK != socket_set_inheritable (h))
307 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
308 "socket_set_inheritable");
310 if (GNUNET_SYSERR == socket_set_blocking (h, GNUNET_NO))
313 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
314 return GNUNET_SYSERR;
317 socket_set_nosigpipe (h);
319 if ( (type == SOCK_STREAM)
324 socket_set_nodelay (h);
330 * accept a new connection on a socket
332 * @param desc bound socket
333 * @param address address of the connecting peer, may be NULL
334 * @param address_len length of address
335 * @return client socket
337 struct GNUNET_NETWORK_Handle *
338 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
339 struct sockaddr *address, socklen_t * address_len)
341 struct GNUNET_NETWORK_Handle *ret;
343 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
346 struct sockaddr name;
347 socklen_t namelen = sizeof (name);
348 int gsn = getsockname (desc->fd, &name, &namelen);
351 LOG (GNUNET_ERROR_TYPE_DEBUG, "Accepting connection on `%s'\n",
352 GNUNET_a2s (&name, namelen));
355 ret->fd = accept (desc->fd, address, address_len);
356 if (GNUNET_OK != initialize_network_handle (ret,
357 (NULL != address) ? address->sa_family : desc->af,
365 * Bind to a connected socket
367 * @param address address to be bound
368 * @param address_len length of address
369 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
372 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
373 const struct sockaddr *address,
374 socklen_t address_len)
382 if (desc->af == AF_INET6)
383 if (0 != setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
384 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
388 /* This is required, and required here, but only on UNIX */
389 if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
390 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
394 if (address->sa_family == AF_UNIX)
396 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
398 (void) unlink (un->sun_path);
402 ret = bind (desc->fd, address, address_len);
404 if (SOCKET_ERROR == ret)
405 SetErrnoFromWinsockError (WSAGetLastError ());
408 return GNUNET_SYSERR;
411 desc->addr = GNUNET_malloc (address_len);
412 memcpy (desc->addr, address, address_len);
413 desc->addrlen = address_len;
423 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
426 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
434 ret = closesocket (desc->fd);
435 error = WSAGetLastError ();
436 SetErrnoFromWinsockError (error);
437 LOG (GNUNET_ERROR_TYPE_DEBUG,
438 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
441 ret = close (desc->fd);
445 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
447 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
449 if (0 != unlink (un->sun_path))
450 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
454 GNUNET_free_non_null (desc->addr);
456 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
461 * Box a native socket (and check that it is a socket).
463 * @param fd socket to box
464 * @return NULL on error (including not supported on target platform)
466 struct GNUNET_NETWORK_Handle *
467 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
469 struct GNUNET_NETWORK_Handle *ret;
473 /* FIXME: Find a better call to check that FD is valid */
474 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
475 return NULL; /* invalid FD */
476 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
481 if (fcntl (fd, F_GETFD) < 0)
482 return NULL; /* invalid FD */
483 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
494 * @param address peer address
495 * @param address_len length of address
496 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
499 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
500 const struct sockaddr *address,
501 socklen_t address_len)
505 ret = connect (desc->fd, address, address_len);
508 if (SOCKET_ERROR == ret)
510 SetErrnoFromWinsockError (WSAGetLastError ());
511 if (errno == EWOULDBLOCK)
515 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
523 * @param level protocol level of the option
524 * @param optname identifier of the option
525 * @param optval options
526 * @param optlen length of optval
527 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
530 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
531 int level, int optname, void *optval,
536 ret = getsockopt (desc->fd, level, optname, optval, optlen);
539 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
540 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
542 else if (SOCKET_ERROR == ret)
543 SetErrnoFromWinsockError (WSAGetLastError ());
545 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
552 * @param backlog length of the listen queue
553 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
556 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
561 ret = listen (desc->fd, backlog);
564 if (SOCKET_ERROR == ret)
565 SetErrnoFromWinsockError (WSAGetLastError ());
568 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
573 * How much data is available to be read on this descriptor?
575 * Returns GNUNET_NO if no data is available, or on error!
579 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
584 /* How much is there to be read? */
588 error = ioctl (desc->fd, FIONREAD, &pending);
590 return (ssize_t) pending;
595 error = ioctlsocket (desc->fd, FIONREAD, &pending);
596 if (error != SOCKET_ERROR)
597 return (ssize_t) pending;
604 * Read data from a connected socket (always non-blocking).
606 * @param buffer buffer
607 * @param length length of buffer
608 * @param src_addr either the source to recv from, or all zeroes
609 * to be filled in by recvfrom
610 * @param addrlen length of the addr
613 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
614 void *buffer, size_t length,
615 struct sockaddr * src_addr, socklen_t * addrlen)
623 flags |= MSG_DONTWAIT;
626 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
628 if (SOCKET_ERROR == ret)
629 SetErrnoFromWinsockError (WSAGetLastError ());
636 * Read data from a connected socket (always non-blocking).
638 * @param buffer buffer
639 * @param length length of buffer
642 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
643 void *buffer, size_t length)
651 flags |= MSG_DONTWAIT;
653 ret = recv (desc->fd, buffer, length, flags);
655 if (SOCKET_ERROR == ret)
656 SetErrnoFromWinsockError (WSAGetLastError ());
663 * Send data (always non-blocking).
666 * @param buffer data to send
667 * @param length size of the buffer
668 * @return number of bytes sent, GNUNET_SYSERR on error
671 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
672 const void *buffer, size_t length)
680 flags |= MSG_DONTWAIT;
684 flags |= MSG_NOSIGNAL;
687 ret = send (desc->fd, buffer, length, flags);
690 if (SOCKET_ERROR == ret)
691 SetErrnoFromWinsockError (WSAGetLastError ());
699 * Send data to a particular destination (always non-blocking).
700 * This function only works for UDP sockets.
703 * @param message data to send
704 * @param length size of the data
705 * @param dest_addr destination address
706 * @param dest_len length of address
707 * @return number of bytes sent, GNUNET_SYSERR on error
710 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
711 const void *message, size_t length,
712 const struct sockaddr * dest_addr,
721 flags |= MSG_DONTWAIT;
724 flags |= MSG_NOSIGNAL;
726 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
728 if (SOCKET_ERROR == ret)
729 SetErrnoFromWinsockError (WSAGetLastError ());
738 * @param level protocol level of the option
739 * @param option_name option identifier
740 * @param option_value value to set
741 * @param option_len size of option_value
742 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
745 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
746 int option_name, const void *option_value,
747 socklen_t option_len)
751 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
753 if (SOCKET_ERROR == ret)
754 SetErrnoFromWinsockError (WSAGetLastError ());
756 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
761 * Create a new socket. Configure it for non-blocking IO and
762 * mark it as non-inheritable to child processes (set the
763 * close-on-exec flag).
765 * @param domain domain of the socket
766 * @param type socket type
767 * @param protocol network protocol
768 * @return new socket, NULL on error
770 struct GNUNET_NETWORK_Handle *
771 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
773 struct GNUNET_NETWORK_Handle *ret;
775 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
776 ret->fd = socket (domain, type, protocol);
778 initialize_network_handle (ret, domain, type))
785 * Shut down socket operations
787 * @param how type of shutdown
788 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
791 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
795 ret = shutdown (desc->fd, how);
798 SetErrnoFromWinsockError (WSAGetLastError ());
800 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
805 * Disable the "CORK" feature for communication with the given socket,
806 * forcing the OS to immediately flush the buffer on transmission
807 * instead of potentially buffering multiple messages. Essentially
808 * reduces the OS send buffers to zero.
811 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
814 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
823 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
825 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
828 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
830 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
836 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
837 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
840 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
841 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
843 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
852 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
857 GNUNET_CONTAINER_slist_clear (fds->handles);
862 * Add a socket to the FD set
864 * @param desc socket to add
867 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
868 const struct GNUNET_NETWORK_Handle *desc)
870 FD_SET (desc->fd, &fds->sds);
871 if (desc->fd + 1 > fds->nsds)
872 fds->nsds = desc->fd + 1;
877 * Check whether a socket is part of the fd set
880 * @return 0 if the FD is not set
883 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
884 const struct GNUNET_NETWORK_Handle *desc)
886 return FD_ISSET (desc->fd, &fds->sds);
891 * Add one fd set to another
892 * @param dst the fd set to add to
893 * @param src the fd set to add from
896 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
897 const struct GNUNET_NETWORK_FDSet *src)
902 for (nfds = src->nsds; nfds > 0; nfds--)
903 if (FD_ISSET (nfds, &src->sds))
906 FD_SET (nfds, &dst->sds);
907 if (nfds + 1 > dst->nsds)
908 dst->nsds = nfds + 1;
911 /* This is MinGW32-specific implementation that relies on the code that
912 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
913 * that fd being added is not already in the set.
914 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
917 for (i = 0; i < src->sds.fd_count; i++)
918 FD_SET (src->sds.fd_array[i], &dst->sds);
919 if (src->nsds > dst->nsds)
920 dst->nsds = src->nsds;
922 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
928 * Copy one fd set to another
930 * @param to destination
934 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
935 const struct GNUNET_NETWORK_FDSet *from)
937 FD_COPY (&from->sds, &to->sds);
938 to->nsds = from->nsds;
941 GNUNET_CONTAINER_slist_clear (to->handles);
942 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
948 * Return file descriptor for this network handle
950 * @param desc wrapper to process
951 * @return POSIX file descriptor
954 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
960 * Return sockaddr for this network handle
962 * @param desc wrapper to process
966 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
972 * Return sockaddr length for this network handle
974 * @param desc wrapper to process
975 * @return socklen_t for sockaddr
978 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
980 return desc->addrlen;
983 * Copy a native fd set
985 * @param to destination
986 * @param from native source set
987 * @param nfds the biggest socket number in from + 1
990 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
991 const fd_set * from, int nfds)
993 FD_COPY (from, &to->sds);
999 * Set a native fd in a set
1001 * @param to destination
1002 * @param nfd native FD to set
1005 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1007 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1008 FD_SET (nfd, &to->sds);
1009 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1014 * Test native fd in a set
1016 * @param to set to test, NULL for empty set
1017 * @param nfd native FD to test, or -1 for none
1018 * @return GNUNET_YES if FD is set in the set
1021 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1024 if ((nfd == -1) || (to == NULL))
1026 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1031 * Add a file handle to the fd set
1033 * @param h the file handle to add
1036 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1037 const struct GNUNET_DISK_FileHandle *h)
1040 GNUNET_CONTAINER_slist_add (fds->handles,
1041 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1042 sizeof (struct GNUNET_DISK_FileHandle));
1047 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1048 FD_SET (fd, &fds->sds);
1049 if (fd + 1 > fds->nsds)
1057 * Check if a file handle is part of an fd set
1059 * @param h file handle
1060 * @return GNUNET_YES if the file handle is part of the set
1063 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1064 const struct GNUNET_DISK_FileHandle *h)
1068 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1070 GNUNET_DISK_FileHandle));
1072 return FD_ISSET (h->fd, &fds->sds);
1078 * Checks if two fd sets overlap
1079 * @param fds1 first fd set
1080 * @param fds2 second fd set
1081 * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
1084 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1085 const struct GNUNET_NETWORK_FDSet *fds2)
1091 if (nfds > fds2->nsds)
1096 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1100 struct GNUNET_CONTAINER_SList_Iterator it;
1101 struct GNUNET_DISK_FileHandle *h;
1105 /*This code is somewhat hacky, we are not supposed to know what's
1106 * inside of fd_set; also the O(n^2) is really bad... */
1108 for (i = 0; i < fds1->sds.fd_count; i++)
1110 for (j = 0; j < fds2->sds.fd_count; j++)
1112 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1116 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1117 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1120 struct GNUNET_CONTAINER_SList_Iterator t;
1122 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1125 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1127 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1128 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1129 GNUNET_CONTAINER_slist_next (&t))
1131 struct GNUNET_DISK_FileHandle *fh;
1133 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1135 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1138 if (GNUNET_CONTAINER_slist_contains
1139 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1143 GNUNET_CONTAINER_slist_next (&it);
1152 * @return a new fd set
1154 struct GNUNET_NETWORK_FDSet *
1155 GNUNET_NETWORK_fdset_create ()
1157 struct GNUNET_NETWORK_FDSet *fds;
1159 fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1161 fds->handles = GNUNET_CONTAINER_slist_create ();
1163 GNUNET_NETWORK_fdset_zero (fds);
1169 * Releases the associated memory of an fd set
1173 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1176 GNUNET_CONTAINER_slist_destroy (fds->handles);
1182 struct _select_params
1190 SOCKET wakeup_socket;
1195 _selector (LPVOID p)
1197 struct _select_params *sp = p;
1201 WaitForSingleObject (sp->standby, INFINITE);
1202 ResetEvent (sp->standby);
1203 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1204 if (FD_ISSET (sp->wakeup_socket, sp->r))
1206 FD_CLR (sp->wakeup_socket, sp->r);
1209 SetEvent (sp->wakeup);
1216 * Check if sockets or pipes meet certain conditions
1217 * @param rfds set of sockets or pipes to be checked for readability
1218 * @param wfds set of sockets or pipes to be checked for writability
1219 * @param efds set of sockets or pipes to be checked for exceptions
1220 * @param timeout relative value when to return
1221 * @return number of selected sockets or pipes, GNUNET_SYSERR on error
1224 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1225 struct GNUNET_NETWORK_FDSet *wfds,
1226 struct GNUNET_NETWORK_FDSet *efds,
1227 const struct GNUNET_TIME_Relative timeout)
1233 int read_handles = 0;
1234 int write_handles = 0;
1242 static HANDLE hEventPipeWrite = 0;
1243 static HANDLE hEventReadReady = 0;
1245 static struct _select_params sp;
1246 static HANDLE select_thread = NULL;
1247 static HANDLE select_finished_event = NULL;
1248 static HANDLE select_standby_event = NULL;
1249 static SOCKET select_wakeup_socket = -1;
1250 static SOCKET select_send_socket = -1;
1251 static struct timeval select_timeout;
1254 int writePipePos = 0;
1256 HANDLE handle_array[FD_SETSIZE + 2];
1257 int returncode = -1;
1258 int returnedpos = 0;
1260 struct GNUNET_CONTAINER_SList *handles_read;
1261 struct GNUNET_CONTAINER_SList *handles_write;
1262 struct GNUNET_CONTAINER_SList *handles_except;
1276 /* TODO: Make this growable */
1277 struct GNUNET_DISK_FileHandle *readArray[50];
1285 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1288 struct GNUNET_CONTAINER_SList_Iterator t;
1290 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1291 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1292 GNUNET_CONTAINER_slist_next (&t))
1294 struct GNUNET_DISK_FileHandle *fh;
1296 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1298 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1307 nfds = GNUNET_MAX (nfds, wfds->nsds);
1309 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1314 nfds = GNUNET_MAX (nfds, efds->nsds);
1316 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1321 (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1328 LOG (GNUNET_ERROR_TYPE_ERROR,
1330 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1334 tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1336 1000 * (timeout.rel_value -
1337 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1338 return select (nfds, (rfds != NULL) ? &rfds->sds : NULL,
1339 (wfds != NULL) ? &wfds->sds : NULL,
1340 (efds != NULL) ? &efds->sds : NULL,
1341 (timeout.rel_value ==
1342 GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ? NULL : &tv);
1345 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1346 /* calculate how long we need to wait in milliseconds */
1347 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1348 ms_total = INFINITE;
1351 ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1352 if (timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value > 0xFFFFFFFFLL - 1)
1355 ms_total = 0xFFFFFFFF - 1;
1358 /* select() may be used as a portable way to sleep */
1359 if (!(rfds || wfds || efds))
1365 if (select_thread == NULL)
1367 SOCKET select_listening_socket = -1;
1368 struct sockaddr_in s_in;
1373 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1374 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1376 select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1378 select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1381 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1383 alen = sizeof (s_in);
1384 s_in.sin_family = AF_INET;
1386 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1387 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1388 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1389 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1390 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1392 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1394 res = listen (select_listening_socket, SOMAXCONN);
1396 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1398 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1400 closesocket (select_listening_socket);
1402 sp.wakeup = select_finished_event;
1403 sp.standby = select_standby_event;
1404 sp.wakeup_socket = select_wakeup_socket;
1406 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1410 handles_read = GNUNET_CONTAINER_slist_create ();
1411 handles_write = GNUNET_CONTAINER_slist_create ();
1412 handles_except = GNUNET_CONTAINER_slist_create ();
1423 FD_COPY (&rfds->sds, &aread);
1425 FD_COPY (&rfds->sds, &bread);
1430 FD_COPY (&wfds->sds, &awrite);
1432 FD_COPY (&wfds->sds, &bwrite);
1437 FD_COPY (&efds->sds, &aexcept);
1439 FD_COPY (&efds->sds, &bexcept);
1443 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1444 By profiling we detected that to be true in 90% of the cases.
1447 /* Do the select now */
1448 select_timeout.tv_sec = 0;
1449 select_timeout.tv_usec = 0;
1451 /* Copy all the writes to the except, so we can detect connect() errors */
1452 for (i = 0; i < awrite.fd_count; i++)
1453 FD_SET (awrite.fd_array[i], &aexcept);
1454 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1455 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1456 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1459 if (selectret == -1)
1461 /* Throw an error early on, while we still have the context. */
1462 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1463 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1467 /* Check aexcept, add its contents to awrite
1468 This is technically wrong (aexcept might have its own descriptors), we should
1469 have checked that descriptors were in awrite originally before re-adding them from
1470 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1471 for (i = 0; i < aexcept.fd_count; i++)
1472 FD_SET (aexcept.fd_array[i], &awrite);
1474 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1475 /* Sadly, it means code duplication :( */
1476 if ((selectret > 0) || (ms_total == 0))
1479 if (rfds && read_handles)
1481 struct GNUNET_CONTAINER_SList_Iterator i;
1483 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1484 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1485 GNUNET_CONTAINER_slist_next (&i))
1487 struct GNUNET_DISK_FileHandle *fh;
1489 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1490 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1496 DWORD waitstatus = 0;
1497 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1498 error = GetLastError ();
1499 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1500 i, fh->h, bret, waitstatus, error);
1503 /* TODO: either add more errors to this condition, or eliminate it
1504 * entirely (failed to peek -> pipe is in serious trouble, should
1505 * be selected as readable).
1507 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1510 else if (waitstatus <= 0)
1512 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1513 fh, sizeof (struct GNUNET_DISK_FileHandle));
1515 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1520 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1521 fh, sizeof (struct GNUNET_DISK_FileHandle));
1526 if (wfds && write_handles)
1528 LOG (GNUNET_ERROR_TYPE_DEBUG,
1529 "Adding the write ready event to the array as %d\n", nhandles);
1530 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1531 retcode += write_handles;
1533 if (efds && ex_handles)
1535 struct GNUNET_CONTAINER_SList_Iterator i;
1537 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1538 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1539 GNUNET_CONTAINER_slist_next (&i))
1541 struct GNUNET_DISK_FileHandle *fh;
1544 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1545 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1547 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1549 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1550 fh, sizeof (struct GNUNET_DISK_FileHandle));
1556 /* Add our select() result.*/
1558 retcode += selectret;
1562 GNUNET_NETWORK_fdset_zero (rfds);
1563 if (selectret != -1)
1564 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1565 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1569 GNUNET_NETWORK_fdset_zero (wfds);
1570 if (selectret != -1)
1571 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1572 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1576 GNUNET_NETWORK_fdset_zero (efds);
1577 if (selectret != -1)
1578 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1579 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1581 GNUNET_CONTAINER_slist_destroy (handles_read);
1582 GNUNET_CONTAINER_slist_destroy (handles_write);
1583 GNUNET_CONTAINER_slist_destroy (handles_except);
1585 if (selectret == -1)
1590 /* If we got this far, use slower implementation that is able to do a waiting select
1591 on both sockets and pipes simultaneously */
1593 /* Events for pipes */
1594 if (!hEventReadReady)
1595 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1596 if (!hEventPipeWrite)
1597 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1613 FD_COPY (&rfds->sds, &aread);
1615 FD_COPY (&rfds->sds, &bread);
1620 FD_COPY (&wfds->sds, &awrite);
1622 FD_COPY (&wfds->sds, &bwrite);
1627 FD_COPY (&efds->sds, &aexcept);
1629 FD_COPY (&efds->sds, &bexcept);
1632 /* We will first Add the PIPES to the events */
1634 if (rfds && read_handles)
1636 struct GNUNET_CONTAINER_SList_Iterator i;
1638 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1639 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1640 GNUNET_CONTAINER_slist_next (&i))
1642 struct GNUNET_DISK_FileHandle *fh;
1644 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1646 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1648 /* Read zero bytes to check the status of the pipe */
1649 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1651 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1653 DWORD error_code = GetLastError ();
1655 if (error_code == ERROR_IO_PENDING)
1657 LOG (GNUNET_ERROR_TYPE_DEBUG,
1658 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1660 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1661 readArray[readPipes++] = fh;
1665 LOG (GNUNET_ERROR_TYPE_DEBUG,
1666 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1667 handle_array[nhandles++] = hEventReadReady;
1668 readArray[readPipes++] = fh;
1673 LOG (GNUNET_ERROR_TYPE_DEBUG,
1674 "Adding the read ready event to the array as %d\n", nhandles);
1675 handle_array[nhandles++] = hEventReadReady;
1676 readArray[readPipes++] = fh;
1681 GNUNET_CONTAINER_slist_add (handles_read,
1682 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1683 fh, sizeof (struct GNUNET_DISK_FileHandle));
1687 if (wfds && write_handles)
1689 LOG (GNUNET_ERROR_TYPE_DEBUG,
1690 "Adding the write ready event to the array as %d\n", nhandles);
1691 handle_array[nhandles++] = hEventPipeWrite;
1692 writePipePos = nhandles;
1694 if (efds && ex_handles)
1696 struct GNUNET_CONTAINER_SList_Iterator i;
1698 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1699 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1700 GNUNET_CONTAINER_slist_next (&i))
1702 struct GNUNET_DISK_FileHandle *fh;
1705 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1707 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1709 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1711 GNUNET_CONTAINER_slist_add (handles_except,
1712 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1714 sizeof (struct GNUNET_DISK_FileHandle));
1724 LOG (GNUNET_ERROR_TYPE_DEBUG,
1725 "Adding the socket event to the array as %d\n", nhandles);
1726 handle_array[nhandles++] = select_finished_event;
1727 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1731 select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1732 select_timeout.tv_usec = 1000 * (timeout.rel_value -
1733 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1734 sp.tv = &select_timeout;
1736 FD_SET (select_wakeup_socket, &aread);
1740 /* Failed connections cause sockets to be set in errorfds on W32,
1741 * but on POSIX it should set them in writefds.
1742 * First copy all awrite sockets to aexcept, later we'll
1743 * check aexcept and set its contents in awrite as well
1744 * Sockets are also set in errorfds when OOB data is available,
1745 * but we don't use OOB data.
1747 for (i = 0; i < awrite.fd_count; i++)
1748 FD_SET (awrite.fd_array[i], &aexcept);
1749 ResetEvent (select_finished_event);
1750 SetEvent (select_standby_event);
1753 handle_array[nhandles] = NULL;
1754 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n",
1755 nfds, nhandles, (unsigned long long) ms_total);
1759 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1760 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1765 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1766 returncode = WAIT_TIMEOUT;
1770 /* Shouldn't come this far. If it does - investigate. */
1776 /* Don't wake up select-thread when delay is 0, it should return immediately
1777 * and wake up by itself.
1780 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1781 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1782 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1787 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1790 /* Check aexcept, add its contents to awrite */
1791 for (i = 0; i < aexcept.fd_count; i++)
1792 FD_SET (aexcept.fd_array[i], &awrite);
1795 returnedpos = returncode - WAIT_OBJECT_0;
1796 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1798 if (nhandles && (returnedpos < nhandles))
1803 retcode += sp.status;
1805 if ((writePipePos != -1) && (returnedpos < writePipePos))
1807 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1808 retcode += write_handles;
1809 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1811 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1812 /* We have some pipes ready for read. */
1813 if (returnedpos < readPipes)
1815 for (i = 0; i < readPipes; i++)
1823 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1824 error = GetLastError ();
1825 LOG (GNUNET_ERROR_TYPE_DEBUG,
1826 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1827 i, readArray[i]->h, bret, waitstatus, error);
1830 /* TODO: either add more errors to this condition, or eliminate it
1831 * entirely (failed to peek -> pipe is in serious trouble, should
1832 * be selected as readable).
1834 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1837 else if (waitstatus <= 0)
1839 GNUNET_CONTAINER_slist_add (handles_read,
1840 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1842 sizeof (struct GNUNET_DISK_FileHandle));
1844 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1845 readArray[i], readArray[i]->h);
1849 if (!nhandles || (returnedpos >= nhandles))
1850 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1853 struct GNUNET_CONTAINER_SList_Iterator t;
1855 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1856 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1857 GNUNET_CONTAINER_slist_next (&t))
1859 struct GNUNET_DISK_FileHandle *fh;
1861 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1863 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1868 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1869 GNUNET_NETWORK_fdset_zero (rfds);
1870 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1871 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1872 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1876 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1877 GNUNET_NETWORK_fdset_zero (wfds);
1878 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1879 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1880 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1884 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1885 GNUNET_NETWORK_fdset_zero (efds);
1886 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1887 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1888 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1890 GNUNET_CONTAINER_slist_destroy (handles_read);
1891 GNUNET_CONTAINER_slist_destroy (handles_write);
1892 GNUNET_CONTAINER_slist_destroy (handles_except);
1896 struct GNUNET_CONTAINER_SList_Iterator t;
1898 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1899 for (i = 0; i < rfds->sds.fd_count; i++)
1901 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1903 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1904 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1905 GNUNET_CONTAINER_slist_next (&t))
1907 struct GNUNET_DISK_FileHandle *fh;
1909 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1911 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1916 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1917 for (i = 0; i < wfds->sds.fd_count; i++)
1919 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1924 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1925 for (i = 0; i < efds->sds.fd_count; i++)
1927 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1930 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1932 if (nhandles && (returnedpos < nhandles))
1939 /* end of network.c */