2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file util/network.c
23 * @brief basic, low-level networking interface
25 * @author Christian Grothoff
28 #include "gnunet_util_lib.h"
31 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
32 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
33 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
35 #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
38 #ifndef INVALID_SOCKET
39 #define INVALID_SOCKET -1
43 struct GNUNET_NETWORK_Handle
52 * Address family / domain.
62 * Number of bytes in addr.
67 * Address we were bound to, or NULL.
69 struct sockaddr *addr;
75 * Test if the given protocol family is supported by this system.
77 * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
78 * @return #GNUNET_OK if the PF is supported
81 GNUNET_NETWORK_test_pf (int pf)
85 s = socket (pf, SOCK_STREAM, 0);
88 if (EAFNOSUPPORT == errno)
90 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
91 "Failed to create test socket: %s\n",
105 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
106 * shorten it to an acceptable length while keeping it unique
107 * and making sure it remains a valid filename (if possible).
109 * @param unixpath long path, will be freed (or same pointer returned
110 * with moved 0-termination).
111 * @return shortened unixpath, NULL on error
114 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
116 struct sockaddr_un dummy;
119 struct GNUNET_HashCode sh;
120 struct GNUNET_CRYPTO_HashAsciiEncoded ae;
123 upm = sizeof (dummy.sun_path);
124 slen = strlen (unixpath);
126 return unixpath; /* no shortening required */
127 GNUNET_CRYPTO_hash (unixpath, slen, &sh);
129 strlen (unixpath) >= upm)
131 if (NULL == (end = strrchr (unixpath, '/')))
133 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
134 _("Unable to shorten unix path `%s' while keeping name unique\n"),
136 GNUNET_free (unixpath);
141 GNUNET_CRYPTO_hash_to_enc (&sh, &ae);
142 strncat (unixpath, (char*) ae.encoding, 16);
148 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
153 * Set if a socket should use blocking or non-blocking IO.
156 * @param doBlock blocking mode
157 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
160 GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
167 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
170 SetErrnoFromWinsockError (WSAGetLastError ());
171 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
172 return GNUNET_SYSERR;
178 int flags = fcntl (fd->fd, F_GETFL);
183 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
184 return GNUNET_SYSERR;
187 flags &= ~O_NONBLOCK;
191 if (0 != fcntl (fd->fd, F_SETFL, flags))
194 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
195 return GNUNET_SYSERR;
203 * Make a socket non-inheritable to child processes
205 * @param h the socket to make non-inheritable
206 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
207 * @warning Not implemented on Windows
210 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
214 i = fcntl (h->fd, F_GETFD);
216 return GNUNET_SYSERR;
217 if (i == (i | FD_CLOEXEC))
220 if (fcntl (h->fd, F_SETFD, i) < 0)
221 return GNUNET_SYSERR;
225 b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
228 SetErrnoFromWinsockError (WSAGetLastError ());
229 return GNUNET_SYSERR;
238 * The MSG_NOSIGNAL equivalent on Mac OS X
240 * @param h the socket to make non-delaying
243 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
248 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE,
249 (const void *) &abs_value,
251 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
257 * Disable delays when sending data via the socket.
258 * (GNUnet makes sure that messages are as big as
261 * @param h the socket to make non-delaying
264 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
269 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
270 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
272 const char *abs_value = "1";
275 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY,
276 (const void *) abs_value,
278 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
284 * Perform proper canonical initialization for a network handle.
285 * Set it to non-blocking, make it non-inheritable to child
286 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
287 * stream socket) and check that it is smaller than FD_SETSIZE.
289 * @param h socket to initialize
290 * @param af address family of the socket
291 * @param type socket type
292 * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
293 * failed and the handle was destroyed
296 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
301 if (h->fd == INVALID_SOCKET)
304 SetErrnoFromWinsockError (WSAGetLastError ());
307 return GNUNET_SYSERR;
310 if (h->fd >= FD_SETSIZE)
312 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
314 return GNUNET_SYSERR;
317 if (GNUNET_OK != socket_set_inheritable (h))
318 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
319 "socket_set_inheritable");
321 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
324 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
325 return GNUNET_SYSERR;
328 socket_set_nosigpipe (h);
330 if ( (type == SOCK_STREAM)
335 socket_set_nodelay (h);
341 * accept a new connection on a socket
343 * @param desc bound socket
344 * @param address address of the connecting peer, may be NULL
345 * @param address_len length of @a address
346 * @return client socket
348 struct GNUNET_NETWORK_Handle *
349 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
350 struct sockaddr *address,
351 socklen_t *address_len)
353 struct GNUNET_NETWORK_Handle *ret;
355 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
358 struct sockaddr name;
359 socklen_t namelen = sizeof (name);
360 int gsn = getsockname (desc->fd, &name, &namelen);
363 LOG (GNUNET_ERROR_TYPE_DEBUG,
364 "Accepting connection on `%s'\n",
365 GNUNET_a2s (&name, namelen));
368 ret->fd = accept (desc->fd, address, address_len);
374 if (GNUNET_OK != initialize_network_handle (ret,
375 (NULL != address) ? address->sa_family : desc->af,
383 * Bind a socket to a particular address.
385 * @param desc socket to bind
386 * @param address address to be bound
387 * @param address_len length of @a address
388 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
391 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
392 const struct sockaddr *address,
393 socklen_t address_len)
396 socklen_t bind_address_len = address_len;
399 if (AF_UNIX == address->sa_family)
401 const struct sockaddr_un *address_un = (const struct sockaddr_un *)address;
402 if (address_un->sun_path[0] == '\0')
405 sizeof (struct sockaddr_un) \
406 - sizeof (address_un->sun_path) \
407 + strnlen (address_un->sun_path + 1, sizeof (address_un->sun_path) - 1) \
419 if (AF_INET6 == desc->af)
420 if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY,
423 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
431 /* This is required here for TCP sockets, but only on UNIX */
432 if ((SOCK_STREAM == desc->type)
433 && (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))))
434 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
439 /* set permissions of newly created UNIX domain socket to "user-only"; applications
440 can choose to relax this later */
443 if (AF_UNIX == address->sa_family)
444 old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH);
447 ret = bind (desc->fd, address, bind_address_len);
449 if (AF_UNIX == address->sa_family)
450 (void) umask (old_mask);
454 if (SOCKET_ERROR == ret)
455 SetErrnoFromWinsockError (WSAGetLastError ());
458 return GNUNET_SYSERR;
460 desc->addr = GNUNET_malloc (address_len);
461 memcpy (desc->addr, address, address_len);
462 desc->addrlen = address_len;
472 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
475 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
483 ret = closesocket (desc->fd);
484 error = WSAGetLastError ();
485 SetErrnoFromWinsockError (error);
486 LOG (GNUNET_ERROR_TYPE_DEBUG,
487 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
490 ret = close (desc->fd);
493 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
495 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
497 if (0 != unlink (un->sun_path))
498 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
503 GNUNET_NETWORK_socket_free_memory_only_ (desc);
504 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
509 * Only free memory of a socket, keep the file descriptor untouched.
514 GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc)
516 GNUNET_free_non_null (desc->addr);
522 * Box a native socket (and check that it is a socket).
524 * @param fd socket to box
525 * @return NULL on error (including not supported on target platform)
527 struct GNUNET_NETWORK_Handle *
528 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
530 struct GNUNET_NETWORK_Handle *ret;
534 /* FIXME: Find a better call to check that FD is valid */
535 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
536 return NULL; /* invalid FD */
537 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
542 if (fcntl (fd, F_GETFD) < 0)
543 return NULL; /* invalid FD */
544 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
553 * Connect a socket to some remote address.
556 * @param address peer address
557 * @param address_len length of @a address
558 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
561 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
562 const struct sockaddr *address,
563 socklen_t address_len)
568 if (address->sa_family == AF_UNIX)
570 const struct sockaddr_un *address_un = (const struct sockaddr_un *)address;
571 if (address_un->sun_path[0] == '\0')
574 sizeof (struct sockaddr_un) \
575 - sizeof (address_un->sun_path) \
576 + strnlen (address_un->sun_path + 1, sizeof (address_un->sun_path) - 1) \
582 ret = connect (desc->fd, address, address_len);
585 if (SOCKET_ERROR == ret)
587 SetErrnoFromWinsockError (WSAGetLastError ());
588 if (errno == EWOULDBLOCK)
592 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
600 * @param level protocol level of the option
601 * @param optname identifier of the option
602 * @param optval options
603 * @param optlen length of @a optval
604 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
607 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
608 int level, int optname, void *optval,
613 ret = getsockopt (desc->fd, level, optname, optval, optlen);
616 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
617 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
619 else if (SOCKET_ERROR == ret)
620 SetErrnoFromWinsockError (WSAGetLastError ());
622 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
630 * @param backlog length of the listen queue
631 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
634 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
639 ret = listen (desc->fd, backlog);
642 if (SOCKET_ERROR == ret)
643 SetErrnoFromWinsockError (WSAGetLastError ());
646 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
651 * How much data is available to be read on this descriptor?
654 * @returns #GNUNET_NO if no data is available, or on error!
657 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
662 /* How much is there to be read? */
666 error = ioctl (desc->fd, FIONREAD, &pending);
668 return (ssize_t) pending;
673 error = ioctlsocket (desc->fd, FIONREAD, &pending);
674 if (error != SOCKET_ERROR)
675 return (ssize_t) pending;
682 * Read data from a socket (always non-blocking).
685 * @param buffer buffer
686 * @param length length of @a buffer
687 * @param src_addr either the source to recv from, or all zeroes
688 * to be filled in by recvfrom
689 * @param addrlen length of the @a src_addr
692 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
693 void *buffer, size_t length,
694 struct sockaddr *src_addr, socklen_t *addrlen)
702 flags |= MSG_DONTWAIT;
705 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
707 if (SOCKET_ERROR == ret)
708 SetErrnoFromWinsockError (WSAGetLastError ());
715 * Read data from a connected socket (always non-blocking).
718 * @param buffer buffer
719 * @param length length of @a buffer
722 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
723 void *buffer, size_t length)
731 flags |= MSG_DONTWAIT;
733 ret = recv (desc->fd, buffer, length, flags);
735 if (SOCKET_ERROR == ret)
736 SetErrnoFromWinsockError (WSAGetLastError ());
743 * Send data (always non-blocking).
746 * @param buffer data to send
747 * @param length size of the @a buffer
748 * @return number of bytes sent, #GNUNET_SYSERR on error
751 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
752 const void *buffer, size_t length)
760 flags |= MSG_DONTWAIT;
764 flags |= MSG_NOSIGNAL;
767 ret = send (desc->fd, buffer, length, flags);
770 if (SOCKET_ERROR == ret)
771 SetErrnoFromWinsockError (WSAGetLastError ());
779 * Send data to a particular destination (always non-blocking).
780 * This function only works for UDP sockets.
783 * @param message data to send
784 * @param length size of the data
785 * @param dest_addr destination address
786 * @param dest_len length of @a address
787 * @return number of bytes sent, #GNUNET_SYSERR on error
790 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
791 const void *message, size_t length,
792 const struct sockaddr * dest_addr,
801 flags |= MSG_DONTWAIT;
804 flags |= MSG_NOSIGNAL;
807 if (dest_addr->sa_family == AF_UNIX)
809 const struct sockaddr_un *dest_addr_un = (const struct sockaddr_un *)dest_addr;
810 if (dest_addr_un->sun_path[0] == '\0')
812 sizeof (struct sockaddr_un) \
813 - sizeof (dest_addr_un->sun_path) \
814 + strnlen (dest_addr_un->sun_path + 1, sizeof (dest_addr_un->sun_path) - 1) \
818 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
820 if (SOCKET_ERROR == ret)
821 SetErrnoFromWinsockError (WSAGetLastError ());
831 * @param level protocol level of the option
832 * @param option_name option identifier
833 * @param option_value value to set
834 * @param option_len size of option_value
835 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
838 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
839 int option_name, const void *option_value,
840 socklen_t option_len)
844 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
846 if (SOCKET_ERROR == ret)
847 SetErrnoFromWinsockError (WSAGetLastError ());
849 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
854 * Create a new socket. Configure it for non-blocking IO and
855 * mark it as non-inheritable to child processes (set the
856 * close-on-exec flag).
858 * @param domain domain of the socket
859 * @param type socket type
860 * @param protocol network protocol
861 * @return new socket, NULL on error
863 struct GNUNET_NETWORK_Handle *
864 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
866 struct GNUNET_NETWORK_Handle *ret;
868 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
869 ret->fd = socket (domain, type, protocol);
876 initialize_network_handle (ret, domain, type))
883 * Shut down socket operations
885 * @param how type of shutdown
886 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
889 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
893 ret = shutdown (desc->fd, how);
896 SetErrnoFromWinsockError (WSAGetLastError ());
898 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
903 * Disable the "CORK" feature for communication with the given socket,
904 * forcing the OS to immediately flush the buffer on transmission
905 * instead of potentially buffering multiple messages. Essentially
906 * reduces the OS send buffers to zero.
909 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
912 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
921 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
923 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
926 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
928 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
934 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
935 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
938 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
939 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
941 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
951 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
956 GNUNET_CONTAINER_slist_clear (fds->handles);
962 * Add a socket to the FD set
965 * @param desc socket to add
968 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
969 const struct GNUNET_NETWORK_Handle *desc)
971 FD_SET (desc->fd, &fds->sds);
972 if (desc->fd + 1 > fds->nsds)
973 fds->nsds = desc->fd + 1;
978 * Check whether a socket is part of the fd set
982 * @return 0 if the FD is not set
985 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
986 const struct GNUNET_NETWORK_Handle *desc)
988 return FD_ISSET (desc->fd, &fds->sds);
993 * Add one fd set to another
995 * @param dst the fd set to add to
996 * @param src the fd set to add from
999 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
1000 const struct GNUNET_NETWORK_FDSet *src)
1005 for (nfds = src->nsds; nfds > 0; nfds--)
1006 if (FD_ISSET (nfds, &src->sds))
1009 FD_SET (nfds, &dst->sds);
1010 if (nfds + 1 > dst->nsds)
1011 dst->nsds = nfds + 1;
1014 /* This is MinGW32-specific implementation that relies on the code that
1015 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
1016 * that fd being added is not already in the set.
1017 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
1020 for (i = 0; i < src->sds.fd_count; i++)
1021 FD_SET (src->sds.fd_array[i], &dst->sds);
1022 if (src->nsds > dst->nsds)
1023 dst->nsds = src->nsds;
1025 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
1031 * Copy one fd set to another
1033 * @param to destination
1034 * @param from source
1037 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
1038 const struct GNUNET_NETWORK_FDSet *from)
1040 FD_COPY (&from->sds, &to->sds);
1041 to->nsds = from->nsds;
1044 GNUNET_CONTAINER_slist_clear (to->handles);
1045 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
1051 * Return file descriptor for this network handle
1053 * @param desc wrapper to process
1054 * @return POSIX file descriptor
1057 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
1064 * Return sockaddr for this network handle
1066 * @param desc wrapper to process
1070 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1077 * Return sockaddr length for this network handle
1079 * @param desc wrapper to process
1080 * @return socklen_t for sockaddr
1083 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1085 return desc->addrlen;
1090 * Copy a native fd set
1092 * @param to destination
1093 * @param from native source set
1094 * @param nfds the biggest socket number in from + 1
1097 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1098 const fd_set * from, int nfds)
1100 FD_COPY (from, &to->sds);
1106 * Set a native fd in a set
1108 * @param to destination
1109 * @param nfd native FD to set
1112 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1114 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1115 FD_SET (nfd, &to->sds);
1116 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1121 * Test native fd in a set
1123 * @param to set to test, NULL for empty set
1124 * @param nfd native FD to test, or -1 for none
1125 * @return #GNUNET_YES if FD is set in the set
1128 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1131 if ((nfd == -1) || (to == NULL))
1133 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1138 * Add a file handle to the fd set
1140 * @param h the file handle to add
1143 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1144 const struct GNUNET_DISK_FileHandle *h)
1147 GNUNET_CONTAINER_slist_add (fds->handles,
1148 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1149 sizeof (struct GNUNET_DISK_FileHandle));
1154 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1155 FD_SET (fd, &fds->sds);
1156 if (fd + 1 > fds->nsds)
1164 * Check if a file handle is part of an fd set
1166 * @param h file handle
1167 * @return #GNUNET_YES if the file handle is part of the set
1170 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1171 const struct GNUNET_DISK_FileHandle *h)
1175 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1177 GNUNET_DISK_FileHandle));
1179 return FD_ISSET (h->fd, &fds->sds);
1185 * Checks if two fd sets overlap
1186 * @param fds1 first fd set
1187 * @param fds2 second fd set
1188 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1191 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1192 const struct GNUNET_NETWORK_FDSet *fds2)
1198 if (nfds > fds2->nsds)
1203 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1207 struct GNUNET_CONTAINER_SList_Iterator it;
1208 struct GNUNET_DISK_FileHandle *h;
1212 /*This code is somewhat hacky, we are not supposed to know what's
1213 * inside of fd_set; also the O(n^2) is really bad... */
1215 for (i = 0; i < fds1->sds.fd_count; i++)
1217 for (j = 0; j < fds2->sds.fd_count; j++)
1219 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1223 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1224 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1227 struct GNUNET_CONTAINER_SList_Iterator t;
1229 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1232 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1234 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1235 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1236 GNUNET_CONTAINER_slist_next (&t))
1238 struct GNUNET_DISK_FileHandle *fh;
1240 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1242 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1245 if (GNUNET_CONTAINER_slist_contains
1246 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1250 GNUNET_CONTAINER_slist_next (&it);
1260 * @return a new fd set
1262 struct GNUNET_NETWORK_FDSet *
1263 GNUNET_NETWORK_fdset_create ()
1265 struct GNUNET_NETWORK_FDSet *fds;
1267 fds = GNUNET_new (struct GNUNET_NETWORK_FDSet);
1269 fds->handles = GNUNET_CONTAINER_slist_create ();
1271 GNUNET_NETWORK_fdset_zero (fds);
1277 * Releases the associated memory of an fd set
1282 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1285 GNUNET_CONTAINER_slist_destroy (fds->handles);
1291 struct _select_params
1299 SOCKET wakeup_socket;
1304 _selector (LPVOID p)
1306 struct _select_params *sp = p;
1310 WaitForSingleObject (sp->standby, INFINITE);
1311 ResetEvent (sp->standby);
1312 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1313 if (FD_ISSET (sp->wakeup_socket, sp->r))
1315 FD_CLR (sp->wakeup_socket, sp->r);
1318 SetEvent (sp->wakeup);
1326 * Check if sockets or pipes meet certain conditions
1327 * @param rfds set of sockets or pipes to be checked for readability
1328 * @param wfds set of sockets or pipes to be checked for writability
1329 * @param efds set of sockets or pipes to be checked for exceptions
1330 * @param timeout relative value when to return
1331 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1334 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1335 struct GNUNET_NETWORK_FDSet *wfds,
1336 struct GNUNET_NETWORK_FDSet *efds,
1337 const struct GNUNET_TIME_Relative timeout)
1343 int read_handles = 0;
1344 int write_handles = 0;
1348 uint64_t mcs_total = 0;
1349 DWORD ms_rounded = 0;
1353 static HANDLE hEventPipeWrite = 0;
1354 static HANDLE hEventReadReady = 0;
1356 static struct _select_params sp;
1357 static HANDLE select_thread = NULL;
1358 static HANDLE select_finished_event = NULL;
1359 static HANDLE select_standby_event = NULL;
1360 static SOCKET select_wakeup_socket = -1;
1361 static SOCKET select_send_socket = -1;
1362 static struct timeval select_timeout;
1365 int writePipePos = 0;
1367 HANDLE handle_array[FD_SETSIZE + 2];
1368 int returncode = -1;
1369 int returnedpos = 0;
1371 struct GNUNET_CONTAINER_SList *handles_read;
1372 struct GNUNET_CONTAINER_SList *handles_write;
1373 struct GNUNET_CONTAINER_SList *handles_except;
1387 /* TODO: Make this growable */
1388 struct GNUNET_DISK_FileHandle *readArray[50];
1396 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1399 struct GNUNET_CONTAINER_SList_Iterator t;
1401 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1402 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1403 GNUNET_CONTAINER_slist_next (&t))
1405 struct GNUNET_DISK_FileHandle *fh;
1407 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1409 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1418 nfds = GNUNET_MAX (nfds, wfds->nsds);
1420 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1425 nfds = GNUNET_MAX (nfds, efds->nsds);
1427 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1432 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1439 LOG (GNUNET_ERROR_TYPE_ERROR,
1441 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1445 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1447 (timeout.rel_value_us -
1448 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1449 return select (nfds,
1450 (NULL != rfds) ? &rfds->sds : NULL,
1451 (NULL != wfds) ? &wfds->sds : NULL,
1452 (NULL != efds) ? &efds->sds : NULL,
1453 (timeout.rel_value_us ==
1454 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1457 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1458 /* calculate how long we need to wait in microseconds */
1459 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1461 mcs_total = INFINITE;
1462 ms_rounded = INFINITE;
1466 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1467 ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1468 if (mcs_total > 0 && ms_rounded == 0)
1471 /* select() may be used as a portable way to sleep */
1472 if (!(rfds || wfds || efds))
1478 if (NULL == select_thread)
1480 SOCKET select_listening_socket = -1;
1481 struct sockaddr_in s_in;
1486 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1487 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1489 select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1491 select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1494 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1495 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1497 alen = sizeof (s_in);
1498 s_in.sin_family = AF_INET;
1500 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1501 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1502 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1503 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1504 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1505 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1507 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1508 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1510 res = listen (select_listening_socket, SOMAXCONN);
1511 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1513 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1514 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1516 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1518 closesocket (select_listening_socket);
1520 sp.wakeup = select_finished_event;
1521 sp.standby = select_standby_event;
1522 sp.wakeup_socket = select_wakeup_socket;
1524 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1528 handles_read = GNUNET_CONTAINER_slist_create ();
1529 handles_write = GNUNET_CONTAINER_slist_create ();
1530 handles_except = GNUNET_CONTAINER_slist_create ();
1541 FD_COPY (&rfds->sds, &aread);
1543 FD_COPY (&rfds->sds, &bread);
1548 FD_COPY (&wfds->sds, &awrite);
1550 FD_COPY (&wfds->sds, &bwrite);
1555 FD_COPY (&efds->sds, &aexcept);
1557 FD_COPY (&efds->sds, &bexcept);
1561 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1562 By profiling we detected that to be true in 90% of the cases.
1565 /* Do the select now */
1566 select_timeout.tv_sec = 0;
1567 select_timeout.tv_usec = 0;
1569 /* Copy all the writes to the except, so we can detect connect() errors */
1570 for (i = 0; i < awrite.fd_count; i++)
1571 FD_SET (awrite.fd_array[i], &aexcept);
1572 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1573 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1574 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1577 if (selectret == -1)
1579 /* Throw an error early on, while we still have the context. */
1580 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1581 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1585 /* Check aexcept, add its contents to awrite
1586 This is technically wrong (aexcept might have its own descriptors), we should
1587 have checked that descriptors were in awrite originally before re-adding them from
1588 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1589 for (i = 0; i < aexcept.fd_count; i++)
1590 FD_SET (aexcept.fd_array[i], &awrite);
1592 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1593 /* Sadly, it means code duplication :( */
1594 if ((selectret > 0) || (mcs_total == 0))
1597 if (rfds && read_handles)
1599 struct GNUNET_CONTAINER_SList_Iterator i;
1602 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1603 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1604 GNUNET_CONTAINER_slist_next (&i), c++)
1606 struct GNUNET_DISK_FileHandle *fh;
1608 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1609 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1615 DWORD waitstatus = 0;
1616 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1617 error = GetLastError ();
1618 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1619 c, fh->h, bret, waitstatus, error);
1622 /* TODO: either add more errors to this condition, or eliminate it
1623 * entirely (failed to peek -> pipe is in serious trouble, should
1624 * be selected as readable).
1626 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1629 else if (waitstatus <= 0)
1631 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1632 fh, sizeof (struct GNUNET_DISK_FileHandle));
1634 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1639 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1640 fh, sizeof (struct GNUNET_DISK_FileHandle));
1645 if (wfds && write_handles)
1647 LOG (GNUNET_ERROR_TYPE_DEBUG,
1648 "Adding the write ready event to the array as %d\n", nhandles);
1649 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1650 retcode += write_handles;
1652 if (efds && ex_handles)
1654 struct GNUNET_CONTAINER_SList_Iterator i;
1656 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1657 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1658 GNUNET_CONTAINER_slist_next (&i))
1660 struct GNUNET_DISK_FileHandle *fh;
1663 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1664 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1666 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1668 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1669 fh, sizeof (struct GNUNET_DISK_FileHandle));
1675 /* Add our select() result.*/
1677 retcode += selectret;
1681 GNUNET_NETWORK_fdset_zero (rfds);
1682 if (selectret != -1)
1683 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1684 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1688 GNUNET_NETWORK_fdset_zero (wfds);
1689 if (selectret != -1)
1690 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1691 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1695 GNUNET_NETWORK_fdset_zero (efds);
1696 if (selectret != -1)
1697 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1698 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1700 GNUNET_CONTAINER_slist_destroy (handles_read);
1701 GNUNET_CONTAINER_slist_destroy (handles_write);
1702 GNUNET_CONTAINER_slist_destroy (handles_except);
1704 if (selectret == -1)
1709 /* If we got this far, use slower implementation that is able to do a waiting select
1710 on both sockets and pipes simultaneously */
1712 /* Events for pipes */
1713 if (!hEventReadReady)
1714 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1715 if (!hEventPipeWrite)
1716 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1732 FD_COPY (&rfds->sds, &aread);
1734 FD_COPY (&rfds->sds, &bread);
1739 FD_COPY (&wfds->sds, &awrite);
1741 FD_COPY (&wfds->sds, &bwrite);
1746 FD_COPY (&efds->sds, &aexcept);
1748 FD_COPY (&efds->sds, &bexcept);
1751 /* We will first Add the PIPES to the events */
1753 if (rfds && read_handles)
1755 struct GNUNET_CONTAINER_SList_Iterator i;
1757 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1758 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1759 GNUNET_CONTAINER_slist_next (&i))
1761 struct GNUNET_DISK_FileHandle *fh;
1763 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1765 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1767 /* Read zero bytes to check the status of the pipe */
1768 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1770 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1772 DWORD error_code = GetLastError ();
1774 if (error_code == ERROR_IO_PENDING)
1776 LOG (GNUNET_ERROR_TYPE_DEBUG,
1777 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1779 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1780 readArray[readPipes++] = fh;
1784 LOG (GNUNET_ERROR_TYPE_DEBUG,
1785 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1786 handle_array[nhandles++] = hEventReadReady;
1787 readArray[readPipes++] = fh;
1792 LOG (GNUNET_ERROR_TYPE_DEBUG,
1793 "Adding the read ready event to the array as %d\n", nhandles);
1794 handle_array[nhandles++] = hEventReadReady;
1795 readArray[readPipes++] = fh;
1800 GNUNET_CONTAINER_slist_add (handles_read,
1801 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1802 fh, sizeof (struct GNUNET_DISK_FileHandle));
1806 if (wfds && write_handles)
1808 LOG (GNUNET_ERROR_TYPE_DEBUG,
1809 "Adding the write ready event to the array as %d\n", nhandles);
1810 handle_array[nhandles++] = hEventPipeWrite;
1811 writePipePos = nhandles;
1813 if (efds && ex_handles)
1815 struct GNUNET_CONTAINER_SList_Iterator i;
1817 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1818 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1819 GNUNET_CONTAINER_slist_next (&i))
1821 struct GNUNET_DISK_FileHandle *fh;
1824 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1826 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1828 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1830 GNUNET_CONTAINER_slist_add (handles_except,
1831 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1833 sizeof (struct GNUNET_DISK_FileHandle));
1843 LOG (GNUNET_ERROR_TYPE_DEBUG,
1844 "Adding the socket event to the array as %d\n",
1846 handle_array[nhandles++] = select_finished_event;
1847 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1851 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1852 select_timeout.tv_usec =(timeout.rel_value_us -
1853 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1854 sp.tv = &select_timeout;
1856 FD_SET (select_wakeup_socket, &aread);
1859 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1864 /* Failed connections cause sockets to be set in errorfds on W32,
1865 * but on POSIX it should set them in writefds.
1866 * First copy all awrite sockets to aexcept, later we'll
1867 * check aexcept and set its contents in awrite as well
1868 * Sockets are also set in errorfds when OOB data is available,
1869 * but we don't use OOB data.
1871 for (i = 0; i < awrite.fd_count; i++)
1872 FD_SET (awrite.fd_array[i], &aexcept);
1873 ResetEvent (select_finished_event);
1874 SetEvent (select_standby_event);
1877 handle_array[nhandles] = NULL;
1878 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
1879 nfds, nhandles, mcs_total);
1883 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
1884 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode);
1888 GNUNET_break (0); /* This branch shouldn't actually be executed...*/
1889 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1890 returncode = WAIT_TIMEOUT;
1894 /* Shouldn't come this far. If it does - investigate. */
1900 /* Don't wake up select-thread when delay is 0, it should return immediately
1901 * and wake up by itself.
1904 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1905 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1906 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1911 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1914 /* Check aexcept, add its contents to awrite */
1915 for (i = 0; i < aexcept.fd_count; i++)
1916 FD_SET (aexcept.fd_array[i], &awrite);
1919 returnedpos = returncode - WAIT_OBJECT_0;
1920 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1922 if (nhandles && (returnedpos < nhandles))
1927 retcode += sp.status;
1929 if ((writePipePos != -1) && (returnedpos < writePipePos))
1931 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1932 retcode += write_handles;
1933 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1935 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1936 /* We have some pipes ready for read. */
1937 if (returnedpos < readPipes)
1939 for (i = 0; i < readPipes; i++)
1947 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1948 error = GetLastError ();
1949 LOG (GNUNET_ERROR_TYPE_DEBUG,
1950 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1951 i, readArray[i]->h, bret, waitstatus, error);
1954 /* TODO: either add more errors to this condition, or eliminate it
1955 * entirely (failed to peek -> pipe is in serious trouble, should
1956 * be selected as readable).
1958 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1961 else if (waitstatus <= 0)
1963 GNUNET_CONTAINER_slist_add (handles_read,
1964 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1966 sizeof (struct GNUNET_DISK_FileHandle));
1968 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1969 readArray[i], readArray[i]->h);
1973 if (!nhandles || (returnedpos >= nhandles))
1974 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1977 struct GNUNET_CONTAINER_SList_Iterator t;
1979 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1980 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1981 GNUNET_CONTAINER_slist_next (&t))
1983 struct GNUNET_DISK_FileHandle *fh;
1985 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1987 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1992 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1993 GNUNET_NETWORK_fdset_zero (rfds);
1994 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1995 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1996 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
2000 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
2001 GNUNET_NETWORK_fdset_zero (wfds);
2002 if (retcode != -1 && nhandles && (returnedpos < nhandles))
2003 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
2004 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
2008 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
2009 GNUNET_NETWORK_fdset_zero (efds);
2010 if (retcode != -1 && nhandles && (returnedpos < nhandles))
2011 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
2012 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
2014 GNUNET_CONTAINER_slist_destroy (handles_read);
2015 GNUNET_CONTAINER_slist_destroy (handles_write);
2016 GNUNET_CONTAINER_slist_destroy (handles_except);
2020 struct GNUNET_CONTAINER_SList_Iterator t;
2022 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
2023 for (i = 0; i < rfds->sds.fd_count; i++)
2025 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
2027 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
2028 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
2029 GNUNET_CONTAINER_slist_next (&t))
2031 struct GNUNET_DISK_FileHandle *fh;
2033 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
2035 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
2040 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
2041 for (i = 0; i < wfds->sds.fd_count; i++)
2043 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
2048 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
2049 for (i = 0; i < efds->sds.fd_count; i++)
2051 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
2054 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
2056 if (nhandles && (returnedpos < nhandles))
2063 /* end of network.c */