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,
168 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
171 SetErrnoFromWinsockError (WSAGetLastError ());
172 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
173 return GNUNET_SYSERR;
179 int flags = fcntl (fd->fd, F_GETFL);
184 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
185 return GNUNET_SYSERR;
188 flags &= ~O_NONBLOCK;
192 if (0 != fcntl (fd->fd, F_SETFL, flags))
195 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
196 return GNUNET_SYSERR;
204 * Make a socket non-inheritable to child processes
206 * @param h the socket to make non-inheritable
207 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
208 * @warning Not implemented on Windows
211 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
215 i = fcntl (h->fd, F_GETFD);
217 return GNUNET_SYSERR;
218 if (i == (i | FD_CLOEXEC))
221 if (fcntl (h->fd, F_SETFD, i) < 0)
222 return GNUNET_SYSERR;
226 b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
229 SetErrnoFromWinsockError (WSAGetLastError ());
230 return GNUNET_SYSERR;
239 * The MSG_NOSIGNAL equivalent on Mac OS X
241 * @param h the socket to make non-delaying
244 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
249 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE,
250 (const void *) &abs_value,
252 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
258 * Disable delays when sending data via the socket.
259 * (GNUnet makes sure that messages are as big as
262 * @param h the socket to make non-delaying
265 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
270 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
271 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
273 const char *abs_value = "1";
276 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY,
277 (const void *) abs_value,
279 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
285 * Perform proper canonical initialization for a network handle.
286 * Set it to non-blocking, make it non-inheritable to child
287 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
288 * stream socket) and check that it is smaller than FD_SETSIZE.
290 * @param h socket to initialize
291 * @param af address family of the socket
292 * @param type socket type
293 * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
294 * failed and the handle was destroyed
297 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
302 if (h->fd == INVALID_SOCKET)
305 SetErrnoFromWinsockError (WSAGetLastError ());
308 return GNUNET_SYSERR;
311 if (h->fd >= FD_SETSIZE)
313 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
315 return GNUNET_SYSERR;
318 if (GNUNET_OK != socket_set_inheritable (h))
319 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
320 "socket_set_inheritable");
322 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
325 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
326 return GNUNET_SYSERR;
329 socket_set_nosigpipe (h);
331 if ( (type == SOCK_STREAM)
336 socket_set_nodelay (h);
342 * accept a new connection on a socket
344 * @param desc bound socket
345 * @param address address of the connecting peer, may be NULL
346 * @param address_len length of @a address
347 * @return client socket
349 struct GNUNET_NETWORK_Handle *
350 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
351 struct sockaddr *address,
352 socklen_t *address_len)
354 struct GNUNET_NETWORK_Handle *ret;
356 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
359 struct sockaddr name;
360 socklen_t namelen = sizeof (name);
361 int gsn = getsockname (desc->fd, &name, &namelen);
364 LOG (GNUNET_ERROR_TYPE_DEBUG,
365 "Accepting connection on `%s'\n",
366 GNUNET_a2s (&name, namelen));
369 ret->fd = accept (desc->fd, address, address_len);
375 if (GNUNET_OK != initialize_network_handle (ret,
376 (NULL != address) ? address->sa_family : desc->af,
384 * Bind a socket to a particular address.
386 * @param desc socket to bind
387 * @param address address to be bound
388 * @param address_len length of @a address
389 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
392 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
393 const struct sockaddr *address,
394 socklen_t address_len)
403 if (AF_INET6 == desc->af)
404 if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY,
407 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
415 /* This is required here for TCP sockets, but only on UNIX */
416 if ((SOCK_STREAM == desc->type)
417 && (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))))
418 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
423 /* set permissions of newly created non-abstract UNIX domain socket to
424 "user-only"; applications can choose to relax this later */
425 mode_t old_mask = 0; /* assigned to make compiler happy */
426 const struct sockaddr_un *un;
427 int not_abstract = 0;
429 if ((AF_UNIX == address->sa_family)
430 && (NULL != (un = (const struct sockaddr_un *) address)->sun_path)
431 && ('\0' != un->sun_path[0]) ) /* Not an abstract socket */
434 old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH);
437 ret = bind (desc->fd, address, address_len);
440 (void) umask (old_mask);
444 if (SOCKET_ERROR == ret)
445 SetErrnoFromWinsockError (WSAGetLastError ());
448 return GNUNET_SYSERR;
450 desc->addr = GNUNET_malloc (address_len);
451 memcpy (desc->addr, address, address_len);
452 desc->addrlen = address_len;
462 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
465 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
473 ret = closesocket (desc->fd);
474 error = WSAGetLastError ();
475 SetErrnoFromWinsockError (error);
476 LOG (GNUNET_ERROR_TYPE_DEBUG,
477 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
480 ret = close (desc->fd);
483 const struct sockaddr_un *un;
485 /* Cleanup the UNIX domain socket and its parent directories in case of non
487 if ((AF_UNIX == desc->af) && (NULL != desc->addr)
488 && (NULL != (un = (const struct sockaddr_un *) desc->addr)->sun_path)
489 && ('\0' != un->sun_path[0]))
491 char *dirname = GNUNET_strndup (un->sun_path,
492 sizeof (un->sun_path));
494 if (0 != unlink (dirname))
496 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
504 len = strlen (dirname);
505 while ((len > 0) && (dirname[len] != DIR_SEPARATOR))
508 if ((0 != len) && (0 != rmdir (dirname)))
515 /* these are normal and can just be ignored */
518 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
525 GNUNET_free (dirname);
528 GNUNET_NETWORK_socket_free_memory_only_ (desc);
529 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
534 * Only free memory of a socket, keep the file descriptor untouched.
539 GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc)
541 GNUNET_free_non_null (desc->addr);
547 * Box a native socket (and check that it is a socket).
549 * @param fd socket to box
550 * @return NULL on error (including not supported on target platform)
552 struct GNUNET_NETWORK_Handle *
553 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
555 struct GNUNET_NETWORK_Handle *ret;
559 /* FIXME: Find a better call to check that FD is valid */
560 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
561 return NULL; /* invalid FD */
562 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
567 if (fcntl (fd, F_GETFD) < 0)
568 return NULL; /* invalid FD */
569 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
578 * Connect a socket to some remote address.
581 * @param address peer address
582 * @param address_len length of @a address
583 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
586 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
587 const struct sockaddr *address,
588 socklen_t address_len)
592 ret = connect (desc->fd, address, address_len);
595 if (SOCKET_ERROR == ret)
597 SetErrnoFromWinsockError (WSAGetLastError ());
598 if (errno == EWOULDBLOCK)
602 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
610 * @param level protocol level of the option
611 * @param optname identifier of the option
612 * @param optval options
613 * @param optlen length of @a optval
614 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
617 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
618 int level, int optname, void *optval,
623 ret = getsockopt (desc->fd, level, optname, optval, optlen);
626 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
627 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
629 else if (SOCKET_ERROR == ret)
630 SetErrnoFromWinsockError (WSAGetLastError ());
632 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
640 * @param backlog length of the listen queue
641 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
644 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
649 ret = listen (desc->fd, backlog);
652 if (SOCKET_ERROR == ret)
653 SetErrnoFromWinsockError (WSAGetLastError ());
656 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
661 * How much data is available to be read on this descriptor?
664 * @returns #GNUNET_NO if no data is available, or on error!
667 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
672 /* How much is there to be read? */
676 error = ioctl (desc->fd, FIONREAD, &pending);
678 return (ssize_t) pending;
683 error = ioctlsocket (desc->fd, FIONREAD, &pending);
684 if (error != SOCKET_ERROR)
685 return (ssize_t) pending;
692 * Read data from a socket (always non-blocking).
695 * @param buffer buffer
696 * @param length length of @a buffer
697 * @param src_addr either the source to recv from, or all zeroes
698 * to be filled in by recvfrom
699 * @param addrlen length of the @a src_addr
702 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
703 void *buffer, size_t length,
704 struct sockaddr *src_addr, socklen_t *addrlen)
712 flags |= MSG_DONTWAIT;
715 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
717 if (SOCKET_ERROR == ret)
718 SetErrnoFromWinsockError (WSAGetLastError ());
725 * Read data from a connected socket (always non-blocking).
728 * @param buffer buffer
729 * @param length length of @a buffer
732 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
733 void *buffer, size_t length)
741 flags |= MSG_DONTWAIT;
743 ret = recv (desc->fd, buffer, length, flags);
745 if (SOCKET_ERROR == ret)
746 SetErrnoFromWinsockError (WSAGetLastError ());
753 * Send data (always non-blocking).
756 * @param buffer data to send
757 * @param length size of the @a buffer
758 * @return number of bytes sent, #GNUNET_SYSERR on error
761 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
762 const void *buffer, size_t length)
770 flags |= MSG_DONTWAIT;
774 flags |= MSG_NOSIGNAL;
777 ret = send (desc->fd, buffer, length, flags);
780 if (SOCKET_ERROR == ret)
781 SetErrnoFromWinsockError (WSAGetLastError ());
789 * Send data to a particular destination (always non-blocking).
790 * This function only works for UDP sockets.
793 * @param message data to send
794 * @param length size of the data
795 * @param dest_addr destination address
796 * @param dest_len length of @a address
797 * @return number of bytes sent, #GNUNET_SYSERR on error
800 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
801 const void *message, size_t length,
802 const struct sockaddr * dest_addr,
811 flags |= MSG_DONTWAIT;
814 flags |= MSG_NOSIGNAL;
816 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
818 if (SOCKET_ERROR == ret)
819 SetErrnoFromWinsockError (WSAGetLastError ());
829 * @param level protocol level of the option
830 * @param option_name option identifier
831 * @param option_value value to set
832 * @param option_len size of option_value
833 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
836 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
837 int option_name, const void *option_value,
838 socklen_t option_len)
842 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
844 if (SOCKET_ERROR == ret)
845 SetErrnoFromWinsockError (WSAGetLastError ());
847 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
852 * Create a new socket. Configure it for non-blocking IO and
853 * mark it as non-inheritable to child processes (set the
854 * close-on-exec flag).
856 * @param domain domain of the socket
857 * @param type socket type
858 * @param protocol network protocol
859 * @return new socket, NULL on error
861 struct GNUNET_NETWORK_Handle *
862 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
864 struct GNUNET_NETWORK_Handle *ret;
866 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
867 ret->fd = socket (domain, type, protocol);
874 initialize_network_handle (ret, domain, type))
881 * Shut down socket operations
883 * @param how type of shutdown
884 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
887 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
891 ret = shutdown (desc->fd, how);
894 SetErrnoFromWinsockError (WSAGetLastError ());
896 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
901 * Disable the "CORK" feature for communication with the given socket,
902 * forcing the OS to immediately flush the buffer on transmission
903 * instead of potentially buffering multiple messages. Essentially
904 * reduces the OS send buffers to zero.
907 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
910 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
919 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
921 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
924 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
926 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
932 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
933 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
936 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
937 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
939 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
949 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
954 GNUNET_CONTAINER_slist_clear (fds->handles);
960 * Add a socket to the FD set
963 * @param desc socket to add
966 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
967 const struct GNUNET_NETWORK_Handle *desc)
969 FD_SET (desc->fd, &fds->sds);
970 if (desc->fd + 1 > fds->nsds)
971 fds->nsds = desc->fd + 1;
976 * Check whether a socket is part of the fd set
980 * @return 0 if the FD is not set
983 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
984 const struct GNUNET_NETWORK_Handle *desc)
986 return FD_ISSET (desc->fd, &fds->sds);
991 * Add one fd set to another
993 * @param dst the fd set to add to
994 * @param src the fd set to add from
997 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
998 const struct GNUNET_NETWORK_FDSet *src)
1003 for (nfds = src->nsds; nfds >= 0; nfds--)
1004 if (FD_ISSET (nfds, &src->sds))
1007 FD_SET (nfds, &dst->sds);
1008 if (nfds + 1 > dst->nsds)
1009 dst->nsds = nfds + 1;
1012 /* This is MinGW32-specific implementation that relies on the code that
1013 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
1014 * that fd being added is not already in the set.
1015 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
1018 for (i = 0; i < src->sds.fd_count; i++)
1019 FD_SET (src->sds.fd_array[i], &dst->sds);
1020 if (src->nsds > dst->nsds)
1021 dst->nsds = src->nsds;
1023 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
1029 * Copy one fd set to another
1031 * @param to destination
1032 * @param from source
1035 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
1036 const struct GNUNET_NETWORK_FDSet *from)
1038 FD_COPY (&from->sds, &to->sds);
1039 to->nsds = from->nsds;
1042 GNUNET_CONTAINER_slist_clear (to->handles);
1043 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
1049 * Return file descriptor for this network handle
1051 * @param desc wrapper to process
1052 * @return POSIX file descriptor
1055 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
1062 * Return sockaddr for this network handle
1064 * @param desc wrapper to process
1068 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1075 * Return sockaddr length for this network handle
1077 * @param desc wrapper to process
1078 * @return socklen_t for sockaddr
1081 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1083 return desc->addrlen;
1088 * Copy a native fd set
1090 * @param to destination
1091 * @param from native source set
1092 * @param nfds the biggest socket number in from + 1
1095 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1096 const fd_set * from, int nfds)
1098 FD_COPY (from, &to->sds);
1104 * Set a native fd in a set
1106 * @param to destination
1107 * @param nfd native FD to set
1110 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1112 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1113 FD_SET (nfd, &to->sds);
1114 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1119 * Test native fd in a set
1121 * @param to set to test, NULL for empty set
1122 * @param nfd native FD to test, or -1 for none
1123 * @return #GNUNET_YES if FD is set in the set
1126 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1129 if ((nfd == -1) || (to == NULL))
1131 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1136 * Add a file handle to the fd set
1138 * @param h the file handle to add
1141 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1142 const struct GNUNET_DISK_FileHandle *h)
1145 GNUNET_CONTAINER_slist_add (fds->handles,
1146 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1147 sizeof (struct GNUNET_DISK_FileHandle));
1152 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1153 FD_SET (fd, &fds->sds);
1154 if (fd + 1 > fds->nsds)
1162 * Check if a file handle is part of an fd set
1164 * @param h file handle
1165 * @return #GNUNET_YES if the file handle is part of the set
1168 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1169 const struct GNUNET_DISK_FileHandle *h)
1173 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1175 GNUNET_DISK_FileHandle));
1177 return FD_ISSET (h->fd, &fds->sds);
1183 * Checks if two fd sets overlap
1184 * @param fds1 first fd set
1185 * @param fds2 second fd set
1186 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1189 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1190 const struct GNUNET_NETWORK_FDSet *fds2)
1196 if (nfds > fds2->nsds)
1201 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1205 struct GNUNET_CONTAINER_SList_Iterator it;
1206 struct GNUNET_DISK_FileHandle *h;
1210 /*This code is somewhat hacky, we are not supposed to know what's
1211 * inside of fd_set; also the O(n^2) is really bad... */
1213 for (i = 0; i < fds1->sds.fd_count; i++)
1215 for (j = 0; j < fds2->sds.fd_count; j++)
1217 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1221 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1222 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1225 struct GNUNET_CONTAINER_SList_Iterator t;
1227 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1230 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1232 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1233 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1234 GNUNET_CONTAINER_slist_next (&t))
1236 struct GNUNET_DISK_FileHandle *fh;
1238 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1240 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1243 if (GNUNET_CONTAINER_slist_contains
1244 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1248 GNUNET_CONTAINER_slist_next (&it);
1258 * @return a new fd set
1260 struct GNUNET_NETWORK_FDSet *
1261 GNUNET_NETWORK_fdset_create ()
1263 struct GNUNET_NETWORK_FDSet *fds;
1265 fds = GNUNET_new (struct GNUNET_NETWORK_FDSet);
1267 fds->handles = GNUNET_CONTAINER_slist_create ();
1269 GNUNET_NETWORK_fdset_zero (fds);
1275 * Releases the associated memory of an fd set
1280 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1283 GNUNET_CONTAINER_slist_destroy (fds->handles);
1289 struct _select_params
1297 SOCKET wakeup_socket;
1302 _selector (LPVOID p)
1304 struct _select_params *sp = p;
1308 WaitForSingleObject (sp->standby, INFINITE);
1309 ResetEvent (sp->standby);
1310 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1311 if (FD_ISSET (sp->wakeup_socket, sp->r))
1313 FD_CLR (sp->wakeup_socket, sp->r);
1316 SetEvent (sp->wakeup);
1325 * 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)
1347 nfds = GNUNET_MAX (nfds, wfds->nsds);
1349 nfds = GNUNET_MAX (nfds, efds->nsds);
1351 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us))
1354 LOG (GNUNET_ERROR_TYPE_ERROR,
1355 _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1358 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1360 (timeout.rel_value_us -
1361 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1362 return select (nfds,
1363 (NULL != rfds) ? &rfds->sds : NULL,
1364 (NULL != wfds) ? &wfds->sds : NULL,
1365 (NULL != efds) ? &efds->sds : NULL,
1366 (timeout.rel_value_us ==
1367 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1376 * Check if sockets or pipes meet certain conditions, version for W32.
1378 * @param rfds set of sockets or pipes to be checked for readability
1379 * @param wfds set of sockets or pipes to be checked for writability
1380 * @param efds set of sockets or pipes to be checked for exceptions
1381 * @param timeout relative value when to return
1382 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1385 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1386 struct GNUNET_NETWORK_FDSet *wfds,
1387 struct GNUNET_NETWORK_FDSet *efds,
1388 const struct GNUNET_TIME_Relative timeout)
1393 int read_handles = 0;
1394 int write_handles = 0;
1398 uint64_t mcs_total = 0;
1399 DWORD ms_rounded = 0;
1403 static HANDLE hEventPipeWrite = 0;
1404 static HANDLE hEventReadReady = 0;
1406 static struct _select_params sp;
1407 static HANDLE select_thread = NULL;
1408 static HANDLE select_finished_event = NULL;
1409 static HANDLE select_standby_event = NULL;
1410 static SOCKET select_wakeup_socket = -1;
1411 static SOCKET select_send_socket = -1;
1412 static struct timeval select_timeout;
1415 int writePipePos = 0;
1417 HANDLE handle_array[FD_SETSIZE + 2];
1418 int returncode = -1;
1419 int returnedpos = 0;
1421 struct GNUNET_CONTAINER_SList *handles_read;
1422 struct GNUNET_CONTAINER_SList *handles_write;
1423 struct GNUNET_CONTAINER_SList *handles_except;
1437 /* TODO: Make this growable */
1438 struct GNUNET_DISK_FileHandle *readArray[50];
1444 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1447 struct GNUNET_CONTAINER_SList_Iterator t;
1449 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1450 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1451 GNUNET_CONTAINER_slist_next (&t))
1453 struct GNUNET_DISK_FileHandle *fh;
1455 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1457 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1465 nfds = GNUNET_MAX (nfds, wfds->nsds);
1466 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1470 nfds = GNUNET_MAX (nfds, efds->nsds);
1471 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1475 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1479 LOG (GNUNET_ERROR_TYPE_ERROR,
1480 _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1483 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1484 /* calculate how long we need to wait in microseconds */
1485 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1487 mcs_total = INFINITE;
1488 ms_rounded = INFINITE;
1492 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1493 ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1494 if (mcs_total > 0 && ms_rounded == 0)
1497 /* select() may be used as a portable way to sleep */
1498 if (!(rfds || wfds || efds))
1504 if (NULL == select_thread)
1506 SOCKET select_listening_socket = -1;
1507 struct sockaddr_in s_in;
1512 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1513 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1515 select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1517 select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1520 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1521 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1523 alen = sizeof (s_in);
1524 s_in.sin_family = AF_INET;
1526 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1527 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1528 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1529 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1530 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1531 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1533 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1534 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1536 res = listen (select_listening_socket, SOMAXCONN);
1537 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1539 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1540 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1542 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1544 closesocket (select_listening_socket);
1546 sp.wakeup = select_finished_event;
1547 sp.standby = select_standby_event;
1548 sp.wakeup_socket = select_wakeup_socket;
1550 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1554 handles_read = GNUNET_CONTAINER_slist_create ();
1555 handles_write = GNUNET_CONTAINER_slist_create ();
1556 handles_except = GNUNET_CONTAINER_slist_create ();
1567 FD_COPY (&rfds->sds, &aread);
1569 FD_COPY (&rfds->sds, &bread);
1574 FD_COPY (&wfds->sds, &awrite);
1576 FD_COPY (&wfds->sds, &bwrite);
1581 FD_COPY (&efds->sds, &aexcept);
1583 FD_COPY (&efds->sds, &bexcept);
1587 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1588 By profiling we detected that to be true in 90% of the cases.
1591 /* Do the select now */
1592 select_timeout.tv_sec = 0;
1593 select_timeout.tv_usec = 0;
1595 /* Copy all the writes to the except, so we can detect connect() errors */
1596 for (i = 0; i < awrite.fd_count; i++)
1597 FD_SET (awrite.fd_array[i], &aexcept);
1598 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1599 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1600 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1603 if (selectret == -1)
1605 /* Throw an error early on, while we still have the context. */
1606 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1607 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1611 /* Check aexcept, add its contents to awrite
1612 This is technically wrong (aexcept might have its own descriptors), we should
1613 have checked that descriptors were in awrite originally before re-adding them from
1614 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1615 for (i = 0; i < aexcept.fd_count; i++)
1616 FD_SET (aexcept.fd_array[i], &awrite);
1618 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1619 /* Sadly, it means code duplication :( */
1620 if ((selectret > 0) || (mcs_total == 0))
1623 if (rfds && read_handles)
1625 struct GNUNET_CONTAINER_SList_Iterator i;
1628 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1629 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1630 GNUNET_CONTAINER_slist_next (&i), c++)
1632 struct GNUNET_DISK_FileHandle *fh;
1634 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1635 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1641 DWORD waitstatus = 0;
1642 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1643 error = GetLastError ();
1644 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1645 c, fh->h, bret, waitstatus, error);
1648 /* TODO: either add more errors to this condition, or eliminate it
1649 * entirely (failed to peek -> pipe is in serious trouble, should
1650 * be selected as readable).
1652 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1655 else if (waitstatus <= 0)
1657 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1658 fh, sizeof (struct GNUNET_DISK_FileHandle));
1660 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1665 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1666 fh, sizeof (struct GNUNET_DISK_FileHandle));
1671 if (wfds && write_handles)
1673 LOG (GNUNET_ERROR_TYPE_DEBUG,
1674 "Adding the write ready event to the array as %d\n", nhandles);
1675 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1676 retcode += write_handles;
1678 if (efds && ex_handles)
1680 struct GNUNET_CONTAINER_SList_Iterator i;
1682 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1683 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1684 GNUNET_CONTAINER_slist_next (&i))
1686 struct GNUNET_DISK_FileHandle *fh;
1689 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1690 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1692 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1694 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1695 fh, sizeof (struct GNUNET_DISK_FileHandle));
1701 /* Add our select() result.*/
1703 retcode += selectret;
1707 GNUNET_NETWORK_fdset_zero (rfds);
1708 if (selectret != -1)
1709 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1710 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1714 GNUNET_NETWORK_fdset_zero (wfds);
1715 if (selectret != -1)
1716 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1717 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1721 GNUNET_NETWORK_fdset_zero (efds);
1722 if (selectret != -1)
1723 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1724 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1726 GNUNET_CONTAINER_slist_destroy (handles_read);
1727 GNUNET_CONTAINER_slist_destroy (handles_write);
1728 GNUNET_CONTAINER_slist_destroy (handles_except);
1730 if (selectret == -1)
1735 /* If we got this far, use slower implementation that is able to do a waiting select
1736 on both sockets and pipes simultaneously */
1738 /* Events for pipes */
1739 if (!hEventReadReady)
1740 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1741 if (!hEventPipeWrite)
1742 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1758 FD_COPY (&rfds->sds, &aread);
1760 FD_COPY (&rfds->sds, &bread);
1765 FD_COPY (&wfds->sds, &awrite);
1767 FD_COPY (&wfds->sds, &bwrite);
1772 FD_COPY (&efds->sds, &aexcept);
1774 FD_COPY (&efds->sds, &bexcept);
1777 /* We will first Add the PIPES to the events */
1779 if (rfds && read_handles)
1781 struct GNUNET_CONTAINER_SList_Iterator i;
1783 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1784 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1785 GNUNET_CONTAINER_slist_next (&i))
1787 struct GNUNET_DISK_FileHandle *fh;
1789 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1791 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1793 /* Read zero bytes to check the status of the pipe */
1794 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1796 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1798 DWORD error_code = GetLastError ();
1800 if (error_code == ERROR_IO_PENDING)
1802 LOG (GNUNET_ERROR_TYPE_DEBUG,
1803 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1805 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1806 readArray[readPipes++] = fh;
1810 LOG (GNUNET_ERROR_TYPE_DEBUG,
1811 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1812 handle_array[nhandles++] = hEventReadReady;
1813 readArray[readPipes++] = fh;
1818 LOG (GNUNET_ERROR_TYPE_DEBUG,
1819 "Adding the read ready event to the array as %d\n", nhandles);
1820 handle_array[nhandles++] = hEventReadReady;
1821 readArray[readPipes++] = fh;
1826 GNUNET_CONTAINER_slist_add (handles_read,
1827 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1828 fh, sizeof (struct GNUNET_DISK_FileHandle));
1832 if (wfds && write_handles)
1834 LOG (GNUNET_ERROR_TYPE_DEBUG,
1835 "Adding the write ready event to the array as %d\n", nhandles);
1836 handle_array[nhandles++] = hEventPipeWrite;
1837 writePipePos = nhandles;
1839 if (efds && ex_handles)
1841 struct GNUNET_CONTAINER_SList_Iterator i;
1843 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1844 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1845 GNUNET_CONTAINER_slist_next (&i))
1847 struct GNUNET_DISK_FileHandle *fh;
1850 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1852 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1854 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1856 GNUNET_CONTAINER_slist_add (handles_except,
1857 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1859 sizeof (struct GNUNET_DISK_FileHandle));
1869 LOG (GNUNET_ERROR_TYPE_DEBUG,
1870 "Adding the socket event to the array as %d\n",
1872 handle_array[nhandles++] = select_finished_event;
1873 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1877 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1878 select_timeout.tv_usec =(timeout.rel_value_us -
1879 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1880 sp.tv = &select_timeout;
1882 FD_SET (select_wakeup_socket, &aread);
1885 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1890 /* Failed connections cause sockets to be set in errorfds on W32,
1891 * but on POSIX it should set them in writefds.
1892 * First copy all awrite sockets to aexcept, later we'll
1893 * check aexcept and set its contents in awrite as well
1894 * Sockets are also set in errorfds when OOB data is available,
1895 * but we don't use OOB data.
1897 for (i = 0; i < awrite.fd_count; i++)
1898 FD_SET (awrite.fd_array[i], &aexcept);
1899 ResetEvent (select_finished_event);
1900 SetEvent (select_standby_event);
1903 handle_array[nhandles] = NULL;
1904 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
1905 nfds, nhandles, mcs_total);
1909 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
1910 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode);
1914 GNUNET_break (0); /* This branch shouldn't actually be executed...*/
1915 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1916 returncode = WAIT_TIMEOUT;
1920 /* Shouldn't come this far. If it does - investigate. */
1926 /* Don't wake up select-thread when delay is 0, it should return immediately
1927 * and wake up by itself.
1930 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1931 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1932 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1937 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1940 /* Check aexcept, add its contents to awrite */
1941 for (i = 0; i < aexcept.fd_count; i++)
1942 FD_SET (aexcept.fd_array[i], &awrite);
1945 returnedpos = returncode - WAIT_OBJECT_0;
1946 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1948 if (nhandles && (returnedpos < nhandles))
1953 retcode += sp.status;
1955 if ((writePipePos != -1) && (returnedpos < writePipePos))
1957 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1958 retcode += write_handles;
1959 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1961 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1962 /* We have some pipes ready for read. */
1963 if (returnedpos < readPipes)
1965 for (i = 0; i < readPipes; i++)
1973 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1974 error = GetLastError ();
1975 LOG (GNUNET_ERROR_TYPE_DEBUG,
1976 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1977 i, readArray[i]->h, bret, waitstatus, error);
1980 /* TODO: either add more errors to this condition, or eliminate it
1981 * entirely (failed to peek -> pipe is in serious trouble, should
1982 * be selected as readable).
1984 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1987 else if (waitstatus <= 0)
1989 GNUNET_CONTAINER_slist_add (handles_read,
1990 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1992 sizeof (struct GNUNET_DISK_FileHandle));
1994 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1995 readArray[i], readArray[i]->h);
1999 if (!nhandles || (returnedpos >= nhandles))
2000 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
2003 struct GNUNET_CONTAINER_SList_Iterator t;
2005 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
2006 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
2007 GNUNET_CONTAINER_slist_next (&t))
2009 struct GNUNET_DISK_FileHandle *fh;
2011 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
2013 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
2018 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
2019 GNUNET_NETWORK_fdset_zero (rfds);
2020 if (retcode != -1 && nhandles && (returnedpos < nhandles))
2021 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
2022 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
2026 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
2027 GNUNET_NETWORK_fdset_zero (wfds);
2028 if (retcode != -1 && nhandles && (returnedpos < nhandles))
2029 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
2030 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
2034 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
2035 GNUNET_NETWORK_fdset_zero (efds);
2036 if (retcode != -1 && nhandles && (returnedpos < nhandles))
2037 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
2038 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
2040 GNUNET_CONTAINER_slist_destroy (handles_read);
2041 GNUNET_CONTAINER_slist_destroy (handles_write);
2042 GNUNET_CONTAINER_slist_destroy (handles_except);
2046 struct GNUNET_CONTAINER_SList_Iterator t;
2048 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
2049 for (i = 0; i < rfds->sds.fd_count; i++)
2051 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
2053 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
2054 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
2055 GNUNET_CONTAINER_slist_next (&t))
2057 struct GNUNET_DISK_FileHandle *fh;
2059 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
2061 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
2066 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
2067 for (i = 0; i < wfds->sds.fd_count; i++)
2069 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
2074 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
2075 for (i = 0; i < efds->sds.fd_count; i++)
2077 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
2080 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
2082 if (nhandles && (returnedpos < nhandles))
2091 /* end of network.c */