2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file util/network.c
23 * @brief basic, low-level networking interface
25 * @author Christian Grothoff
29 #include "gnunet_util_lib.h"
31 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
32 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
33 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
35 #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
38 #ifndef INVALID_SOCKET
39 #define INVALID_SOCKET -1
43 struct GNUNET_NETWORK_Handle
52 * Address family / domain.
62 * Number of bytes in addr.
67 * Address we were bound to, or NULL.
69 struct sockaddr *addr;
75 * Test if the given protocol family is supported by this system.
77 * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
78 * @return GNUNET_OK if the PF is supported
81 GNUNET_NETWORK_test_pf (int pf)
85 s = socket (pf, SOCK_STREAM, 0);
88 if (EAFNOSUPPORT == errno)
90 fprintf (stderr, "Failed to create test socket: %s\n", STRERROR (errno));
103 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
104 * shorten it to an acceptable length while keeping it unique
105 * and making sure it remains a valid filename (if possible).
107 * @param unixpath long path, will be freed (or same pointer returned
108 * with moved 0-termination).
109 * @return shortened unixpath, NULL on error
112 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
114 struct sockaddr_un dummy;
117 struct GNUNET_CRYPTO_ShortHashCode sh;
118 struct GNUNET_CRYPTO_ShortHashAsciiEncoded ae;
121 upm = sizeof (dummy.sun_path);
122 slen = strlen (unixpath);
124 return unixpath; /* no shortening required */
125 GNUNET_CRYPTO_short_hash (unixpath, slen, &sh);
126 while (sizeof (struct GNUNET_CRYPTO_ShortHashAsciiEncoded) +
127 strlen (unixpath) >= upm)
129 if (NULL == (end = strrchr (unixpath, '/')))
131 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
132 _("Unable to shorten unix path `%s' while keeping name unique\n"),
134 GNUNET_free (unixpath);
139 GNUNET_CRYPTO_short_hash_to_enc (&sh, &ae);
140 strcat (unixpath, (char*) ae.short_encoding);
146 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
151 * Set if a socket should use blocking or non-blocking IO.
154 * @param doBlock blocking mode
155 * @return GNUNET_OK on success, GNUNET_SYSERR on error
158 GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
165 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
168 SetErrnoFromWinsockError (WSAGetLastError ());
169 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
170 return GNUNET_SYSERR;
176 int flags = fcntl (fd->fd, F_GETFL);
181 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
182 return GNUNET_SYSERR;
185 flags &= ~O_NONBLOCK;
189 if (0 != fcntl (fd->fd, F_SETFL, flags))
192 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
193 return GNUNET_SYSERR;
201 * Make a socket non-inheritable to child processes
203 * @param h the socket to make non-inheritable
204 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
205 * @warning Not implemented on Windows
208 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
212 i = fcntl (h->fd, F_GETFD);
214 return GNUNET_SYSERR;
215 if (i == (i | FD_CLOEXEC))
218 if (fcntl (h->fd, F_SETFD, i) < 0)
219 return GNUNET_SYSERR;
223 b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
226 SetErrnoFromWinsockError (WSAGetLastError ());
227 return GNUNET_SYSERR;
236 * The MSG_NOSIGNAL equivalent on Mac OS X
238 * @param h the socket to make non-delaying
241 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
246 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE,
247 (const void *) &abs_value,
249 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
255 * Disable delays when sending data via the socket.
256 * (GNUnet makes sure that messages are as big as
259 * @param h the socket to make non-delaying
262 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
267 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
268 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
270 const char *abs_value = "1";
273 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY,
274 (const void *) abs_value,
276 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
282 * Perform proper canonical initialization for a network handle.
283 * Set it to non-blocking, make it non-inheritable to child
284 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
285 * stream socket) and check that it is smaller than FS_SETSIZE.
287 * @param h socket to initialize
288 * @param af address family of the socket
289 * @param type socket type
290 * @return GNUNET_OK on success, GNUNET_SYSERR if initialization
291 * failed and the handle was destroyed
294 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
299 if (h->fd == INVALID_SOCKET)
302 SetErrnoFromWinsockError (WSAGetLastError ());
305 return GNUNET_SYSERR;
308 if (h->fd >= FD_SETSIZE)
310 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
312 return GNUNET_SYSERR;
315 if (GNUNET_OK != socket_set_inheritable (h))
316 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
317 "socket_set_inheritable");
319 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
322 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
323 return GNUNET_SYSERR;
326 socket_set_nosigpipe (h);
328 if ( (type == SOCK_STREAM)
333 socket_set_nodelay (h);
339 * accept a new connection on a socket
341 * @param desc bound socket
342 * @param address address of the connecting peer, may be NULL
343 * @param address_len length of address
344 * @return client socket
346 struct GNUNET_NETWORK_Handle *
347 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
348 struct sockaddr *address, socklen_t * address_len)
350 struct GNUNET_NETWORK_Handle *ret;
352 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
355 struct sockaddr name;
356 socklen_t namelen = sizeof (name);
357 int gsn = getsockname (desc->fd, &name, &namelen);
360 LOG (GNUNET_ERROR_TYPE_DEBUG, "Accepting connection on `%s'\n",
361 GNUNET_a2s (&name, namelen));
364 ret->fd = accept (desc->fd, address, address_len);
365 if (GNUNET_OK != initialize_network_handle (ret,
366 (NULL != address) ? address->sa_family : desc->af,
374 * Bind to a connected socket
376 * @param desc socket to bind
377 * @param address address to be bound
378 * @param address_len length of address
379 * @param flags flags affecting bind behaviour
380 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
383 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
384 const struct sockaddr *address,
385 socklen_t address_len,
395 if (desc->af == AF_INET6)
396 if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY,
399 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
407 /* This is required here for TCP sockets, but only on UNIX */
408 if ((SOCK_STREAM == desc->type)
409 && (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))))
410 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
415 if (address->sa_family == AF_UNIX && (flags & GNUNET_BIND_EXCLUSIVE) == 0)
417 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
419 (void) unlink (un->sun_path);
423 ret = bind (desc->fd, address, address_len);
425 if (SOCKET_ERROR == ret)
426 SetErrnoFromWinsockError (WSAGetLastError ());
429 return GNUNET_SYSERR;
432 desc->addr = GNUNET_malloc (address_len);
433 memcpy (desc->addr, address, address_len);
434 desc->addrlen = address_len;
444 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
447 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
455 ret = closesocket (desc->fd);
456 error = WSAGetLastError ();
457 SetErrnoFromWinsockError (error);
458 LOG (GNUNET_ERROR_TYPE_DEBUG,
459 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
462 ret = close (desc->fd);
466 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
468 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
470 if (0 != unlink (un->sun_path))
471 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
475 GNUNET_free_non_null (desc->addr);
477 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
482 * Box a native socket (and check that it is a socket).
484 * @param fd socket to box
485 * @return NULL on error (including not supported on target platform)
487 struct GNUNET_NETWORK_Handle *
488 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
490 struct GNUNET_NETWORK_Handle *ret;
494 /* FIXME: Find a better call to check that FD is valid */
495 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
496 return NULL; /* invalid FD */
497 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
502 if (fcntl (fd, F_GETFD) < 0)
503 return NULL; /* invalid FD */
504 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
515 * @param address peer address
516 * @param address_len length of address
517 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
520 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
521 const struct sockaddr *address,
522 socklen_t address_len)
526 ret = connect (desc->fd, address, address_len);
529 if (SOCKET_ERROR == ret)
531 SetErrnoFromWinsockError (WSAGetLastError ());
532 if (errno == EWOULDBLOCK)
536 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
544 * @param level protocol level of the option
545 * @param optname identifier of the option
546 * @param optval options
547 * @param optlen length of optval
548 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
551 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
552 int level, int optname, void *optval,
557 ret = getsockopt (desc->fd, level, optname, optval, optlen);
560 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
561 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
563 else if (SOCKET_ERROR == ret)
564 SetErrnoFromWinsockError (WSAGetLastError ());
566 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
573 * @param backlog length of the listen queue
574 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
577 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
582 ret = listen (desc->fd, backlog);
585 if (SOCKET_ERROR == ret)
586 SetErrnoFromWinsockError (WSAGetLastError ());
589 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
594 * How much data is available to be read on this descriptor?
596 * Returns GNUNET_NO if no data is available, or on error!
600 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
605 /* How much is there to be read? */
609 error = ioctl (desc->fd, FIONREAD, &pending);
611 return (ssize_t) pending;
616 error = ioctlsocket (desc->fd, FIONREAD, &pending);
617 if (error != SOCKET_ERROR)
618 return (ssize_t) pending;
625 * Read data from a connected socket (always non-blocking).
627 * @param buffer buffer
628 * @param length length of buffer
629 * @param src_addr either the source to recv from, or all zeroes
630 * to be filled in by recvfrom
631 * @param addrlen length of the addr
634 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
635 void *buffer, size_t length,
636 struct sockaddr * src_addr, socklen_t * addrlen)
644 flags |= MSG_DONTWAIT;
647 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
649 if (SOCKET_ERROR == ret)
650 SetErrnoFromWinsockError (WSAGetLastError ());
657 * Read data from a connected socket (always non-blocking).
659 * @param buffer buffer
660 * @param length length of buffer
663 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
664 void *buffer, size_t length)
672 flags |= MSG_DONTWAIT;
674 ret = recv (desc->fd, buffer, length, flags);
676 if (SOCKET_ERROR == ret)
677 SetErrnoFromWinsockError (WSAGetLastError ());
684 * Send data (always non-blocking).
687 * @param buffer data to send
688 * @param length size of the buffer
689 * @return number of bytes sent, GNUNET_SYSERR on error
692 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
693 const void *buffer, size_t length)
701 flags |= MSG_DONTWAIT;
705 flags |= MSG_NOSIGNAL;
708 ret = send (desc->fd, buffer, length, flags);
711 if (SOCKET_ERROR == ret)
712 SetErrnoFromWinsockError (WSAGetLastError ());
720 * Send data to a particular destination (always non-blocking).
721 * This function only works for UDP sockets.
724 * @param message data to send
725 * @param length size of the data
726 * @param dest_addr destination address
727 * @param dest_len length of address
728 * @return number of bytes sent, GNUNET_SYSERR on error
731 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
732 const void *message, size_t length,
733 const struct sockaddr * dest_addr,
742 flags |= MSG_DONTWAIT;
745 flags |= MSG_NOSIGNAL;
747 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
749 if (SOCKET_ERROR == ret)
750 SetErrnoFromWinsockError (WSAGetLastError ());
759 * @param level protocol level of the option
760 * @param option_name option identifier
761 * @param option_value value to set
762 * @param option_len size of option_value
763 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
766 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
767 int option_name, const void *option_value,
768 socklen_t option_len)
772 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
774 if (SOCKET_ERROR == ret)
775 SetErrnoFromWinsockError (WSAGetLastError ());
777 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
782 * Create a new socket. Configure it for non-blocking IO and
783 * mark it as non-inheritable to child processes (set the
784 * close-on-exec flag).
786 * @param domain domain of the socket
787 * @param type socket type
788 * @param protocol network protocol
789 * @return new socket, NULL on error
791 struct GNUNET_NETWORK_Handle *
792 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
794 struct GNUNET_NETWORK_Handle *ret;
796 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
797 ret->fd = socket (domain, type, protocol);
799 initialize_network_handle (ret, domain, type))
806 * Shut down socket operations
808 * @param how type of shutdown
809 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
812 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
816 ret = shutdown (desc->fd, how);
819 SetErrnoFromWinsockError (WSAGetLastError ());
821 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
826 * Disable the "CORK" feature for communication with the given socket,
827 * forcing the OS to immediately flush the buffer on transmission
828 * instead of potentially buffering multiple messages. Essentially
829 * reduces the OS send buffers to zero.
832 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
835 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
844 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
846 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
849 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
851 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
857 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
858 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
861 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
862 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
864 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
873 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
878 GNUNET_CONTAINER_slist_clear (fds->handles);
883 * Add a socket to the FD set
885 * @param desc socket to add
888 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
889 const struct GNUNET_NETWORK_Handle *desc)
891 FD_SET (desc->fd, &fds->sds);
892 if (desc->fd + 1 > fds->nsds)
893 fds->nsds = desc->fd + 1;
898 * Check whether a socket is part of the fd set
901 * @return 0 if the FD is not set
904 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
905 const struct GNUNET_NETWORK_Handle *desc)
907 return FD_ISSET (desc->fd, &fds->sds);
912 * Add one fd set to another
913 * @param dst the fd set to add to
914 * @param src the fd set to add from
917 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
918 const struct GNUNET_NETWORK_FDSet *src)
923 for (nfds = src->nsds; nfds > 0; nfds--)
924 if (FD_ISSET (nfds, &src->sds))
927 FD_SET (nfds, &dst->sds);
928 if (nfds + 1 > dst->nsds)
929 dst->nsds = nfds + 1;
932 /* This is MinGW32-specific implementation that relies on the code that
933 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
934 * that fd being added is not already in the set.
935 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
938 for (i = 0; i < src->sds.fd_count; i++)
939 FD_SET (src->sds.fd_array[i], &dst->sds);
940 if (src->nsds > dst->nsds)
941 dst->nsds = src->nsds;
943 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
949 * Copy one fd set to another
951 * @param to destination
955 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
956 const struct GNUNET_NETWORK_FDSet *from)
958 FD_COPY (&from->sds, &to->sds);
959 to->nsds = from->nsds;
962 GNUNET_CONTAINER_slist_clear (to->handles);
963 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
969 * Return file descriptor for this network handle
971 * @param desc wrapper to process
972 * @return POSIX file descriptor
975 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
981 * Return sockaddr for this network handle
983 * @param desc wrapper to process
987 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
993 * Return sockaddr length for this network handle
995 * @param desc wrapper to process
996 * @return socklen_t for sockaddr
999 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1001 return desc->addrlen;
1004 * Copy a native fd set
1006 * @param to destination
1007 * @param from native source set
1008 * @param nfds the biggest socket number in from + 1
1011 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1012 const fd_set * from, int nfds)
1014 FD_COPY (from, &to->sds);
1020 * Set a native fd in a set
1022 * @param to destination
1023 * @param nfd native FD to set
1026 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1028 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1029 FD_SET (nfd, &to->sds);
1030 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1035 * Test native fd in a set
1037 * @param to set to test, NULL for empty set
1038 * @param nfd native FD to test, or -1 for none
1039 * @return GNUNET_YES if FD is set in the set
1042 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1045 if ((nfd == -1) || (to == NULL))
1047 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1052 * Add a file handle to the fd set
1054 * @param h the file handle to add
1057 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1058 const struct GNUNET_DISK_FileHandle *h)
1061 GNUNET_CONTAINER_slist_add (fds->handles,
1062 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1063 sizeof (struct GNUNET_DISK_FileHandle));
1068 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1069 FD_SET (fd, &fds->sds);
1070 if (fd + 1 > fds->nsds)
1078 * Check if a file handle is part of an fd set
1080 * @param h file handle
1081 * @return GNUNET_YES if the file handle is part of the set
1084 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1085 const struct GNUNET_DISK_FileHandle *h)
1089 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1091 GNUNET_DISK_FileHandle));
1093 return FD_ISSET (h->fd, &fds->sds);
1099 * Checks if two fd sets overlap
1100 * @param fds1 first fd set
1101 * @param fds2 second fd set
1102 * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
1105 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1106 const struct GNUNET_NETWORK_FDSet *fds2)
1112 if (nfds > fds2->nsds)
1117 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1121 struct GNUNET_CONTAINER_SList_Iterator it;
1122 struct GNUNET_DISK_FileHandle *h;
1126 /*This code is somewhat hacky, we are not supposed to know what's
1127 * inside of fd_set; also the O(n^2) is really bad... */
1129 for (i = 0; i < fds1->sds.fd_count; i++)
1131 for (j = 0; j < fds2->sds.fd_count; j++)
1133 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1137 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1138 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1141 struct GNUNET_CONTAINER_SList_Iterator t;
1143 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1146 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1148 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1149 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1150 GNUNET_CONTAINER_slist_next (&t))
1152 struct GNUNET_DISK_FileHandle *fh;
1154 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1156 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1159 if (GNUNET_CONTAINER_slist_contains
1160 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1164 GNUNET_CONTAINER_slist_next (&it);
1173 * @return a new fd set
1175 struct GNUNET_NETWORK_FDSet *
1176 GNUNET_NETWORK_fdset_create ()
1178 struct GNUNET_NETWORK_FDSet *fds;
1180 fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1182 fds->handles = GNUNET_CONTAINER_slist_create ();
1184 GNUNET_NETWORK_fdset_zero (fds);
1190 * Releases the associated memory of an fd set
1194 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1197 GNUNET_CONTAINER_slist_destroy (fds->handles);
1203 struct _select_params
1211 SOCKET wakeup_socket;
1216 _selector (LPVOID p)
1218 struct _select_params *sp = p;
1222 WaitForSingleObject (sp->standby, INFINITE);
1223 ResetEvent (sp->standby);
1224 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1225 if (FD_ISSET (sp->wakeup_socket, sp->r))
1227 FD_CLR (sp->wakeup_socket, sp->r);
1230 SetEvent (sp->wakeup);
1237 * Check if sockets or pipes meet certain conditions
1238 * @param rfds set of sockets or pipes to be checked for readability
1239 * @param wfds set of sockets or pipes to be checked for writability
1240 * @param efds set of sockets or pipes to be checked for exceptions
1241 * @param timeout relative value when to return
1242 * @return number of selected sockets or pipes, GNUNET_SYSERR on error
1245 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1246 struct GNUNET_NETWORK_FDSet *wfds,
1247 struct GNUNET_NETWORK_FDSet *efds,
1248 const struct GNUNET_TIME_Relative timeout)
1254 int read_handles = 0;
1255 int write_handles = 0;
1263 static HANDLE hEventPipeWrite = 0;
1264 static HANDLE hEventReadReady = 0;
1266 static struct _select_params sp;
1267 static HANDLE select_thread = NULL;
1268 static HANDLE select_finished_event = NULL;
1269 static HANDLE select_standby_event = NULL;
1270 static SOCKET select_wakeup_socket = -1;
1271 static SOCKET select_send_socket = -1;
1272 static struct timeval select_timeout;
1275 int writePipePos = 0;
1277 HANDLE handle_array[FD_SETSIZE + 2];
1278 int returncode = -1;
1279 int returnedpos = 0;
1281 struct GNUNET_CONTAINER_SList *handles_read;
1282 struct GNUNET_CONTAINER_SList *handles_write;
1283 struct GNUNET_CONTAINER_SList *handles_except;
1297 /* TODO: Make this growable */
1298 struct GNUNET_DISK_FileHandle *readArray[50];
1306 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1309 struct GNUNET_CONTAINER_SList_Iterator t;
1311 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1312 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1313 GNUNET_CONTAINER_slist_next (&t))
1315 struct GNUNET_DISK_FileHandle *fh;
1317 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1319 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1328 nfds = GNUNET_MAX (nfds, wfds->nsds);
1330 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1335 nfds = GNUNET_MAX (nfds, efds->nsds);
1337 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1342 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1349 LOG (GNUNET_ERROR_TYPE_ERROR,
1351 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1355 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1357 (timeout.rel_value_us -
1358 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1359 return select (nfds,
1360 (NULL != rfds) ? &rfds->sds : NULL,
1361 (NULL != wfds) ? &wfds->sds : NULL,
1362 (NULL != efds) ? &efds->sds : NULL,
1363 (timeout.rel_value_us ==
1364 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1367 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1368 /* calculate how long we need to wait in milliseconds */
1369 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1370 ms_total = INFINITE;
1373 ms_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
1374 if (timeout.rel_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us > 0xFFFFFFFFLL - 1)
1377 ms_total = 0xFFFFFFFF - 1;
1380 /* select() may be used as a portable way to sleep */
1381 if (!(rfds || wfds || efds))
1387 if (NULL == select_thread)
1389 SOCKET select_listening_socket = -1;
1390 struct sockaddr_in s_in;
1395 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1396 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1398 select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1400 select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1403 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1404 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1406 alen = sizeof (s_in);
1407 s_in.sin_family = AF_INET;
1409 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1410 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1411 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1412 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1413 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1414 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1416 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1417 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1419 res = listen (select_listening_socket, SOMAXCONN);
1420 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1422 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1423 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1425 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1427 closesocket (select_listening_socket);
1429 sp.wakeup = select_finished_event;
1430 sp.standby = select_standby_event;
1431 sp.wakeup_socket = select_wakeup_socket;
1433 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1437 handles_read = GNUNET_CONTAINER_slist_create ();
1438 handles_write = GNUNET_CONTAINER_slist_create ();
1439 handles_except = GNUNET_CONTAINER_slist_create ();
1450 FD_COPY (&rfds->sds, &aread);
1452 FD_COPY (&rfds->sds, &bread);
1457 FD_COPY (&wfds->sds, &awrite);
1459 FD_COPY (&wfds->sds, &bwrite);
1464 FD_COPY (&efds->sds, &aexcept);
1466 FD_COPY (&efds->sds, &bexcept);
1470 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1471 By profiling we detected that to be true in 90% of the cases.
1474 /* Do the select now */
1475 select_timeout.tv_sec = 0;
1476 select_timeout.tv_usec = 0;
1478 /* Copy all the writes to the except, so we can detect connect() errors */
1479 for (i = 0; i < awrite.fd_count; i++)
1480 FD_SET (awrite.fd_array[i], &aexcept);
1481 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1482 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1483 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1486 if (selectret == -1)
1488 /* Throw an error early on, while we still have the context. */
1489 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1490 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1494 /* Check aexcept, add its contents to awrite
1495 This is technically wrong (aexcept might have its own descriptors), we should
1496 have checked that descriptors were in awrite originally before re-adding them from
1497 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1498 for (i = 0; i < aexcept.fd_count; i++)
1499 FD_SET (aexcept.fd_array[i], &awrite);
1501 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1502 /* Sadly, it means code duplication :( */
1503 if ((selectret > 0) || (ms_total == 0))
1506 if (rfds && read_handles)
1508 struct GNUNET_CONTAINER_SList_Iterator i;
1511 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1512 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1513 GNUNET_CONTAINER_slist_next (&i), c++)
1515 struct GNUNET_DISK_FileHandle *fh;
1517 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1518 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1524 DWORD waitstatus = 0;
1525 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1526 error = GetLastError ();
1527 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1528 c, fh->h, bret, waitstatus, error);
1531 /* TODO: either add more errors to this condition, or eliminate it
1532 * entirely (failed to peek -> pipe is in serious trouble, should
1533 * be selected as readable).
1535 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1538 else if (waitstatus <= 0)
1540 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1541 fh, sizeof (struct GNUNET_DISK_FileHandle));
1543 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1548 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1549 fh, sizeof (struct GNUNET_DISK_FileHandle));
1554 if (wfds && write_handles)
1556 LOG (GNUNET_ERROR_TYPE_DEBUG,
1557 "Adding the write ready event to the array as %d\n", nhandles);
1558 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1559 retcode += write_handles;
1561 if (efds && ex_handles)
1563 struct GNUNET_CONTAINER_SList_Iterator i;
1565 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1566 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1567 GNUNET_CONTAINER_slist_next (&i))
1569 struct GNUNET_DISK_FileHandle *fh;
1572 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1573 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1575 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1577 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1578 fh, sizeof (struct GNUNET_DISK_FileHandle));
1584 /* Add our select() result.*/
1586 retcode += selectret;
1590 GNUNET_NETWORK_fdset_zero (rfds);
1591 if (selectret != -1)
1592 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1593 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1597 GNUNET_NETWORK_fdset_zero (wfds);
1598 if (selectret != -1)
1599 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1600 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1604 GNUNET_NETWORK_fdset_zero (efds);
1605 if (selectret != -1)
1606 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1607 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1609 GNUNET_CONTAINER_slist_destroy (handles_read);
1610 GNUNET_CONTAINER_slist_destroy (handles_write);
1611 GNUNET_CONTAINER_slist_destroy (handles_except);
1613 if (selectret == -1)
1618 /* If we got this far, use slower implementation that is able to do a waiting select
1619 on both sockets and pipes simultaneously */
1621 /* Events for pipes */
1622 if (!hEventReadReady)
1623 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1624 if (!hEventPipeWrite)
1625 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1641 FD_COPY (&rfds->sds, &aread);
1643 FD_COPY (&rfds->sds, &bread);
1648 FD_COPY (&wfds->sds, &awrite);
1650 FD_COPY (&wfds->sds, &bwrite);
1655 FD_COPY (&efds->sds, &aexcept);
1657 FD_COPY (&efds->sds, &bexcept);
1660 /* We will first Add the PIPES to the events */
1662 if (rfds && read_handles)
1664 struct GNUNET_CONTAINER_SList_Iterator i;
1666 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1667 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1668 GNUNET_CONTAINER_slist_next (&i))
1670 struct GNUNET_DISK_FileHandle *fh;
1672 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1674 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1676 /* Read zero bytes to check the status of the pipe */
1677 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1679 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1681 DWORD error_code = GetLastError ();
1683 if (error_code == ERROR_IO_PENDING)
1685 LOG (GNUNET_ERROR_TYPE_DEBUG,
1686 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1688 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1689 readArray[readPipes++] = fh;
1693 LOG (GNUNET_ERROR_TYPE_DEBUG,
1694 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1695 handle_array[nhandles++] = hEventReadReady;
1696 readArray[readPipes++] = fh;
1701 LOG (GNUNET_ERROR_TYPE_DEBUG,
1702 "Adding the read ready event to the array as %d\n", nhandles);
1703 handle_array[nhandles++] = hEventReadReady;
1704 readArray[readPipes++] = fh;
1709 GNUNET_CONTAINER_slist_add (handles_read,
1710 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1711 fh, sizeof (struct GNUNET_DISK_FileHandle));
1715 if (wfds && write_handles)
1717 LOG (GNUNET_ERROR_TYPE_DEBUG,
1718 "Adding the write ready event to the array as %d\n", nhandles);
1719 handle_array[nhandles++] = hEventPipeWrite;
1720 writePipePos = nhandles;
1722 if (efds && ex_handles)
1724 struct GNUNET_CONTAINER_SList_Iterator i;
1726 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1727 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1728 GNUNET_CONTAINER_slist_next (&i))
1730 struct GNUNET_DISK_FileHandle *fh;
1733 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1735 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1737 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1739 GNUNET_CONTAINER_slist_add (handles_except,
1740 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1742 sizeof (struct GNUNET_DISK_FileHandle));
1752 LOG (GNUNET_ERROR_TYPE_DEBUG,
1753 "Adding the socket event to the array as %d\n",
1755 handle_array[nhandles++] = select_finished_event;
1756 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1760 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1761 select_timeout.tv_usec =(timeout.rel_value_us -
1762 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1763 sp.tv = &select_timeout;
1765 FD_SET (select_wakeup_socket, &aread);
1769 /* Failed connections cause sockets to be set in errorfds on W32,
1770 * but on POSIX it should set them in writefds.
1771 * First copy all awrite sockets to aexcept, later we'll
1772 * check aexcept and set its contents in awrite as well
1773 * Sockets are also set in errorfds when OOB data is available,
1774 * but we don't use OOB data.
1776 for (i = 0; i < awrite.fd_count; i++)
1777 FD_SET (awrite.fd_array[i], &aexcept);
1778 ResetEvent (select_finished_event);
1779 SetEvent (select_standby_event);
1782 handle_array[nhandles] = NULL;
1783 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n",
1784 nfds, nhandles, (unsigned long long) ms_total);
1788 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1789 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1794 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1795 returncode = WAIT_TIMEOUT;
1799 /* Shouldn't come this far. If it does - investigate. */
1805 /* Don't wake up select-thread when delay is 0, it should return immediately
1806 * and wake up by itself.
1809 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1810 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1811 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1816 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1819 /* Check aexcept, add its contents to awrite */
1820 for (i = 0; i < aexcept.fd_count; i++)
1821 FD_SET (aexcept.fd_array[i], &awrite);
1824 returnedpos = returncode - WAIT_OBJECT_0;
1825 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1827 if (nhandles && (returnedpos < nhandles))
1832 retcode += sp.status;
1834 if ((writePipePos != -1) && (returnedpos < writePipePos))
1836 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1837 retcode += write_handles;
1838 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1840 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1841 /* We have some pipes ready for read. */
1842 if (returnedpos < readPipes)
1844 for (i = 0; i < readPipes; i++)
1852 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1853 error = GetLastError ();
1854 LOG (GNUNET_ERROR_TYPE_DEBUG,
1855 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1856 i, readArray[i]->h, bret, waitstatus, error);
1859 /* TODO: either add more errors to this condition, or eliminate it
1860 * entirely (failed to peek -> pipe is in serious trouble, should
1861 * be selected as readable).
1863 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1866 else if (waitstatus <= 0)
1868 GNUNET_CONTAINER_slist_add (handles_read,
1869 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1871 sizeof (struct GNUNET_DISK_FileHandle));
1873 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1874 readArray[i], readArray[i]->h);
1878 if (!nhandles || (returnedpos >= nhandles))
1879 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1882 struct GNUNET_CONTAINER_SList_Iterator t;
1884 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1885 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1886 GNUNET_CONTAINER_slist_next (&t))
1888 struct GNUNET_DISK_FileHandle *fh;
1890 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1892 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1897 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1898 GNUNET_NETWORK_fdset_zero (rfds);
1899 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1900 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1901 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1905 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1906 GNUNET_NETWORK_fdset_zero (wfds);
1907 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1908 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1909 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1913 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1914 GNUNET_NETWORK_fdset_zero (efds);
1915 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1916 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1917 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1919 GNUNET_CONTAINER_slist_destroy (handles_read);
1920 GNUNET_CONTAINER_slist_destroy (handles_write);
1921 GNUNET_CONTAINER_slist_destroy (handles_except);
1925 struct GNUNET_CONTAINER_SList_Iterator t;
1927 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1928 for (i = 0; i < rfds->sds.fd_count; i++)
1930 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1932 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1933 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1934 GNUNET_CONTAINER_slist_next (&t))
1936 struct GNUNET_DISK_FileHandle *fh;
1938 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1940 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1945 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1946 for (i = 0; i < wfds->sds.fd_count; i++)
1948 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1953 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1954 for (i = 0; i < efds->sds.fd_count; i++)
1956 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1959 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1961 if (nhandles && (returnedpos < nhandles))
1968 /* end of network.c */