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 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
71 * shorten it to an acceptable length while keeping it unique
72 * and making sure it remains a valid filename (if possible).
74 * @param unixpath long path, will be freed (or same pointer returned
75 * with moved 0-termination).
76 * @return shortened unixpath, NULL on error
79 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
81 struct sockaddr_un dummy;
84 struct GNUNET_CRYPTO_ShortHashCode sh;
85 struct GNUNET_CRYPTO_ShortHashAsciiEncoded ae;
88 upm = sizeof (dummy.sun_path);
89 slen = strlen (unixpath);
91 return unixpath; /* no shortening required */
92 GNUNET_CRYPTO_short_hash (unixpath, slen, &sh);
93 while (sizeof (struct GNUNET_CRYPTO_ShortHashAsciiEncoded) +
94 strlen (unixpath) >= upm)
96 if (NULL == (end = strrchr (unixpath, '/')))
98 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
99 _("Unable to shorten unix path `%s' while keeping name unique\n"),
101 GNUNET_free (unixpath);
106 GNUNET_CRYPTO_short_hash_to_enc (&sh, &ae);
107 strcat (unixpath, (char*) ae.short_encoding);
113 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
118 * Set if a socket should use blocking or non-blocking IO.
120 * @param doBlock blocking mode
121 * @return GNUNET_OK on success, GNUNET_SYSERR on error
124 socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
131 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
134 SetErrnoFromWinsockError (WSAGetLastError ());
135 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
136 return GNUNET_SYSERR;
142 int flags = fcntl (fd->fd, F_GETFL);
147 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
148 return GNUNET_SYSERR;
151 flags &= ~O_NONBLOCK;
155 if (0 != fcntl (fd->fd, F_SETFL, flags))
158 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
159 return GNUNET_SYSERR;
167 * Make a socket non-inheritable to child processes
169 * @param h the socket to make non-inheritable
170 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
171 * @warning Not implemented on Windows
174 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
178 i = fcntl (h->fd, F_GETFD);
180 return GNUNET_SYSERR;
181 if (i == (i | FD_CLOEXEC))
184 if (fcntl (h->fd, F_SETFD, i) < 0)
185 return GNUNET_SYSERR;
189 b = SetHandleInformation (h->fd, HANDLE_FLAG_INHERIT, 0);
192 SetErrnoFromWinsockError (WSAGetLastError ());
193 return GNUNET_SYSERR;
202 * The MSG_NOSIGNAL equivalent on Mac OS X
204 * @param h the socket to make non-delaying
207 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
212 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, &abs_value,
214 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
220 * Disable delays when sending data via the socket.
221 * (GNUnet makes sure that messages are as big as
224 * @param h the socket to make non-delaying
227 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
232 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
233 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
235 const char *abs_value = "1";
238 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, abs_value,
240 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
246 * Perform proper canonical initialization for a network handle.
247 * Set it to non-blocking, make it non-inheritable to child
248 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
249 * stream socket) and check that it is smaller than FS_SETSIZE.
251 * @param h socket to initialize
252 * @param af address family of the socket
253 * @param type socket type
254 * @return GNUNET_OK on success, GNUNET_SYSERR if initialization
255 * failed and the handle was destroyed
258 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
262 if (h->fd == INVALID_SOCKET)
265 SetErrnoFromWinsockError (WSAGetLastError ());
268 return GNUNET_SYSERR;
271 if (h->fd >= FD_SETSIZE)
273 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
275 return GNUNET_SYSERR;
278 if (GNUNET_OK != socket_set_inheritable (h))
279 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
280 "socket_set_inheritable");
282 if (GNUNET_SYSERR == socket_set_blocking (h, GNUNET_NO))
285 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
286 return GNUNET_SYSERR;
289 socket_set_nosigpipe (h);
291 if ( (type == SOCK_STREAM)
296 socket_set_nodelay (h);
302 * accept a new connection on a socket
304 * @param desc bound socket
305 * @param address address of the connecting peer, may be NULL
306 * @param address_len length of address
307 * @return client socket
309 struct GNUNET_NETWORK_Handle *
310 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
311 struct sockaddr *address, socklen_t * address_len)
313 struct GNUNET_NETWORK_Handle *ret;
315 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
318 struct sockaddr name;
319 socklen_t namelen = sizeof (name);
320 int gsn = getsockname (desc->fd, &name, &namelen);
323 LOG (GNUNET_ERROR_TYPE_DEBUG, "Accepting connection on `%s'\n",
324 GNUNET_a2s (&name, namelen));
327 ret->fd = accept (desc->fd, address, address_len);
328 if (GNUNET_OK != initialize_network_handle (ret,
329 (NULL != address) ? address->sa_family : desc->af,
337 * Bind to a connected socket
339 * @param address address to be bound
340 * @param address_len length of address
341 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
344 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
345 const struct sockaddr *address,
346 socklen_t address_len)
354 if (desc->af == AF_INET6)
355 if (0 != setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
356 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
360 /* This is required, and required here, but only on UNIX */
361 if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
362 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
366 if (address->sa_family == AF_UNIX)
368 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
370 (void) unlink (un->sun_path);
374 ret = bind (desc->fd, address, address_len);
376 if (SOCKET_ERROR == ret)
377 SetErrnoFromWinsockError (WSAGetLastError ());
380 return GNUNET_SYSERR;
383 desc->addr = GNUNET_malloc (address_len);
384 memcpy (desc->addr, address, address_len);
385 desc->addrlen = address_len;
395 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
398 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
406 ret = closesocket (desc->fd);
407 error = WSAGetLastError ();
408 SetErrnoFromWinsockError (error);
409 LOG (GNUNET_ERROR_TYPE_DEBUG,
410 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
413 ret = close (desc->fd);
417 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
419 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
421 if (0 != unlink (un->sun_path))
422 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
426 GNUNET_free_non_null (desc->addr);
428 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
433 * Box a native socket (and check that it is a socket).
435 * @param fd socket to box
436 * @return NULL on error (including not supported on target platform)
438 struct GNUNET_NETWORK_Handle *
439 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
441 struct GNUNET_NETWORK_Handle *ret;
445 /* FIXME: Find a better call to check that FD is valid */
446 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
447 return NULL; /* invalid FD */
448 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
453 if (fcntl (fd, F_GETFD) < 0)
454 return NULL; /* invalid FD */
455 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
466 * @param address peer address
467 * @param address_len length of address
468 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
471 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
472 const struct sockaddr *address,
473 socklen_t address_len)
477 ret = connect (desc->fd, address, address_len);
480 if (SOCKET_ERROR == ret)
482 SetErrnoFromWinsockError (WSAGetLastError ());
483 if (errno == EWOULDBLOCK)
487 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
495 * @param level protocol level of the option
496 * @param optname identifier of the option
497 * @param optval options
498 * @param optlen length of optval
499 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
502 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
503 int level, int optname, void *optval,
508 ret = getsockopt (desc->fd, level, optname, optval, optlen);
511 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
512 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
514 else if (SOCKET_ERROR == ret)
515 SetErrnoFromWinsockError (WSAGetLastError ());
517 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
524 * @param backlog length of the listen queue
525 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
528 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
533 ret = listen (desc->fd, backlog);
536 if (SOCKET_ERROR == ret)
537 SetErrnoFromWinsockError (WSAGetLastError ());
540 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
545 * How much data is available to be read on this descriptor?
547 * Returns GNUNET_NO if no data is available, or on error!
551 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
556 /* How much is there to be read? */
560 error = ioctl (desc->fd, FIONREAD, &pending);
562 return (ssize_t) pending;
567 error = ioctlsocket (desc->fd, FIONREAD, &pending);
568 if (error != SOCKET_ERROR)
569 return (ssize_t) pending;
576 * Read data from a connected socket (always non-blocking).
578 * @param buffer buffer
579 * @param length length of buffer
580 * @param src_addr either the source to recv from, or all zeroes
581 * to be filled in by recvfrom
582 * @param addrlen length of the addr
585 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
586 void *buffer, size_t length,
587 struct sockaddr * src_addr, socklen_t * addrlen)
595 flags |= MSG_DONTWAIT;
598 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
600 if (SOCKET_ERROR == ret)
601 SetErrnoFromWinsockError (WSAGetLastError ());
608 * Read data from a connected socket (always non-blocking).
610 * @param buffer buffer
611 * @param length length of buffer
614 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
615 void *buffer, size_t length)
623 flags |= MSG_DONTWAIT;
625 ret = recv (desc->fd, buffer, length, flags);
627 if (SOCKET_ERROR == ret)
628 SetErrnoFromWinsockError (WSAGetLastError ());
635 * Send data (always non-blocking).
638 * @param buffer data to send
639 * @param length size of the buffer
640 * @return number of bytes sent, GNUNET_SYSERR on error
643 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
644 const void *buffer, size_t length)
652 flags |= MSG_DONTWAIT;
656 flags |= MSG_NOSIGNAL;
659 ret = send (desc->fd, buffer, length, flags);
662 if (SOCKET_ERROR == ret)
663 SetErrnoFromWinsockError (WSAGetLastError ());
671 * Send data to a particular destination (always non-blocking).
672 * This function only works for UDP sockets.
675 * @param message data to send
676 * @param length size of the data
677 * @param dest_addr destination address
678 * @param dest_len length of address
679 * @return number of bytes sent, GNUNET_SYSERR on error
682 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
683 const void *message, size_t length,
684 const struct sockaddr * dest_addr,
693 flags |= MSG_DONTWAIT;
696 flags |= MSG_NOSIGNAL;
698 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
700 if (SOCKET_ERROR == ret)
701 SetErrnoFromWinsockError (WSAGetLastError ());
710 * @param level protocol level of the option
711 * @param option_name option identifier
712 * @param option_value value to set
713 * @param option_len size of option_value
714 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
717 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
718 int option_name, const void *option_value,
719 socklen_t option_len)
723 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
725 if (SOCKET_ERROR == ret)
726 SetErrnoFromWinsockError (WSAGetLastError ());
728 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
733 * Create a new socket. Configure it for non-blocking IO and
734 * mark it as non-inheritable to child processes (set the
735 * close-on-exec flag).
737 * @param domain domain of the socket
738 * @param type socket type
739 * @param protocol network protocol
740 * @return new socket, NULL on error
742 struct GNUNET_NETWORK_Handle *
743 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
745 struct GNUNET_NETWORK_Handle *ret;
747 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
748 ret->fd = socket (domain, type, protocol);
750 initialize_network_handle (ret, domain, type))
757 * Shut down socket operations
759 * @param how type of shutdown
760 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
763 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
767 ret = shutdown (desc->fd, how);
770 SetErrnoFromWinsockError (WSAGetLastError ());
772 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
777 * Disable the "CORK" feature for communication with the given socket,
778 * forcing the OS to immediately flush the buffer on transmission
779 * instead of potentially buffering multiple messages. Essentially
780 * reduces the OS send buffers to zero.
783 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
786 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
795 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
797 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
800 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
802 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
808 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
809 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
812 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
813 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
815 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
824 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
829 GNUNET_CONTAINER_slist_clear (fds->handles);
834 * Add a socket to the FD set
836 * @param desc socket to add
839 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
840 const struct GNUNET_NETWORK_Handle *desc)
842 FD_SET (desc->fd, &fds->sds);
843 if (desc->fd + 1 > fds->nsds)
844 fds->nsds = desc->fd + 1;
849 * Check whether a socket is part of the fd set
852 * @return 0 if the FD is not set
855 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
856 const struct GNUNET_NETWORK_Handle *desc)
858 return FD_ISSET (desc->fd, &fds->sds);
863 * Add one fd set to another
864 * @param dst the fd set to add to
865 * @param src the fd set to add from
868 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
869 const struct GNUNET_NETWORK_FDSet *src)
873 for (nfds = src->nsds; nfds > 0; nfds--)
874 if (FD_ISSET (nfds, &src->sds))
877 FD_SET (nfds, &dst->sds);
878 if (nfds + 1 > dst->nsds)
879 dst->nsds = nfds + 1;
882 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
888 * Copy one fd set to another
890 * @param to destination
894 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
895 const struct GNUNET_NETWORK_FDSet *from)
897 FD_COPY (&from->sds, &to->sds);
898 to->nsds = from->nsds;
901 GNUNET_CONTAINER_slist_clear (to->handles);
902 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
908 * Return file descriptor for this network handle
910 * @param desc wrapper to process
911 * @return POSIX file descriptor
914 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
920 * Return sockaddr for this network handle
922 * @param desc wrapper to process
926 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
932 * Return sockaddr length for this network handle
934 * @param desc wrapper to process
935 * @return socklen_t for sockaddr
938 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
940 return desc->addrlen;
943 * Copy a native fd set
945 * @param to destination
946 * @param from native source set
947 * @param nfds the biggest socket number in from + 1
950 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
951 const fd_set * from, int nfds)
953 FD_COPY (from, &to->sds);
959 * Set a native fd in a set
961 * @param to destination
962 * @param nfd native FD to set
965 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
967 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
968 FD_SET (nfd, &to->sds);
969 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
974 * Test native fd in a set
976 * @param to set to test, NULL for empty set
977 * @param nfd native FD to test, or -1 for none
978 * @return GNUNET_YES if FD is set in the set
981 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
984 if ((nfd == -1) || (to == NULL))
986 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
991 * Add a file handle to the fd set
993 * @param h the file handle to add
996 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
997 const struct GNUNET_DISK_FileHandle *h)
1000 GNUNET_CONTAINER_slist_add (fds->handles,
1001 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1002 sizeof (struct GNUNET_DISK_FileHandle));
1007 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1008 FD_SET (fd, &fds->sds);
1009 if (fd + 1 > fds->nsds)
1017 * Check if a file handle is part of an fd set
1019 * @param h file handle
1020 * @return GNUNET_YES if the file handle is part of the set
1023 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1024 const struct GNUNET_DISK_FileHandle *h)
1028 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1030 GNUNET_DISK_FileHandle));
1032 return FD_ISSET (h->fd, &fds->sds);
1038 * Checks if two fd sets overlap
1039 * @param fds1 first fd set
1040 * @param fds2 second fd set
1041 * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
1044 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1045 const struct GNUNET_NETWORK_FDSet *fds2)
1051 if (nfds > fds2->nsds)
1056 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1060 struct GNUNET_CONTAINER_SList_Iterator it;
1061 struct GNUNET_DISK_FileHandle *h;
1065 /*This code is somewhat hacky, we are not supposed to know what's
1066 * inside of fd_set; also the O(n^2) is really bad... */
1068 for (i = 0; i < fds1->sds.fd_count; i++)
1070 for (j = 0; j < fds2->sds.fd_count; j++)
1072 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1076 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1077 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1080 struct GNUNET_CONTAINER_SList_Iterator t;
1082 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1085 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1087 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1088 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1089 GNUNET_CONTAINER_slist_next (&t))
1091 struct GNUNET_DISK_FileHandle *fh;
1093 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1095 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1098 if (GNUNET_CONTAINER_slist_contains
1099 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1103 GNUNET_CONTAINER_slist_next (&it);
1112 * @return a new fd set
1114 struct GNUNET_NETWORK_FDSet *
1115 GNUNET_NETWORK_fdset_create ()
1117 struct GNUNET_NETWORK_FDSet *fds;
1119 fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1121 fds->handles = GNUNET_CONTAINER_slist_create ();
1123 GNUNET_NETWORK_fdset_zero (fds);
1129 * Releases the associated memory of an fd set
1133 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1136 GNUNET_CONTAINER_slist_destroy (fds->handles);
1142 struct _select_params
1150 SOCKET wakeup_socket;
1155 _selector (LPVOID p)
1157 struct _select_params *sp = p;
1161 WaitForSingleObject (sp->standby, INFINITE);
1162 ResetEvent (sp->standby);
1163 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1164 if (FD_ISSET (sp->wakeup_socket, sp->r))
1166 FD_CLR (sp->wakeup_socket, sp->r);
1169 SetEvent (sp->wakeup);
1176 * Check if sockets or pipes meet certain conditions
1177 * @param rfds set of sockets or pipes to be checked for readability
1178 * @param wfds set of sockets or pipes to be checked for writability
1179 * @param efds set of sockets or pipes to be checked for exceptions
1180 * @param timeout relative value when to return
1181 * @return number of selected sockets or pipes, GNUNET_SYSERR on error
1184 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1185 struct GNUNET_NETWORK_FDSet *wfds,
1186 struct GNUNET_NETWORK_FDSet *efds,
1187 const struct GNUNET_TIME_Relative timeout)
1193 int read_handles = 0;
1194 int write_handles = 0;
1202 static HANDLE hEventPipeWrite = 0;
1203 static HANDLE hEventReadReady = 0;
1205 static struct _select_params sp;
1206 static HANDLE select_thread = NULL;
1207 static HANDLE select_finished_event = NULL;
1208 static HANDLE select_standby_event = NULL;
1209 static SOCKET select_wakeup_socket = -1;
1210 static SOCKET select_send_socket = -1;
1211 static struct timeval select_timeout;
1214 int writePipePos = 0;
1216 HANDLE handle_array[FD_SETSIZE + 2];
1217 int returncode = -1;
1218 int returnedpos = 0;
1220 struct GNUNET_CONTAINER_SList *handles_read;
1221 struct GNUNET_CONTAINER_SList *handles_write;
1222 struct GNUNET_CONTAINER_SList *handles_except;
1236 /* TODO: Make this growable */
1237 struct GNUNET_DISK_FileHandle *readArray[50];
1245 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1248 struct GNUNET_CONTAINER_SList_Iterator t;
1250 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1251 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1252 GNUNET_CONTAINER_slist_next (&t))
1254 struct GNUNET_DISK_FileHandle *fh;
1256 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1258 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1267 nfds = GNUNET_MAX (nfds, wfds->nsds);
1269 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1274 nfds = GNUNET_MAX (nfds, efds->nsds);
1276 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1281 (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1288 LOG (GNUNET_ERROR_TYPE_ERROR,
1290 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1294 tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1296 1000 * (timeout.rel_value -
1297 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1298 return select (nfds, (rfds != NULL) ? &rfds->sds : NULL,
1299 (wfds != NULL) ? &wfds->sds : NULL,
1300 (efds != NULL) ? &efds->sds : NULL,
1301 (timeout.rel_value ==
1302 GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ? NULL : &tv);
1305 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1306 /* calculate how long we need to wait in milliseconds */
1307 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1308 ms_total = INFINITE;
1311 ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1312 if (timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value > 0xFFFFFFFFLL - 1)
1315 ms_total = 0xFFFFFFFF - 1;
1318 /* select() may be used as a portable way to sleep */
1319 if (!(rfds || wfds || efds))
1325 if (select_thread == NULL)
1327 SOCKET select_listening_socket = -1;
1328 struct sockaddr_in s_in;
1333 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1334 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1336 select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1338 select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1341 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1343 alen = sizeof (s_in);
1344 s_in.sin_family = AF_INET;
1346 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1347 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1348 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1349 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1350 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1352 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1354 res = listen (select_listening_socket, SOMAXCONN);
1356 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1358 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1360 closesocket (select_listening_socket);
1362 sp.wakeup = select_finished_event;
1363 sp.standby = select_standby_event;
1364 sp.wakeup_socket = select_wakeup_socket;
1366 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1370 handles_read = GNUNET_CONTAINER_slist_create ();
1371 handles_write = GNUNET_CONTAINER_slist_create ();
1372 handles_except = GNUNET_CONTAINER_slist_create ();
1383 FD_COPY (&rfds->sds, &aread);
1385 FD_COPY (&rfds->sds, &bread);
1390 FD_COPY (&wfds->sds, &awrite);
1392 FD_COPY (&wfds->sds, &bwrite);
1397 FD_COPY (&efds->sds, &aexcept);
1399 FD_COPY (&efds->sds, &bexcept);
1403 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1404 By profiling we detected that to be true in 90% of the cases.
1407 /* Do the select now */
1408 select_timeout.tv_sec = 0;
1409 select_timeout.tv_usec = 0;
1411 /* Copy all the writes to the except, so we can detect connect() errors */
1412 for (i = 0; i < awrite.fd_count; i++)
1414 if (awrite.fd_array[i] != 0 && awrite.fd_array[i] != -1)
1415 FD_SET (awrite.fd_array[i], &aexcept);
1417 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1418 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1419 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1422 if (selectret == -1)
1424 /* Throw an error early on, while we still have the context. */
1425 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1426 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1430 /* Check aexcept, add its contents to awrite
1431 This is technically wrong (aexcept might have its own descriptors), we should
1432 have checked that descriptors were in awrite originally before re-adding them from
1433 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1434 for (i = 0; i < aexcept.fd_count; i++)
1436 if (aexcept.fd_array[i] != 0 && aexcept.fd_array[i] != -1)
1437 FD_SET (aexcept.fd_array[i], &awrite);
1440 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1441 /* Sadly, it means code duplication :( */
1442 if ((selectret > 0) || (ms_total == 0))
1445 if (rfds && read_handles)
1447 struct GNUNET_CONTAINER_SList_Iterator i;
1449 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1450 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1451 GNUNET_CONTAINER_slist_next (&i))
1453 struct GNUNET_DISK_FileHandle *fh;
1455 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1456 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1462 DWORD waitstatus = 0;
1463 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1464 error = GetLastError ();
1465 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1466 i, fh->h, bret, waitstatus, error);
1469 /* TODO: either add more errors to this condition, or eliminate it
1470 * entirely (failed to peek -> pipe is in serious trouble, should
1471 * be selected as readable).
1473 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1476 else if (waitstatus <= 0)
1478 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1479 fh, sizeof (struct GNUNET_DISK_FileHandle));
1481 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1486 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1487 fh, sizeof (struct GNUNET_DISK_FileHandle));
1492 if (wfds && write_handles)
1494 LOG (GNUNET_ERROR_TYPE_DEBUG,
1495 "Adding the write ready event to the array as %d\n", nhandles);
1496 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1497 retcode += write_handles;
1499 if (efds && ex_handles)
1501 struct GNUNET_CONTAINER_SList_Iterator i;
1503 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1504 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1505 GNUNET_CONTAINER_slist_next (&i))
1507 struct GNUNET_DISK_FileHandle *fh;
1510 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1511 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1513 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1515 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1516 fh, sizeof (struct GNUNET_DISK_FileHandle));
1522 /* Add our select() result.*/
1524 retcode += selectret;
1528 GNUNET_NETWORK_fdset_zero (rfds);
1529 if (selectret != -1)
1530 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1531 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1535 GNUNET_NETWORK_fdset_zero (wfds);
1536 if (selectret != -1)
1537 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1538 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1542 GNUNET_NETWORK_fdset_zero (efds);
1543 if (selectret != -1)
1544 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1545 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1547 GNUNET_CONTAINER_slist_destroy (handles_read);
1548 GNUNET_CONTAINER_slist_destroy (handles_write);
1549 GNUNET_CONTAINER_slist_destroy (handles_except);
1551 if (selectret == -1)
1556 /* If we got this far, use slower implementation that is able to do a waiting select
1557 on both sockets and pipes simultaneously */
1559 /* Events for pipes */
1560 if (!hEventReadReady)
1561 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1562 if (!hEventPipeWrite)
1563 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1579 FD_COPY (&rfds->sds, &aread);
1581 FD_COPY (&rfds->sds, &bread);
1586 FD_COPY (&wfds->sds, &awrite);
1588 FD_COPY (&wfds->sds, &bwrite);
1593 FD_COPY (&efds->sds, &aexcept);
1595 FD_COPY (&efds->sds, &bexcept);
1598 /* We will first Add the PIPES to the events */
1600 if (rfds && read_handles)
1602 struct GNUNET_CONTAINER_SList_Iterator i;
1604 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1605 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1606 GNUNET_CONTAINER_slist_next (&i))
1608 struct GNUNET_DISK_FileHandle *fh;
1610 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1612 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1614 /* Read zero bytes to check the status of the pipe */
1615 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1617 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1619 DWORD error_code = GetLastError ();
1621 if (error_code == ERROR_IO_PENDING)
1623 LOG (GNUNET_ERROR_TYPE_DEBUG,
1624 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1626 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1627 readArray[readPipes++] = fh;
1631 LOG (GNUNET_ERROR_TYPE_DEBUG,
1632 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1633 handle_array[nhandles++] = hEventReadReady;
1634 readArray[readPipes++] = fh;
1639 LOG (GNUNET_ERROR_TYPE_DEBUG,
1640 "Adding the read ready event to the array as %d\n", nhandles);
1641 handle_array[nhandles++] = hEventReadReady;
1642 readArray[readPipes++] = fh;
1647 GNUNET_CONTAINER_slist_add (handles_read,
1648 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1649 fh, sizeof (struct GNUNET_DISK_FileHandle));
1653 if (wfds && write_handles)
1655 LOG (GNUNET_ERROR_TYPE_DEBUG,
1656 "Adding the write ready event to the array as %d\n", nhandles);
1657 handle_array[nhandles++] = hEventPipeWrite;
1658 writePipePos = nhandles;
1660 if (efds && ex_handles)
1662 struct GNUNET_CONTAINER_SList_Iterator i;
1664 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1665 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1666 GNUNET_CONTAINER_slist_next (&i))
1668 struct GNUNET_DISK_FileHandle *fh;
1671 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1673 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1675 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1677 GNUNET_CONTAINER_slist_add (handles_except,
1678 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1680 sizeof (struct GNUNET_DISK_FileHandle));
1690 LOG (GNUNET_ERROR_TYPE_DEBUG,
1691 "Adding the socket event to the array as %d\n", nhandles);
1692 handle_array[nhandles++] = select_finished_event;
1693 if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1697 select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1698 select_timeout.tv_usec = 1000 * (timeout.rel_value -
1699 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1700 sp.tv = &select_timeout;
1702 FD_SET (select_wakeup_socket, &aread);
1706 /* Failed connections cause sockets to be set in errorfds on W32,
1707 * but on POSIX it should set them in writefds.
1708 * First copy all awrite sockets to aexcept, later we'll
1709 * check aexcept and set its contents in awrite as well
1710 * Sockets are also set in errorfds when OOB data is available,
1711 * but we don't use OOB data.
1713 for (i = 0; i < awrite.fd_count; i++)
1715 if (awrite.fd_array[i] != 0 && awrite.fd_array[i] != -1)
1716 FD_SET (awrite.fd_array[i], &aexcept);
1718 ResetEvent (select_finished_event);
1719 SetEvent (select_standby_event);
1722 handle_array[nhandles] = NULL;
1723 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n",
1724 nfds, nhandles, (unsigned long long) ms_total);
1728 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1729 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1734 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1735 returncode = WAIT_TIMEOUT;
1739 /* Shouldn't come this far. If it does - investigate. */
1745 /* Don't wake up select-thread when delay is 0, it should return immediately
1746 * and wake up by itself.
1749 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1750 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1751 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1756 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1759 /* Check aexcept, add its contents to awrite */
1760 for (i = 0; i < aexcept.fd_count; i++)
1762 if (aexcept.fd_array[i] != 0 && aexcept.fd_array[i] != -1)
1763 FD_SET (aexcept.fd_array[i], &awrite);
1767 returnedpos = returncode - WAIT_OBJECT_0;
1768 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1770 if (nhandles && (returnedpos < nhandles))
1775 retcode += sp.status;
1777 if ((writePipePos != -1) && (returnedpos < writePipePos))
1779 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1780 retcode += write_handles;
1781 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1783 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1784 /* We have some pipes ready for read. */
1785 if (returnedpos < readPipes)
1787 for (i = 0; i < readPipes; i++)
1795 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1796 error = GetLastError ();
1797 LOG (GNUNET_ERROR_TYPE_DEBUG,
1798 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1799 i, readArray[i]->h, bret, waitstatus, error);
1802 /* TODO: either add more errors to this condition, or eliminate it
1803 * entirely (failed to peek -> pipe is in serious trouble, should
1804 * be selected as readable).
1806 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1809 else if (waitstatus <= 0)
1811 GNUNET_CONTAINER_slist_add (handles_read,
1812 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1814 sizeof (struct GNUNET_DISK_FileHandle));
1816 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1817 readArray[i], readArray[i]->h);
1821 if (!nhandles || (returnedpos >= nhandles))
1822 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1825 struct GNUNET_CONTAINER_SList_Iterator t;
1827 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1828 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1829 GNUNET_CONTAINER_slist_next (&t))
1831 struct GNUNET_DISK_FileHandle *fh;
1833 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1835 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1840 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1841 GNUNET_NETWORK_fdset_zero (rfds);
1842 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1843 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1844 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1848 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1849 GNUNET_NETWORK_fdset_zero (wfds);
1850 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1851 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1852 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1856 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1857 GNUNET_NETWORK_fdset_zero (efds);
1858 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1859 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1860 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1862 GNUNET_CONTAINER_slist_destroy (handles_read);
1863 GNUNET_CONTAINER_slist_destroy (handles_write);
1864 GNUNET_CONTAINER_slist_destroy (handles_except);
1868 struct GNUNET_CONTAINER_SList_Iterator t;
1870 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1871 for (i = 0; i < rfds->sds.fd_count; i++)
1873 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1875 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1876 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1877 GNUNET_CONTAINER_slist_next (&t))
1879 struct GNUNET_DISK_FileHandle *fh;
1881 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1883 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1888 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1889 for (i = 0; i < wfds->sds.fd_count; i++)
1891 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1896 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1897 for (i = 0; i < efds->sds.fd_count; i++)
1899 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1902 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1904 if (nhandles && (returnedpos < nhandles))
1911 /* end of network.c */