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)
901 for (nfds = src->nsds; nfds > 0; nfds--)
902 if (FD_ISSET (nfds, &src->sds))
905 FD_SET (nfds, &dst->sds);
906 if (nfds + 1 > dst->nsds)
907 dst->nsds = nfds + 1;
910 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
916 * Copy one fd set to another
918 * @param to destination
922 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
923 const struct GNUNET_NETWORK_FDSet *from)
925 FD_COPY (&from->sds, &to->sds);
926 to->nsds = from->nsds;
929 GNUNET_CONTAINER_slist_clear (to->handles);
930 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
936 * Return file descriptor for this network handle
938 * @param desc wrapper to process
939 * @return POSIX file descriptor
942 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
948 * Return sockaddr for this network handle
950 * @param desc wrapper to process
954 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
960 * Return sockaddr length for this network handle
962 * @param desc wrapper to process
963 * @return socklen_t for sockaddr
966 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
968 return desc->addrlen;
971 * Copy a native fd set
973 * @param to destination
974 * @param from native source set
975 * @param nfds the biggest socket number in from + 1
978 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
979 const fd_set * from, int nfds)
981 FD_COPY (from, &to->sds);
987 * Set a native fd in a set
989 * @param to destination
990 * @param nfd native FD to set
993 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
995 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
996 FD_SET (nfd, &to->sds);
997 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1002 * Test native fd in a set
1004 * @param to set to test, NULL for empty set
1005 * @param nfd native FD to test, or -1 for none
1006 * @return GNUNET_YES if FD is set in the set
1009 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1012 if ((nfd == -1) || (to == NULL))
1014 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1019 * Add a file handle to the fd set
1021 * @param h the file handle to add
1024 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1025 const struct GNUNET_DISK_FileHandle *h)
1028 GNUNET_CONTAINER_slist_add (fds->handles,
1029 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1030 sizeof (struct GNUNET_DISK_FileHandle));
1035 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1036 FD_SET (fd, &fds->sds);
1037 if (fd + 1 > fds->nsds)
1045 * Check if a file handle is part of an fd set
1047 * @param h file handle
1048 * @return GNUNET_YES if the file handle is part of the set
1051 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1052 const struct GNUNET_DISK_FileHandle *h)
1056 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1058 GNUNET_DISK_FileHandle));
1060 return FD_ISSET (h->fd, &fds->sds);
1066 * Checks if two fd sets overlap
1067 * @param fds1 first fd set
1068 * @param fds2 second fd set
1069 * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
1072 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1073 const struct GNUNET_NETWORK_FDSet *fds2)
1079 if (nfds > fds2->nsds)
1084 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1088 struct GNUNET_CONTAINER_SList_Iterator it;
1089 struct GNUNET_DISK_FileHandle *h;
1093 /*This code is somewhat hacky, we are not supposed to know what's
1094 * inside of fd_set; also the O(n^2) is really bad... */
1096 for (i = 0; i < fds1->sds.fd_count; i++)
1098 for (j = 0; j < fds2->sds.fd_count; j++)
1100 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1104 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1105 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1108 struct GNUNET_CONTAINER_SList_Iterator t;
1110 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1113 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1115 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1116 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1117 GNUNET_CONTAINER_slist_next (&t))
1119 struct GNUNET_DISK_FileHandle *fh;
1121 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1123 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1126 if (GNUNET_CONTAINER_slist_contains
1127 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1131 GNUNET_CONTAINER_slist_next (&it);
1140 * @return a new fd set
1142 struct GNUNET_NETWORK_FDSet *
1143 GNUNET_NETWORK_fdset_create ()
1145 struct GNUNET_NETWORK_FDSet *fds;
1147 fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1149 fds->handles = GNUNET_CONTAINER_slist_create ();
1151 GNUNET_NETWORK_fdset_zero (fds);
1157 * Releases the associated memory of an fd set
1161 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1164 GNUNET_CONTAINER_slist_destroy (fds->handles);
1170 struct _select_params
1178 SOCKET wakeup_socket;
1183 _selector (LPVOID p)
1185 struct _select_params *sp = p;
1189 WaitForSingleObject (sp->standby, INFINITE);
1190 ResetEvent (sp->standby);
1191 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1192 if (FD_ISSET (sp->wakeup_socket, sp->r))
1194 FD_CLR (sp->wakeup_socket, sp->r);
1197 SetEvent (sp->wakeup);
1204 * Check if sockets or pipes meet certain conditions
1205 * @param rfds set of sockets or pipes to be checked for readability
1206 * @param wfds set of sockets or pipes to be checked for writability
1207 * @param efds set of sockets or pipes to be checked for exceptions
1208 * @param timeout relative value when to return
1209 * @return number of selected sockets or pipes, GNUNET_SYSERR on error
1212 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1213 struct GNUNET_NETWORK_FDSet *wfds,
1214 struct GNUNET_NETWORK_FDSet *efds,
1215 const struct GNUNET_TIME_Relative timeout)
1221 int read_handles = 0;
1222 int write_handles = 0;
1230 static HANDLE hEventPipeWrite = 0;
1231 static HANDLE hEventReadReady = 0;
1233 static struct _select_params sp;
1234 static HANDLE select_thread = NULL;
1235 static HANDLE select_finished_event = NULL;
1236 static HANDLE select_standby_event = NULL;
1237 static SOCKET select_wakeup_socket = -1;
1238 static SOCKET select_send_socket = -1;
1239 static struct timeval select_timeout;
1242 int writePipePos = 0;
1244 HANDLE handle_array[FD_SETSIZE + 2];
1245 int returncode = -1;
1246 int returnedpos = 0;
1248 struct GNUNET_CONTAINER_SList *handles_read;
1249 struct GNUNET_CONTAINER_SList *handles_write;
1250 struct GNUNET_CONTAINER_SList *handles_except;
1264 /* TODO: Make this growable */
1265 struct GNUNET_DISK_FileHandle *readArray[50];
1273 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1276 struct GNUNET_CONTAINER_SList_Iterator t;
1278 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1279 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1280 GNUNET_CONTAINER_slist_next (&t))
1282 struct GNUNET_DISK_FileHandle *fh;
1284 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1286 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1295 nfds = GNUNET_MAX (nfds, wfds->nsds);
1297 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1302 nfds = GNUNET_MAX (nfds, efds->nsds);
1304 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1309 (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1316 LOG (GNUNET_ERROR_TYPE_ERROR,
1318 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1322 tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1324 1000 * (timeout.rel_value -
1325 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1326 return select (nfds, (rfds != NULL) ? &rfds->sds : NULL,
1327 (wfds != NULL) ? &wfds->sds : NULL,
1328 (efds != NULL) ? &efds->sds : NULL,
1329 (timeout.rel_value ==
1330 GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ? NULL : &tv);
1333 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1334 /* calculate how long we need to wait in milliseconds */
1335 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1336 ms_total = INFINITE;
1339 ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1340 if (timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value > 0xFFFFFFFFLL - 1)
1343 ms_total = 0xFFFFFFFF - 1;
1346 /* select() may be used as a portable way to sleep */
1347 if (!(rfds || wfds || efds))
1353 if (select_thread == NULL)
1355 SOCKET select_listening_socket = -1;
1356 struct sockaddr_in s_in;
1361 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1362 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1364 select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1366 select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1369 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1371 alen = sizeof (s_in);
1372 s_in.sin_family = AF_INET;
1374 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1375 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1376 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1377 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1378 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1380 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1382 res = listen (select_listening_socket, SOMAXCONN);
1384 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1386 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1388 closesocket (select_listening_socket);
1390 sp.wakeup = select_finished_event;
1391 sp.standby = select_standby_event;
1392 sp.wakeup_socket = select_wakeup_socket;
1394 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1398 handles_read = GNUNET_CONTAINER_slist_create ();
1399 handles_write = GNUNET_CONTAINER_slist_create ();
1400 handles_except = GNUNET_CONTAINER_slist_create ();
1411 FD_COPY (&rfds->sds, &aread);
1413 FD_COPY (&rfds->sds, &bread);
1418 FD_COPY (&wfds->sds, &awrite);
1420 FD_COPY (&wfds->sds, &bwrite);
1425 FD_COPY (&efds->sds, &aexcept);
1427 FD_COPY (&efds->sds, &bexcept);
1431 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1432 By profiling we detected that to be true in 90% of the cases.
1435 /* Do the select now */
1436 select_timeout.tv_sec = 0;
1437 select_timeout.tv_usec = 0;
1439 /* Copy all the writes to the except, so we can detect connect() errors */
1440 for (i = 0; i < awrite.fd_count; i++)
1442 if (awrite.fd_array[i] != 0 && awrite.fd_array[i] != -1)
1443 FD_SET (awrite.fd_array[i], &aexcept);
1445 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1446 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1447 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1450 if (selectret == -1)
1452 /* Throw an error early on, while we still have the context. */
1453 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1454 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1458 /* Check aexcept, add its contents to awrite
1459 This is technically wrong (aexcept might have its own descriptors), we should
1460 have checked that descriptors were in awrite originally before re-adding them from
1461 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1462 for (i = 0; i < aexcept.fd_count; i++)
1464 if (aexcept.fd_array[i] != 0 && aexcept.fd_array[i] != -1)
1465 FD_SET (aexcept.fd_array[i], &awrite);
1468 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1469 /* Sadly, it means code duplication :( */
1470 if ((selectret > 0) || (ms_total == 0))
1473 if (rfds && read_handles)
1475 struct GNUNET_CONTAINER_SList_Iterator i;
1477 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1478 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1479 GNUNET_CONTAINER_slist_next (&i))
1481 struct GNUNET_DISK_FileHandle *fh;
1483 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1484 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1490 DWORD waitstatus = 0;
1491 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1492 error = GetLastError ();
1493 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1494 i, fh->h, bret, waitstatus, error);
1497 /* TODO: either add more errors to this condition, or eliminate it
1498 * entirely (failed to peek -> pipe is in serious trouble, should
1499 * be selected as readable).
1501 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1504 else if (waitstatus <= 0)
1506 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1507 fh, sizeof (struct GNUNET_DISK_FileHandle));
1509 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1514 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1515 fh, sizeof (struct GNUNET_DISK_FileHandle));
1520 if (wfds && write_handles)
1522 LOG (GNUNET_ERROR_TYPE_DEBUG,
1523 "Adding the write ready event to the array as %d\n", nhandles);
1524 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1525 retcode += write_handles;
1527 if (efds && ex_handles)
1529 struct GNUNET_CONTAINER_SList_Iterator i;
1531 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1532 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1533 GNUNET_CONTAINER_slist_next (&i))
1535 struct GNUNET_DISK_FileHandle *fh;
1538 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1539 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1541 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1543 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1544 fh, sizeof (struct GNUNET_DISK_FileHandle));
1550 /* Add our select() result.*/
1552 retcode += selectret;
1556 GNUNET_NETWORK_fdset_zero (rfds);
1557 if (selectret != -1)
1558 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1559 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1563 GNUNET_NETWORK_fdset_zero (wfds);
1564 if (selectret != -1)
1565 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1566 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1570 GNUNET_NETWORK_fdset_zero (efds);
1571 if (selectret != -1)
1572 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1573 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1575 GNUNET_CONTAINER_slist_destroy (handles_read);
1576 GNUNET_CONTAINER_slist_destroy (handles_write);
1577 GNUNET_CONTAINER_slist_destroy (handles_except);
1579 if (selectret == -1)
1584 /* If we got this far, use slower implementation that is able to do a waiting select
1585 on both sockets and pipes simultaneously */
1587 /* Events for pipes */
1588 if (!hEventReadReady)
1589 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1590 if (!hEventPipeWrite)
1591 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1607 FD_COPY (&rfds->sds, &aread);
1609 FD_COPY (&rfds->sds, &bread);
1614 FD_COPY (&wfds->sds, &awrite);
1616 FD_COPY (&wfds->sds, &bwrite);
1621 FD_COPY (&efds->sds, &aexcept);
1623 FD_COPY (&efds->sds, &bexcept);
1626 /* We will first Add the PIPES to the events */
1628 if (rfds && read_handles)
1630 struct GNUNET_CONTAINER_SList_Iterator i;
1632 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1633 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1634 GNUNET_CONTAINER_slist_next (&i))
1636 struct GNUNET_DISK_FileHandle *fh;
1638 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1640 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1642 /* Read zero bytes to check the status of the pipe */
1643 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1645 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1647 DWORD error_code = GetLastError ();
1649 if (error_code == ERROR_IO_PENDING)
1651 LOG (GNUNET_ERROR_TYPE_DEBUG,
1652 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1654 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1655 readArray[readPipes++] = fh;
1659 LOG (GNUNET_ERROR_TYPE_DEBUG,
1660 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1661 handle_array[nhandles++] = hEventReadReady;
1662 readArray[readPipes++] = fh;
1667 LOG (GNUNET_ERROR_TYPE_DEBUG,
1668 "Adding the read ready event to the array as %d\n", nhandles);
1669 handle_array[nhandles++] = hEventReadReady;
1670 readArray[readPipes++] = fh;
1675 GNUNET_CONTAINER_slist_add (handles_read,
1676 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1677 fh, sizeof (struct GNUNET_DISK_FileHandle));
1681 if (wfds && write_handles)
1683 LOG (GNUNET_ERROR_TYPE_DEBUG,
1684 "Adding the write ready event to the array as %d\n", nhandles);
1685 handle_array[nhandles++] = hEventPipeWrite;
1686 writePipePos = nhandles;
1688 if (efds && ex_handles)
1690 struct GNUNET_CONTAINER_SList_Iterator i;
1692 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1693 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1694 GNUNET_CONTAINER_slist_next (&i))
1696 struct GNUNET_DISK_FileHandle *fh;
1699 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1701 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1703 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1705 GNUNET_CONTAINER_slist_add (handles_except,
1706 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1708 sizeof (struct GNUNET_DISK_FileHandle));
1718 LOG (GNUNET_ERROR_TYPE_DEBUG,
1719 "Adding the socket event to the array as %d\n", nhandles);
1720 handle_array[nhandles++] = select_finished_event;
1721 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1725 select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1726 select_timeout.tv_usec = 1000 * (timeout.rel_value -
1727 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1728 sp.tv = &select_timeout;
1730 FD_SET (select_wakeup_socket, &aread);
1734 /* Failed connections cause sockets to be set in errorfds on W32,
1735 * but on POSIX it should set them in writefds.
1736 * First copy all awrite sockets to aexcept, later we'll
1737 * check aexcept and set its contents in awrite as well
1738 * Sockets are also set in errorfds when OOB data is available,
1739 * but we don't use OOB data.
1741 for (i = 0; i < awrite.fd_count; i++)
1743 if (awrite.fd_array[i] != 0 && awrite.fd_array[i] != -1)
1744 FD_SET (awrite.fd_array[i], &aexcept);
1746 ResetEvent (select_finished_event);
1747 SetEvent (select_standby_event);
1750 handle_array[nhandles] = NULL;
1751 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n",
1752 nfds, nhandles, (unsigned long long) ms_total);
1756 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1757 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1762 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1763 returncode = WAIT_TIMEOUT;
1767 /* Shouldn't come this far. If it does - investigate. */
1773 /* Don't wake up select-thread when delay is 0, it should return immediately
1774 * and wake up by itself.
1777 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1778 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1779 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1784 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1787 /* Check aexcept, add its contents to awrite */
1788 for (i = 0; i < aexcept.fd_count; i++)
1790 if (aexcept.fd_array[i] != 0 && aexcept.fd_array[i] != -1)
1791 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 */