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 UNIX domain socket to "user-only"; applications
424 can choose to relax this later */
425 mode_t old_mask = 0; /* assigned to make compiler happy */
427 if (AF_UNIX == address->sa_family)
428 old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH);
431 ret = bind (desc->fd, address, address_len);
433 if (AF_UNIX == address->sa_family)
434 (void) umask (old_mask);
438 if (SOCKET_ERROR == ret)
439 SetErrnoFromWinsockError (WSAGetLastError ());
442 return GNUNET_SYSERR;
444 desc->addr = GNUNET_malloc (address_len);
445 memcpy (desc->addr, address, address_len);
446 desc->addrlen = address_len;
456 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
459 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
467 ret = closesocket (desc->fd);
468 error = WSAGetLastError ();
469 SetErrnoFromWinsockError (error);
470 LOG (GNUNET_ERROR_TYPE_DEBUG,
471 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
474 ret = close (desc->fd);
477 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
479 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
480 char *dirname = GNUNET_strndup (un->sun_path,
481 sizeof (un->sun_path));
483 if (0 != unlink (dirname))
485 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
493 len = strlen (dirname);
494 while ((len > 0) && (dirname[len] != DIR_SEPARATOR))
497 if (0 != rmdir (dirname))
504 /* these are normal and can just be ignored */
507 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
514 GNUNET_free (dirname);
517 GNUNET_NETWORK_socket_free_memory_only_ (desc);
518 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
523 * Only free memory of a socket, keep the file descriptor untouched.
528 GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc)
530 GNUNET_free_non_null (desc->addr);
536 * Box a native socket (and check that it is a socket).
538 * @param fd socket to box
539 * @return NULL on error (including not supported on target platform)
541 struct GNUNET_NETWORK_Handle *
542 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
544 struct GNUNET_NETWORK_Handle *ret;
548 /* FIXME: Find a better call to check that FD is valid */
549 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
550 return NULL; /* invalid FD */
551 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
556 if (fcntl (fd, F_GETFD) < 0)
557 return NULL; /* invalid FD */
558 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
567 * Connect a socket to some remote address.
570 * @param address peer address
571 * @param address_len length of @a address
572 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
575 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
576 const struct sockaddr *address,
577 socklen_t address_len)
581 ret = connect (desc->fd, address, address_len);
584 if (SOCKET_ERROR == ret)
586 SetErrnoFromWinsockError (WSAGetLastError ());
587 if (errno == EWOULDBLOCK)
591 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
599 * @param level protocol level of the option
600 * @param optname identifier of the option
601 * @param optval options
602 * @param optlen length of @a optval
603 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
606 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
607 int level, int optname, void *optval,
612 ret = getsockopt (desc->fd, level, optname, optval, optlen);
615 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
616 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
618 else if (SOCKET_ERROR == ret)
619 SetErrnoFromWinsockError (WSAGetLastError ());
621 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
629 * @param backlog length of the listen queue
630 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
633 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
638 ret = listen (desc->fd, backlog);
641 if (SOCKET_ERROR == ret)
642 SetErrnoFromWinsockError (WSAGetLastError ());
645 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
650 * How much data is available to be read on this descriptor?
653 * @returns #GNUNET_NO if no data is available, or on error!
656 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
661 /* How much is there to be read? */
665 error = ioctl (desc->fd, FIONREAD, &pending);
667 return (ssize_t) pending;
672 error = ioctlsocket (desc->fd, FIONREAD, &pending);
673 if (error != SOCKET_ERROR)
674 return (ssize_t) pending;
681 * Read data from a socket (always non-blocking).
684 * @param buffer buffer
685 * @param length length of @a buffer
686 * @param src_addr either the source to recv from, or all zeroes
687 * to be filled in by recvfrom
688 * @param addrlen length of the @a src_addr
691 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
692 void *buffer, size_t length,
693 struct sockaddr *src_addr, socklen_t *addrlen)
701 flags |= MSG_DONTWAIT;
704 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
706 if (SOCKET_ERROR == ret)
707 SetErrnoFromWinsockError (WSAGetLastError ());
714 * Read data from a connected socket (always non-blocking).
717 * @param buffer buffer
718 * @param length length of @a buffer
721 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
722 void *buffer, size_t length)
730 flags |= MSG_DONTWAIT;
732 ret = recv (desc->fd, buffer, length, flags);
734 if (SOCKET_ERROR == ret)
735 SetErrnoFromWinsockError (WSAGetLastError ());
742 * Send data (always non-blocking).
745 * @param buffer data to send
746 * @param length size of the @a buffer
747 * @return number of bytes sent, #GNUNET_SYSERR on error
750 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
751 const void *buffer, size_t length)
759 flags |= MSG_DONTWAIT;
763 flags |= MSG_NOSIGNAL;
766 ret = send (desc->fd, buffer, length, flags);
769 if (SOCKET_ERROR == ret)
770 SetErrnoFromWinsockError (WSAGetLastError ());
778 * Send data to a particular destination (always non-blocking).
779 * This function only works for UDP sockets.
782 * @param message data to send
783 * @param length size of the data
784 * @param dest_addr destination address
785 * @param dest_len length of @a address
786 * @return number of bytes sent, #GNUNET_SYSERR on error
789 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
790 const void *message, size_t length,
791 const struct sockaddr * dest_addr,
800 flags |= MSG_DONTWAIT;
803 flags |= MSG_NOSIGNAL;
805 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
807 if (SOCKET_ERROR == ret)
808 SetErrnoFromWinsockError (WSAGetLastError ());
818 * @param level protocol level of the option
819 * @param option_name option identifier
820 * @param option_value value to set
821 * @param option_len size of option_value
822 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
825 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
826 int option_name, const void *option_value,
827 socklen_t option_len)
831 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
833 if (SOCKET_ERROR == ret)
834 SetErrnoFromWinsockError (WSAGetLastError ());
836 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
841 * Create a new socket. Configure it for non-blocking IO and
842 * mark it as non-inheritable to child processes (set the
843 * close-on-exec flag).
845 * @param domain domain of the socket
846 * @param type socket type
847 * @param protocol network protocol
848 * @return new socket, NULL on error
850 struct GNUNET_NETWORK_Handle *
851 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
853 struct GNUNET_NETWORK_Handle *ret;
855 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
856 ret->fd = socket (domain, type, protocol);
863 initialize_network_handle (ret, domain, type))
870 * Shut down socket operations
872 * @param how type of shutdown
873 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
876 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
880 ret = shutdown (desc->fd, how);
883 SetErrnoFromWinsockError (WSAGetLastError ());
885 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
890 * Disable the "CORK" feature for communication with the given socket,
891 * forcing the OS to immediately flush the buffer on transmission
892 * instead of potentially buffering multiple messages. Essentially
893 * reduces the OS send buffers to zero.
896 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
899 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
908 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
910 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
913 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
915 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
921 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
922 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
925 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
926 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
928 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
938 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
943 GNUNET_CONTAINER_slist_clear (fds->handles);
949 * Add a socket to the FD set
952 * @param desc socket to add
955 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
956 const struct GNUNET_NETWORK_Handle *desc)
958 FD_SET (desc->fd, &fds->sds);
959 if (desc->fd + 1 > fds->nsds)
960 fds->nsds = desc->fd + 1;
965 * Check whether a socket is part of the fd set
969 * @return 0 if the FD is not set
972 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
973 const struct GNUNET_NETWORK_Handle *desc)
975 return FD_ISSET (desc->fd, &fds->sds);
980 * Add one fd set to another
982 * @param dst the fd set to add to
983 * @param src the fd set to add from
986 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
987 const struct GNUNET_NETWORK_FDSet *src)
992 for (nfds = src->nsds; nfds >= 0; nfds--)
993 if (FD_ISSET (nfds, &src->sds))
996 FD_SET (nfds, &dst->sds);
997 if (nfds + 1 > dst->nsds)
998 dst->nsds = nfds + 1;
1001 /* This is MinGW32-specific implementation that relies on the code that
1002 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
1003 * that fd being added is not already in the set.
1004 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
1007 for (i = 0; i < src->sds.fd_count; i++)
1008 FD_SET (src->sds.fd_array[i], &dst->sds);
1009 if (src->nsds > dst->nsds)
1010 dst->nsds = src->nsds;
1012 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
1018 * Copy one fd set to another
1020 * @param to destination
1021 * @param from source
1024 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
1025 const struct GNUNET_NETWORK_FDSet *from)
1027 FD_COPY (&from->sds, &to->sds);
1028 to->nsds = from->nsds;
1031 GNUNET_CONTAINER_slist_clear (to->handles);
1032 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
1038 * Return file descriptor for this network handle
1040 * @param desc wrapper to process
1041 * @return POSIX file descriptor
1044 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
1051 * Return sockaddr for this network handle
1053 * @param desc wrapper to process
1057 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1064 * Return sockaddr length for this network handle
1066 * @param desc wrapper to process
1067 * @return socklen_t for sockaddr
1070 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1072 return desc->addrlen;
1077 * Copy a native fd set
1079 * @param to destination
1080 * @param from native source set
1081 * @param nfds the biggest socket number in from + 1
1084 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1085 const fd_set * from, int nfds)
1087 FD_COPY (from, &to->sds);
1093 * Set a native fd in a set
1095 * @param to destination
1096 * @param nfd native FD to set
1099 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1101 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1102 FD_SET (nfd, &to->sds);
1103 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1108 * Test native fd in a set
1110 * @param to set to test, NULL for empty set
1111 * @param nfd native FD to test, or -1 for none
1112 * @return #GNUNET_YES if FD is set in the set
1115 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1118 if ((nfd == -1) || (to == NULL))
1120 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1125 * Add a file handle to the fd set
1127 * @param h the file handle to add
1130 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1131 const struct GNUNET_DISK_FileHandle *h)
1134 GNUNET_CONTAINER_slist_add (fds->handles,
1135 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1136 sizeof (struct GNUNET_DISK_FileHandle));
1141 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1142 FD_SET (fd, &fds->sds);
1143 if (fd + 1 > fds->nsds)
1151 * Check if a file handle is part of an fd set
1153 * @param h file handle
1154 * @return #GNUNET_YES if the file handle is part of the set
1157 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1158 const struct GNUNET_DISK_FileHandle *h)
1162 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1164 GNUNET_DISK_FileHandle));
1166 return FD_ISSET (h->fd, &fds->sds);
1172 * Checks if two fd sets overlap
1173 * @param fds1 first fd set
1174 * @param fds2 second fd set
1175 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1178 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1179 const struct GNUNET_NETWORK_FDSet *fds2)
1185 if (nfds > fds2->nsds)
1190 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1194 struct GNUNET_CONTAINER_SList_Iterator it;
1195 struct GNUNET_DISK_FileHandle *h;
1199 /*This code is somewhat hacky, we are not supposed to know what's
1200 * inside of fd_set; also the O(n^2) is really bad... */
1202 for (i = 0; i < fds1->sds.fd_count; i++)
1204 for (j = 0; j < fds2->sds.fd_count; j++)
1206 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1210 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1211 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1214 struct GNUNET_CONTAINER_SList_Iterator t;
1216 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1219 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1221 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1222 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1223 GNUNET_CONTAINER_slist_next (&t))
1225 struct GNUNET_DISK_FileHandle *fh;
1227 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1229 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1232 if (GNUNET_CONTAINER_slist_contains
1233 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1237 GNUNET_CONTAINER_slist_next (&it);
1247 * @return a new fd set
1249 struct GNUNET_NETWORK_FDSet *
1250 GNUNET_NETWORK_fdset_create ()
1252 struct GNUNET_NETWORK_FDSet *fds;
1254 fds = GNUNET_new (struct GNUNET_NETWORK_FDSet);
1256 fds->handles = GNUNET_CONTAINER_slist_create ();
1258 GNUNET_NETWORK_fdset_zero (fds);
1264 * Releases the associated memory of an fd set
1269 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1272 GNUNET_CONTAINER_slist_destroy (fds->handles);
1278 struct _select_params
1286 SOCKET wakeup_socket;
1291 _selector (LPVOID p)
1293 struct _select_params *sp = p;
1297 WaitForSingleObject (sp->standby, INFINITE);
1298 ResetEvent (sp->standby);
1299 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1300 if (FD_ISSET (sp->wakeup_socket, sp->r))
1302 FD_CLR (sp->wakeup_socket, sp->r);
1305 SetEvent (sp->wakeup);
1314 * Check if sockets or pipes meet certain conditions
1316 * @param rfds set of sockets or pipes to be checked for readability
1317 * @param wfds set of sockets or pipes to be checked for writability
1318 * @param efds set of sockets or pipes to be checked for exceptions
1319 * @param timeout relative value when to return
1320 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1323 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1324 struct GNUNET_NETWORK_FDSet *wfds,
1325 struct GNUNET_NETWORK_FDSet *efds,
1326 const struct GNUNET_TIME_Relative timeout)
1336 nfds = GNUNET_MAX (nfds, wfds->nsds);
1338 nfds = GNUNET_MAX (nfds, efds->nsds);
1340 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us))
1343 LOG (GNUNET_ERROR_TYPE_ERROR,
1344 _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1347 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1349 (timeout.rel_value_us -
1350 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1351 return select (nfds,
1352 (NULL != rfds) ? &rfds->sds : NULL,
1353 (NULL != wfds) ? &wfds->sds : NULL,
1354 (NULL != efds) ? &efds->sds : NULL,
1355 (timeout.rel_value_us ==
1356 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1365 * Check if sockets or pipes meet certain conditions, version for W32.
1367 * @param rfds set of sockets or pipes to be checked for readability
1368 * @param wfds set of sockets or pipes to be checked for writability
1369 * @param efds set of sockets or pipes to be checked for exceptions
1370 * @param timeout relative value when to return
1371 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1374 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1375 struct GNUNET_NETWORK_FDSet *wfds,
1376 struct GNUNET_NETWORK_FDSet *efds,
1377 const struct GNUNET_TIME_Relative timeout)
1382 int read_handles = 0;
1383 int write_handles = 0;
1387 uint64_t mcs_total = 0;
1388 DWORD ms_rounded = 0;
1392 static HANDLE hEventPipeWrite = 0;
1393 static HANDLE hEventReadReady = 0;
1395 static struct _select_params sp;
1396 static HANDLE select_thread = NULL;
1397 static HANDLE select_finished_event = NULL;
1398 static HANDLE select_standby_event = NULL;
1399 static SOCKET select_wakeup_socket = -1;
1400 static SOCKET select_send_socket = -1;
1401 static struct timeval select_timeout;
1404 int writePipePos = 0;
1406 HANDLE handle_array[FD_SETSIZE + 2];
1407 int returncode = -1;
1408 int returnedpos = 0;
1410 struct GNUNET_CONTAINER_SList *handles_read;
1411 struct GNUNET_CONTAINER_SList *handles_write;
1412 struct GNUNET_CONTAINER_SList *handles_except;
1426 /* TODO: Make this growable */
1427 struct GNUNET_DISK_FileHandle *readArray[50];
1433 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1436 struct GNUNET_CONTAINER_SList_Iterator t;
1438 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1439 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1440 GNUNET_CONTAINER_slist_next (&t))
1442 struct GNUNET_DISK_FileHandle *fh;
1444 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1446 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1454 nfds = GNUNET_MAX (nfds, wfds->nsds);
1455 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1459 nfds = GNUNET_MAX (nfds, efds->nsds);
1460 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1464 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1468 LOG (GNUNET_ERROR_TYPE_ERROR,
1469 _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1472 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1473 /* calculate how long we need to wait in microseconds */
1474 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1476 mcs_total = INFINITE;
1477 ms_rounded = INFINITE;
1481 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1482 ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1483 if (mcs_total > 0 && ms_rounded == 0)
1486 /* select() may be used as a portable way to sleep */
1487 if (!(rfds || wfds || efds))
1493 if (NULL == select_thread)
1495 SOCKET select_listening_socket = -1;
1496 struct sockaddr_in s_in;
1501 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1502 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1504 select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1506 select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1509 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1510 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1512 alen = sizeof (s_in);
1513 s_in.sin_family = AF_INET;
1515 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1516 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1517 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1518 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1519 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1520 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1522 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1523 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1525 res = listen (select_listening_socket, SOMAXCONN);
1526 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1528 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1529 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1531 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1533 closesocket (select_listening_socket);
1535 sp.wakeup = select_finished_event;
1536 sp.standby = select_standby_event;
1537 sp.wakeup_socket = select_wakeup_socket;
1539 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1543 handles_read = GNUNET_CONTAINER_slist_create ();
1544 handles_write = GNUNET_CONTAINER_slist_create ();
1545 handles_except = GNUNET_CONTAINER_slist_create ();
1556 FD_COPY (&rfds->sds, &aread);
1558 FD_COPY (&rfds->sds, &bread);
1563 FD_COPY (&wfds->sds, &awrite);
1565 FD_COPY (&wfds->sds, &bwrite);
1570 FD_COPY (&efds->sds, &aexcept);
1572 FD_COPY (&efds->sds, &bexcept);
1576 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1577 By profiling we detected that to be true in 90% of the cases.
1580 /* Do the select now */
1581 select_timeout.tv_sec = 0;
1582 select_timeout.tv_usec = 0;
1584 /* Copy all the writes to the except, so we can detect connect() errors */
1585 for (i = 0; i < awrite.fd_count; i++)
1586 FD_SET (awrite.fd_array[i], &aexcept);
1587 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1588 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1589 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1592 if (selectret == -1)
1594 /* Throw an error early on, while we still have the context. */
1595 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1596 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1600 /* Check aexcept, add its contents to awrite
1601 This is technically wrong (aexcept might have its own descriptors), we should
1602 have checked that descriptors were in awrite originally before re-adding them from
1603 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1604 for (i = 0; i < aexcept.fd_count; i++)
1605 FD_SET (aexcept.fd_array[i], &awrite);
1607 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1608 /* Sadly, it means code duplication :( */
1609 if ((selectret > 0) || (mcs_total == 0))
1612 if (rfds && read_handles)
1614 struct GNUNET_CONTAINER_SList_Iterator i;
1617 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1618 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1619 GNUNET_CONTAINER_slist_next (&i), c++)
1621 struct GNUNET_DISK_FileHandle *fh;
1623 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1624 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1630 DWORD waitstatus = 0;
1631 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1632 error = GetLastError ();
1633 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1634 c, fh->h, bret, waitstatus, error);
1637 /* TODO: either add more errors to this condition, or eliminate it
1638 * entirely (failed to peek -> pipe is in serious trouble, should
1639 * be selected as readable).
1641 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1644 else if (waitstatus <= 0)
1646 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1647 fh, sizeof (struct GNUNET_DISK_FileHandle));
1649 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1654 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1655 fh, sizeof (struct GNUNET_DISK_FileHandle));
1660 if (wfds && write_handles)
1662 LOG (GNUNET_ERROR_TYPE_DEBUG,
1663 "Adding the write ready event to the array as %d\n", nhandles);
1664 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1665 retcode += write_handles;
1667 if (efds && ex_handles)
1669 struct GNUNET_CONTAINER_SList_Iterator i;
1671 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1672 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1673 GNUNET_CONTAINER_slist_next (&i))
1675 struct GNUNET_DISK_FileHandle *fh;
1678 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1679 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1681 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1683 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1684 fh, sizeof (struct GNUNET_DISK_FileHandle));
1690 /* Add our select() result.*/
1692 retcode += selectret;
1696 GNUNET_NETWORK_fdset_zero (rfds);
1697 if (selectret != -1)
1698 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1699 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1703 GNUNET_NETWORK_fdset_zero (wfds);
1704 if (selectret != -1)
1705 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1706 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1710 GNUNET_NETWORK_fdset_zero (efds);
1711 if (selectret != -1)
1712 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1713 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1715 GNUNET_CONTAINER_slist_destroy (handles_read);
1716 GNUNET_CONTAINER_slist_destroy (handles_write);
1717 GNUNET_CONTAINER_slist_destroy (handles_except);
1719 if (selectret == -1)
1724 /* If we got this far, use slower implementation that is able to do a waiting select
1725 on both sockets and pipes simultaneously */
1727 /* Events for pipes */
1728 if (!hEventReadReady)
1729 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1730 if (!hEventPipeWrite)
1731 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1747 FD_COPY (&rfds->sds, &aread);
1749 FD_COPY (&rfds->sds, &bread);
1754 FD_COPY (&wfds->sds, &awrite);
1756 FD_COPY (&wfds->sds, &bwrite);
1761 FD_COPY (&efds->sds, &aexcept);
1763 FD_COPY (&efds->sds, &bexcept);
1766 /* We will first Add the PIPES to the events */
1768 if (rfds && read_handles)
1770 struct GNUNET_CONTAINER_SList_Iterator i;
1772 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1773 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1774 GNUNET_CONTAINER_slist_next (&i))
1776 struct GNUNET_DISK_FileHandle *fh;
1778 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1780 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1782 /* Read zero bytes to check the status of the pipe */
1783 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1785 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1787 DWORD error_code = GetLastError ();
1789 if (error_code == ERROR_IO_PENDING)
1791 LOG (GNUNET_ERROR_TYPE_DEBUG,
1792 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1794 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1795 readArray[readPipes++] = fh;
1799 LOG (GNUNET_ERROR_TYPE_DEBUG,
1800 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1801 handle_array[nhandles++] = hEventReadReady;
1802 readArray[readPipes++] = fh;
1807 LOG (GNUNET_ERROR_TYPE_DEBUG,
1808 "Adding the read ready event to the array as %d\n", nhandles);
1809 handle_array[nhandles++] = hEventReadReady;
1810 readArray[readPipes++] = fh;
1815 GNUNET_CONTAINER_slist_add (handles_read,
1816 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1817 fh, sizeof (struct GNUNET_DISK_FileHandle));
1821 if (wfds && write_handles)
1823 LOG (GNUNET_ERROR_TYPE_DEBUG,
1824 "Adding the write ready event to the array as %d\n", nhandles);
1825 handle_array[nhandles++] = hEventPipeWrite;
1826 writePipePos = nhandles;
1828 if (efds && ex_handles)
1830 struct GNUNET_CONTAINER_SList_Iterator i;
1832 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1833 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1834 GNUNET_CONTAINER_slist_next (&i))
1836 struct GNUNET_DISK_FileHandle *fh;
1839 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1841 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1843 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1845 GNUNET_CONTAINER_slist_add (handles_except,
1846 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1848 sizeof (struct GNUNET_DISK_FileHandle));
1858 LOG (GNUNET_ERROR_TYPE_DEBUG,
1859 "Adding the socket event to the array as %d\n",
1861 handle_array[nhandles++] = select_finished_event;
1862 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1866 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1867 select_timeout.tv_usec =(timeout.rel_value_us -
1868 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1869 sp.tv = &select_timeout;
1871 FD_SET (select_wakeup_socket, &aread);
1874 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1879 /* Failed connections cause sockets to be set in errorfds on W32,
1880 * but on POSIX it should set them in writefds.
1881 * First copy all awrite sockets to aexcept, later we'll
1882 * check aexcept and set its contents in awrite as well
1883 * Sockets are also set in errorfds when OOB data is available,
1884 * but we don't use OOB data.
1886 for (i = 0; i < awrite.fd_count; i++)
1887 FD_SET (awrite.fd_array[i], &aexcept);
1888 ResetEvent (select_finished_event);
1889 SetEvent (select_standby_event);
1892 handle_array[nhandles] = NULL;
1893 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
1894 nfds, nhandles, mcs_total);
1898 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
1899 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode);
1903 GNUNET_break (0); /* This branch shouldn't actually be executed...*/
1904 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1905 returncode = WAIT_TIMEOUT;
1909 /* Shouldn't come this far. If it does - investigate. */
1915 /* Don't wake up select-thread when delay is 0, it should return immediately
1916 * and wake up by itself.
1919 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1920 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1921 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1926 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1929 /* Check aexcept, add its contents to awrite */
1930 for (i = 0; i < aexcept.fd_count; i++)
1931 FD_SET (aexcept.fd_array[i], &awrite);
1934 returnedpos = returncode - WAIT_OBJECT_0;
1935 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1937 if (nhandles && (returnedpos < nhandles))
1942 retcode += sp.status;
1944 if ((writePipePos != -1) && (returnedpos < writePipePos))
1946 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1947 retcode += write_handles;
1948 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1950 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1951 /* We have some pipes ready for read. */
1952 if (returnedpos < readPipes)
1954 for (i = 0; i < readPipes; i++)
1962 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1963 error = GetLastError ();
1964 LOG (GNUNET_ERROR_TYPE_DEBUG,
1965 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1966 i, readArray[i]->h, bret, waitstatus, error);
1969 /* TODO: either add more errors to this condition, or eliminate it
1970 * entirely (failed to peek -> pipe is in serious trouble, should
1971 * be selected as readable).
1973 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1976 else if (waitstatus <= 0)
1978 GNUNET_CONTAINER_slist_add (handles_read,
1979 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1981 sizeof (struct GNUNET_DISK_FileHandle));
1983 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1984 readArray[i], readArray[i]->h);
1988 if (!nhandles || (returnedpos >= nhandles))
1989 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1992 struct GNUNET_CONTAINER_SList_Iterator t;
1994 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1995 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1996 GNUNET_CONTAINER_slist_next (&t))
1998 struct GNUNET_DISK_FileHandle *fh;
2000 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
2002 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
2007 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
2008 GNUNET_NETWORK_fdset_zero (rfds);
2009 if (retcode != -1 && nhandles && (returnedpos < nhandles))
2010 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
2011 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
2015 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
2016 GNUNET_NETWORK_fdset_zero (wfds);
2017 if (retcode != -1 && nhandles && (returnedpos < nhandles))
2018 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
2019 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
2023 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
2024 GNUNET_NETWORK_fdset_zero (efds);
2025 if (retcode != -1 && nhandles && (returnedpos < nhandles))
2026 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
2027 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
2029 GNUNET_CONTAINER_slist_destroy (handles_read);
2030 GNUNET_CONTAINER_slist_destroy (handles_write);
2031 GNUNET_CONTAINER_slist_destroy (handles_except);
2035 struct GNUNET_CONTAINER_SList_Iterator t;
2037 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
2038 for (i = 0; i < rfds->sds.fd_count; i++)
2040 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
2042 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
2043 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
2044 GNUNET_CONTAINER_slist_next (&t))
2046 struct GNUNET_DISK_FileHandle *fh;
2048 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
2050 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
2055 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
2056 for (i = 0; i < wfds->sds.fd_count; i++)
2058 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
2063 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
2064 for (i = 0; i < efds->sds.fd_count; i++)
2066 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
2069 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
2071 if (nhandles && (returnedpos < nhandles))
2080 /* end of network.c */