2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file util/network.c
23 * @brief basic, low-level networking interface
25 * @author Christian Grothoff
29 #include "gnunet_util_lib.h"
31 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
32 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
33 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
35 #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
38 #ifndef INVALID_SOCKET
39 #define INVALID_SOCKET -1
43 struct GNUNET_NETWORK_Handle
52 * Address family / domain.
62 * Number of bytes in addr.
67 * Address we were bound to, or NULL.
69 struct sockaddr *addr;
75 * Test if the given protocol family is supported by this system.
77 * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
78 * @return #GNUNET_OK if the PF is supported
81 GNUNET_NETWORK_test_pf (int pf)
85 s = socket (pf, SOCK_STREAM, 0);
88 if (EAFNOSUPPORT == errno)
90 fprintf (stderr, "Failed to create test socket: %s\n", STRERROR (errno));
103 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
104 * shorten it to an acceptable length while keeping it unique
105 * and making sure it remains a valid filename (if possible).
107 * @param unixpath long path, will be freed (or same pointer returned
108 * with moved 0-termination).
109 * @return shortened unixpath, NULL on error
112 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
114 struct sockaddr_un dummy;
117 struct GNUNET_HashCode sh;
118 struct GNUNET_CRYPTO_HashAsciiEncoded ae;
121 upm = sizeof (dummy.sun_path);
122 slen = strlen (unixpath);
124 return unixpath; /* no shortening required */
125 GNUNET_CRYPTO_hash (unixpath, slen, &sh);
127 strlen (unixpath) >= upm)
129 if (NULL == (end = strrchr (unixpath, '/')))
131 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
132 _("Unable to shorten unix path `%s' while keeping name unique\n"),
134 GNUNET_free (unixpath);
139 GNUNET_CRYPTO_hash_to_enc (&sh, &ae);
140 strncat (unixpath, (char*) ae.encoding, 16);
146 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
151 * Set if a socket should use blocking or non-blocking IO.
154 * @param doBlock blocking mode
155 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
158 GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
165 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
168 SetErrnoFromWinsockError (WSAGetLastError ());
169 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
170 return GNUNET_SYSERR;
176 int flags = fcntl (fd->fd, F_GETFL);
181 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
182 return GNUNET_SYSERR;
185 flags &= ~O_NONBLOCK;
189 if (0 != fcntl (fd->fd, F_SETFL, flags))
192 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
193 return GNUNET_SYSERR;
201 * Make a socket non-inheritable to child processes
203 * @param h the socket to make non-inheritable
204 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
205 * @warning Not implemented on Windows
208 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
212 i = fcntl (h->fd, F_GETFD);
214 return GNUNET_SYSERR;
215 if (i == (i | FD_CLOEXEC))
218 if (fcntl (h->fd, F_SETFD, i) < 0)
219 return GNUNET_SYSERR;
223 b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
226 SetErrnoFromWinsockError (WSAGetLastError ());
227 return GNUNET_SYSERR;
236 * The MSG_NOSIGNAL equivalent on Mac OS X
238 * @param h the socket to make non-delaying
241 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
246 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE,
247 (const void *) &abs_value,
249 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
255 * Disable delays when sending data via the socket.
256 * (GNUnet makes sure that messages are as big as
259 * @param h the socket to make non-delaying
262 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
267 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
268 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
270 const char *abs_value = "1";
273 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY,
274 (const void *) abs_value,
276 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
282 * Perform proper canonical initialization for a network handle.
283 * Set it to non-blocking, make it non-inheritable to child
284 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
285 * stream socket) and check that it is smaller than FD_SETSIZE.
287 * @param h socket to initialize
288 * @param af address family of the socket
289 * @param type socket type
290 * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
291 * failed and the handle was destroyed
294 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
299 if (h->fd == INVALID_SOCKET)
302 SetErrnoFromWinsockError (WSAGetLastError ());
305 return GNUNET_SYSERR;
308 if (h->fd >= FD_SETSIZE)
310 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
312 return GNUNET_SYSERR;
315 if (GNUNET_OK != socket_set_inheritable (h))
316 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
317 "socket_set_inheritable");
319 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
322 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
323 return GNUNET_SYSERR;
326 socket_set_nosigpipe (h);
328 if ( (type == SOCK_STREAM)
333 socket_set_nodelay (h);
339 * accept a new connection on a socket
341 * @param desc bound socket
342 * @param address address of the connecting peer, may be NULL
343 * @param address_len length of @a address
344 * @return client socket
346 struct GNUNET_NETWORK_Handle *
347 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
348 struct sockaddr *address,
349 socklen_t *address_len)
351 struct GNUNET_NETWORK_Handle *ret;
353 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
356 struct sockaddr name;
357 socklen_t namelen = sizeof (name);
358 int gsn = getsockname (desc->fd, &name, &namelen);
361 LOG (GNUNET_ERROR_TYPE_DEBUG,
362 "Accepting connection on `%s'\n",
363 GNUNET_a2s (&name, namelen));
366 ret->fd = accept (desc->fd, address, address_len);
372 if (GNUNET_OK != initialize_network_handle (ret,
373 (NULL != address) ? address->sa_family : desc->af,
381 * Bind a socket to a particular address.
383 * @param desc socket to bind
384 * @param address address to be bound
385 * @param address_len length of @a address
386 * @param flags flags affecting bind behaviour
387 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
390 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
391 const struct sockaddr *address,
392 socklen_t address_len,
402 if (desc->af == AF_INET6)
403 if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY,
406 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
414 /* This is required here for TCP sockets, but only on UNIX */
415 if ((SOCK_STREAM == desc->type)
416 && (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))))
417 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
422 if (address->sa_family == AF_UNIX && (flags & GNUNET_BIND_EXCLUSIVE) == 0)
424 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
426 (void) unlink (un->sun_path);
430 ret = bind (desc->fd, address, address_len);
432 if (SOCKET_ERROR == ret)
433 SetErrnoFromWinsockError (WSAGetLastError ());
436 return GNUNET_SYSERR;
439 desc->addr = GNUNET_malloc (address_len);
440 memcpy (desc->addr, address, address_len);
441 desc->addrlen = address_len;
452 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
455 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
463 ret = closesocket (desc->fd);
464 error = WSAGetLastError ();
465 SetErrnoFromWinsockError (error);
466 LOG (GNUNET_ERROR_TYPE_DEBUG,
467 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
470 ret = close (desc->fd);
474 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
476 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
478 if (0 != unlink (un->sun_path))
479 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
483 GNUNET_NETWORK_socket_free_memory_only_ (desc);
484 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
489 * Only free memory of a socket, keep the file descriptor untouched.
494 GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc)
496 GNUNET_free_non_null (desc->addr);
502 * Box a native socket (and check that it is a socket).
504 * @param fd socket to box
505 * @return NULL on error (including not supported on target platform)
507 struct GNUNET_NETWORK_Handle *
508 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
510 struct GNUNET_NETWORK_Handle *ret;
514 /* FIXME: Find a better call to check that FD is valid */
515 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
516 return NULL; /* invalid FD */
517 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
522 if (fcntl (fd, F_GETFD) < 0)
523 return NULL; /* invalid FD */
524 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
533 * Connect a socket to some remote address.
536 * @param address peer address
537 * @param address_len length of @a address
538 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
541 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
542 const struct sockaddr *address,
543 socklen_t address_len)
547 ret = connect (desc->fd, address, address_len);
550 if (SOCKET_ERROR == ret)
552 SetErrnoFromWinsockError (WSAGetLastError ());
553 if (errno == EWOULDBLOCK)
557 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
565 * @param level protocol level of the option
566 * @param optname identifier of the option
567 * @param optval options
568 * @param optlen length of @a optval
569 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
572 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
573 int level, int optname, void *optval,
578 ret = getsockopt (desc->fd, level, optname, optval, optlen);
581 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
582 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
584 else if (SOCKET_ERROR == ret)
585 SetErrnoFromWinsockError (WSAGetLastError ());
587 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
595 * @param backlog length of the listen queue
596 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
599 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
604 ret = listen (desc->fd, backlog);
607 if (SOCKET_ERROR == ret)
608 SetErrnoFromWinsockError (WSAGetLastError ());
611 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
616 * How much data is available to be read on this descriptor?
619 * @returns #GNUNET_NO if no data is available, or on error!
622 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
627 /* How much is there to be read? */
631 error = ioctl (desc->fd, FIONREAD, &pending);
633 return (ssize_t) pending;
638 error = ioctlsocket (desc->fd, FIONREAD, &pending);
639 if (error != SOCKET_ERROR)
640 return (ssize_t) pending;
647 * Read data from a socket (always non-blocking).
650 * @param buffer buffer
651 * @param length length of @a buffer
652 * @param src_addr either the source to recv from, or all zeroes
653 * to be filled in by recvfrom
654 * @param addrlen length of the @a src_addr
657 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
658 void *buffer, size_t length,
659 struct sockaddr *src_addr, socklen_t *addrlen)
667 flags |= MSG_DONTWAIT;
670 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
672 if (SOCKET_ERROR == ret)
673 SetErrnoFromWinsockError (WSAGetLastError ());
680 * Read data from a connected socket (always non-blocking).
683 * @param buffer buffer
684 * @param length length of @a buffer
687 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
688 void *buffer, size_t length)
696 flags |= MSG_DONTWAIT;
698 ret = recv (desc->fd, buffer, length, flags);
700 if (SOCKET_ERROR == ret)
701 SetErrnoFromWinsockError (WSAGetLastError ());
708 * Send data (always non-blocking).
711 * @param buffer data to send
712 * @param length size of the @a buffer
713 * @return number of bytes sent, #GNUNET_SYSERR on error
716 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
717 const void *buffer, size_t length)
725 flags |= MSG_DONTWAIT;
729 flags |= MSG_NOSIGNAL;
732 ret = send (desc->fd, buffer, length, flags);
735 if (SOCKET_ERROR == ret)
736 SetErrnoFromWinsockError (WSAGetLastError ());
744 * Send data to a particular destination (always non-blocking).
745 * This function only works for UDP sockets.
748 * @param message data to send
749 * @param length size of the data
750 * @param dest_addr destination address
751 * @param dest_len length of @a address
752 * @return number of bytes sent, #GNUNET_SYSERR on error
755 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
756 const void *message, size_t length,
757 const struct sockaddr * dest_addr,
766 flags |= MSG_DONTWAIT;
769 flags |= MSG_NOSIGNAL;
771 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
773 if (SOCKET_ERROR == ret)
774 SetErrnoFromWinsockError (WSAGetLastError ());
784 * @param level protocol level of the option
785 * @param option_name option identifier
786 * @param option_value value to set
787 * @param option_len size of option_value
788 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
791 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
792 int option_name, const void *option_value,
793 socklen_t option_len)
797 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
799 if (SOCKET_ERROR == ret)
800 SetErrnoFromWinsockError (WSAGetLastError ());
802 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
807 * Create a new socket. Configure it for non-blocking IO and
808 * mark it as non-inheritable to child processes (set the
809 * close-on-exec flag).
811 * @param domain domain of the socket
812 * @param type socket type
813 * @param protocol network protocol
814 * @return new socket, NULL on error
816 struct GNUNET_NETWORK_Handle *
817 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
819 struct GNUNET_NETWORK_Handle *ret;
821 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
822 ret->fd = socket (domain, type, protocol);
829 initialize_network_handle (ret, domain, type))
836 * Shut down socket operations
838 * @param how type of shutdown
839 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
842 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
846 ret = shutdown (desc->fd, how);
849 SetErrnoFromWinsockError (WSAGetLastError ());
851 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
856 * Disable the "CORK" feature for communication with the given socket,
857 * forcing the OS to immediately flush the buffer on transmission
858 * instead of potentially buffering multiple messages. Essentially
859 * reduces the OS send buffers to zero.
862 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
865 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
874 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
876 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
879 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
881 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
887 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
888 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
891 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
892 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
894 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
904 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
909 GNUNET_CONTAINER_slist_clear (fds->handles);
915 * Add a socket to the FD set
918 * @param desc socket to add
921 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
922 const struct GNUNET_NETWORK_Handle *desc)
924 FD_SET (desc->fd, &fds->sds);
925 if (desc->fd + 1 > fds->nsds)
926 fds->nsds = desc->fd + 1;
931 * Check whether a socket is part of the fd set
935 * @return 0 if the FD is not set
938 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
939 const struct GNUNET_NETWORK_Handle *desc)
941 return FD_ISSET (desc->fd, &fds->sds);
946 * Add one fd set to another
948 * @param dst the fd set to add to
949 * @param src the fd set to add from
952 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
953 const struct GNUNET_NETWORK_FDSet *src)
958 for (nfds = src->nsds; nfds > 0; nfds--)
959 if (FD_ISSET (nfds, &src->sds))
962 FD_SET (nfds, &dst->sds);
963 if (nfds + 1 > dst->nsds)
964 dst->nsds = nfds + 1;
967 /* This is MinGW32-specific implementation that relies on the code that
968 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
969 * that fd being added is not already in the set.
970 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
973 for (i = 0; i < src->sds.fd_count; i++)
974 FD_SET (src->sds.fd_array[i], &dst->sds);
975 if (src->nsds > dst->nsds)
976 dst->nsds = src->nsds;
978 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
984 * Copy one fd set to another
986 * @param to destination
990 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
991 const struct GNUNET_NETWORK_FDSet *from)
993 FD_COPY (&from->sds, &to->sds);
994 to->nsds = from->nsds;
997 GNUNET_CONTAINER_slist_clear (to->handles);
998 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
1004 * Return file descriptor for this network handle
1006 * @param desc wrapper to process
1007 * @return POSIX file descriptor
1010 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
1017 * Return sockaddr for this network handle
1019 * @param desc wrapper to process
1023 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1030 * Return sockaddr length for this network handle
1032 * @param desc wrapper to process
1033 * @return socklen_t for sockaddr
1036 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1038 return desc->addrlen;
1043 * Copy a native fd set
1045 * @param to destination
1046 * @param from native source set
1047 * @param nfds the biggest socket number in from + 1
1050 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1051 const fd_set * from, int nfds)
1053 FD_COPY (from, &to->sds);
1059 * Set a native fd in a set
1061 * @param to destination
1062 * @param nfd native FD to set
1065 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1067 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1068 FD_SET (nfd, &to->sds);
1069 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1074 * Test native fd in a set
1076 * @param to set to test, NULL for empty set
1077 * @param nfd native FD to test, or -1 for none
1078 * @return #GNUNET_YES if FD is set in the set
1081 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1084 if ((nfd == -1) || (to == NULL))
1086 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1091 * Add a file handle to the fd set
1093 * @param h the file handle to add
1096 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1097 const struct GNUNET_DISK_FileHandle *h)
1100 GNUNET_CONTAINER_slist_add (fds->handles,
1101 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1102 sizeof (struct GNUNET_DISK_FileHandle));
1107 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1108 FD_SET (fd, &fds->sds);
1109 if (fd + 1 > fds->nsds)
1117 * Check if a file handle is part of an fd set
1119 * @param h file handle
1120 * @return #GNUNET_YES if the file handle is part of the set
1123 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1124 const struct GNUNET_DISK_FileHandle *h)
1128 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1130 GNUNET_DISK_FileHandle));
1132 return FD_ISSET (h->fd, &fds->sds);
1138 * Checks if two fd sets overlap
1139 * @param fds1 first fd set
1140 * @param fds2 second fd set
1141 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1144 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1145 const struct GNUNET_NETWORK_FDSet *fds2)
1151 if (nfds > fds2->nsds)
1156 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1160 struct GNUNET_CONTAINER_SList_Iterator it;
1161 struct GNUNET_DISK_FileHandle *h;
1165 /*This code is somewhat hacky, we are not supposed to know what's
1166 * inside of fd_set; also the O(n^2) is really bad... */
1168 for (i = 0; i < fds1->sds.fd_count; i++)
1170 for (j = 0; j < fds2->sds.fd_count; j++)
1172 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1176 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1177 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1180 struct GNUNET_CONTAINER_SList_Iterator t;
1182 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1185 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1187 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1188 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1189 GNUNET_CONTAINER_slist_next (&t))
1191 struct GNUNET_DISK_FileHandle *fh;
1193 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1195 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1198 if (GNUNET_CONTAINER_slist_contains
1199 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1203 GNUNET_CONTAINER_slist_next (&it);
1213 * @return a new fd set
1215 struct GNUNET_NETWORK_FDSet *
1216 GNUNET_NETWORK_fdset_create ()
1218 struct GNUNET_NETWORK_FDSet *fds;
1220 fds = GNUNET_new (struct GNUNET_NETWORK_FDSet);
1222 fds->handles = GNUNET_CONTAINER_slist_create ();
1224 GNUNET_NETWORK_fdset_zero (fds);
1230 * Releases the associated memory of an fd set
1235 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1238 GNUNET_CONTAINER_slist_destroy (fds->handles);
1244 struct _select_params
1252 SOCKET wakeup_socket;
1257 _selector (LPVOID p)
1259 struct _select_params *sp = p;
1263 WaitForSingleObject (sp->standby, INFINITE);
1264 ResetEvent (sp->standby);
1265 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1266 if (FD_ISSET (sp->wakeup_socket, sp->r))
1268 FD_CLR (sp->wakeup_socket, sp->r);
1271 SetEvent (sp->wakeup);
1279 * Check if sockets or pipes meet certain conditions
1280 * @param rfds set of sockets or pipes to be checked for readability
1281 * @param wfds set of sockets or pipes to be checked for writability
1282 * @param efds set of sockets or pipes to be checked for exceptions
1283 * @param timeout relative value when to return
1284 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1287 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1288 struct GNUNET_NETWORK_FDSet *wfds,
1289 struct GNUNET_NETWORK_FDSet *efds,
1290 const struct GNUNET_TIME_Relative timeout)
1296 int read_handles = 0;
1297 int write_handles = 0;
1301 uint64_t mcs_total = 0;
1302 DWORD ms_rounded = 0;
1306 static HANDLE hEventPipeWrite = 0;
1307 static HANDLE hEventReadReady = 0;
1309 static struct _select_params sp;
1310 static HANDLE select_thread = NULL;
1311 static HANDLE select_finished_event = NULL;
1312 static HANDLE select_standby_event = NULL;
1313 static SOCKET select_wakeup_socket = -1;
1314 static SOCKET select_send_socket = -1;
1315 static struct timeval select_timeout;
1318 int writePipePos = 0;
1320 HANDLE handle_array[FD_SETSIZE + 2];
1321 int returncode = -1;
1322 int returnedpos = 0;
1324 struct GNUNET_CONTAINER_SList *handles_read;
1325 struct GNUNET_CONTAINER_SList *handles_write;
1326 struct GNUNET_CONTAINER_SList *handles_except;
1340 /* TODO: Make this growable */
1341 struct GNUNET_DISK_FileHandle *readArray[50];
1349 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1352 struct GNUNET_CONTAINER_SList_Iterator t;
1354 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1355 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1356 GNUNET_CONTAINER_slist_next (&t))
1358 struct GNUNET_DISK_FileHandle *fh;
1360 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1362 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1371 nfds = GNUNET_MAX (nfds, wfds->nsds);
1373 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1378 nfds = GNUNET_MAX (nfds, efds->nsds);
1380 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1385 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1392 LOG (GNUNET_ERROR_TYPE_ERROR,
1394 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1398 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1400 (timeout.rel_value_us -
1401 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1402 return select (nfds,
1403 (NULL != rfds) ? &rfds->sds : NULL,
1404 (NULL != wfds) ? &wfds->sds : NULL,
1405 (NULL != efds) ? &efds->sds : NULL,
1406 (timeout.rel_value_us ==
1407 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1410 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1411 /* calculate how long we need to wait in microseconds */
1412 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1414 mcs_total = INFINITE;
1415 ms_rounded = INFINITE;
1419 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1420 ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1421 if (mcs_total > 0 && ms_rounded == 0)
1424 /* select() may be used as a portable way to sleep */
1425 if (!(rfds || wfds || efds))
1431 if (NULL == select_thread)
1433 SOCKET select_listening_socket = -1;
1434 struct sockaddr_in s_in;
1439 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1440 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1442 select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1444 select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1447 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1448 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1450 alen = sizeof (s_in);
1451 s_in.sin_family = AF_INET;
1453 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1454 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1455 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1456 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1457 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1458 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1460 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1461 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1463 res = listen (select_listening_socket, SOMAXCONN);
1464 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1466 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1467 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1469 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1471 closesocket (select_listening_socket);
1473 sp.wakeup = select_finished_event;
1474 sp.standby = select_standby_event;
1475 sp.wakeup_socket = select_wakeup_socket;
1477 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1481 handles_read = GNUNET_CONTAINER_slist_create ();
1482 handles_write = GNUNET_CONTAINER_slist_create ();
1483 handles_except = GNUNET_CONTAINER_slist_create ();
1494 FD_COPY (&rfds->sds, &aread);
1496 FD_COPY (&rfds->sds, &bread);
1501 FD_COPY (&wfds->sds, &awrite);
1503 FD_COPY (&wfds->sds, &bwrite);
1508 FD_COPY (&efds->sds, &aexcept);
1510 FD_COPY (&efds->sds, &bexcept);
1514 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1515 By profiling we detected that to be true in 90% of the cases.
1518 /* Do the select now */
1519 select_timeout.tv_sec = 0;
1520 select_timeout.tv_usec = 0;
1522 /* Copy all the writes to the except, so we can detect connect() errors */
1523 for (i = 0; i < awrite.fd_count; i++)
1524 FD_SET (awrite.fd_array[i], &aexcept);
1525 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1526 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1527 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1530 if (selectret == -1)
1532 /* Throw an error early on, while we still have the context. */
1533 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1534 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1538 /* Check aexcept, add its contents to awrite
1539 This is technically wrong (aexcept might have its own descriptors), we should
1540 have checked that descriptors were in awrite originally before re-adding them from
1541 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1542 for (i = 0; i < aexcept.fd_count; i++)
1543 FD_SET (aexcept.fd_array[i], &awrite);
1545 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1546 /* Sadly, it means code duplication :( */
1547 if ((selectret > 0) || (mcs_total == 0))
1550 if (rfds && read_handles)
1552 struct GNUNET_CONTAINER_SList_Iterator i;
1555 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1556 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1557 GNUNET_CONTAINER_slist_next (&i), c++)
1559 struct GNUNET_DISK_FileHandle *fh;
1561 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1562 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1568 DWORD waitstatus = 0;
1569 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1570 error = GetLastError ();
1571 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1572 c, fh->h, bret, waitstatus, error);
1575 /* TODO: either add more errors to this condition, or eliminate it
1576 * entirely (failed to peek -> pipe is in serious trouble, should
1577 * be selected as readable).
1579 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1582 else if (waitstatus <= 0)
1584 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1585 fh, sizeof (struct GNUNET_DISK_FileHandle));
1587 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1592 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1593 fh, sizeof (struct GNUNET_DISK_FileHandle));
1598 if (wfds && write_handles)
1600 LOG (GNUNET_ERROR_TYPE_DEBUG,
1601 "Adding the write ready event to the array as %d\n", nhandles);
1602 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1603 retcode += write_handles;
1605 if (efds && ex_handles)
1607 struct GNUNET_CONTAINER_SList_Iterator i;
1609 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1610 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1611 GNUNET_CONTAINER_slist_next (&i))
1613 struct GNUNET_DISK_FileHandle *fh;
1616 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1617 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1619 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1621 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1622 fh, sizeof (struct GNUNET_DISK_FileHandle));
1628 /* Add our select() result.*/
1630 retcode += selectret;
1634 GNUNET_NETWORK_fdset_zero (rfds);
1635 if (selectret != -1)
1636 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1637 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1641 GNUNET_NETWORK_fdset_zero (wfds);
1642 if (selectret != -1)
1643 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1644 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1648 GNUNET_NETWORK_fdset_zero (efds);
1649 if (selectret != -1)
1650 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1651 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1653 GNUNET_CONTAINER_slist_destroy (handles_read);
1654 GNUNET_CONTAINER_slist_destroy (handles_write);
1655 GNUNET_CONTAINER_slist_destroy (handles_except);
1657 if (selectret == -1)
1662 /* If we got this far, use slower implementation that is able to do a waiting select
1663 on both sockets and pipes simultaneously */
1665 /* Events for pipes */
1666 if (!hEventReadReady)
1667 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1668 if (!hEventPipeWrite)
1669 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1685 FD_COPY (&rfds->sds, &aread);
1687 FD_COPY (&rfds->sds, &bread);
1692 FD_COPY (&wfds->sds, &awrite);
1694 FD_COPY (&wfds->sds, &bwrite);
1699 FD_COPY (&efds->sds, &aexcept);
1701 FD_COPY (&efds->sds, &bexcept);
1704 /* We will first Add the PIPES to the events */
1706 if (rfds && read_handles)
1708 struct GNUNET_CONTAINER_SList_Iterator i;
1710 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1711 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1712 GNUNET_CONTAINER_slist_next (&i))
1714 struct GNUNET_DISK_FileHandle *fh;
1716 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1718 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1720 /* Read zero bytes to check the status of the pipe */
1721 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1723 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1725 DWORD error_code = GetLastError ();
1727 if (error_code == ERROR_IO_PENDING)
1729 LOG (GNUNET_ERROR_TYPE_DEBUG,
1730 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1732 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1733 readArray[readPipes++] = fh;
1737 LOG (GNUNET_ERROR_TYPE_DEBUG,
1738 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1739 handle_array[nhandles++] = hEventReadReady;
1740 readArray[readPipes++] = fh;
1745 LOG (GNUNET_ERROR_TYPE_DEBUG,
1746 "Adding the read ready event to the array as %d\n", nhandles);
1747 handle_array[nhandles++] = hEventReadReady;
1748 readArray[readPipes++] = fh;
1753 GNUNET_CONTAINER_slist_add (handles_read,
1754 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1755 fh, sizeof (struct GNUNET_DISK_FileHandle));
1759 if (wfds && write_handles)
1761 LOG (GNUNET_ERROR_TYPE_DEBUG,
1762 "Adding the write ready event to the array as %d\n", nhandles);
1763 handle_array[nhandles++] = hEventPipeWrite;
1764 writePipePos = nhandles;
1766 if (efds && ex_handles)
1768 struct GNUNET_CONTAINER_SList_Iterator i;
1770 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1771 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1772 GNUNET_CONTAINER_slist_next (&i))
1774 struct GNUNET_DISK_FileHandle *fh;
1777 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1779 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1781 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1783 GNUNET_CONTAINER_slist_add (handles_except,
1784 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1786 sizeof (struct GNUNET_DISK_FileHandle));
1796 LOG (GNUNET_ERROR_TYPE_DEBUG,
1797 "Adding the socket event to the array as %d\n",
1799 handle_array[nhandles++] = select_finished_event;
1800 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1804 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1805 select_timeout.tv_usec =(timeout.rel_value_us -
1806 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1807 sp.tv = &select_timeout;
1809 FD_SET (select_wakeup_socket, &aread);
1812 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1817 /* Failed connections cause sockets to be set in errorfds on W32,
1818 * but on POSIX it should set them in writefds.
1819 * First copy all awrite sockets to aexcept, later we'll
1820 * check aexcept and set its contents in awrite as well
1821 * Sockets are also set in errorfds when OOB data is available,
1822 * but we don't use OOB data.
1824 for (i = 0; i < awrite.fd_count; i++)
1825 FD_SET (awrite.fd_array[i], &aexcept);
1826 ResetEvent (select_finished_event);
1827 SetEvent (select_standby_event);
1830 handle_array[nhandles] = NULL;
1831 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
1832 nfds, nhandles, mcs_total);
1836 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
1837 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode);
1841 GNUNET_break (0); /* This branch shouldn't actually be executed...*/
1842 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1843 returncode = WAIT_TIMEOUT;
1847 /* Shouldn't come this far. If it does - investigate. */
1853 /* Don't wake up select-thread when delay is 0, it should return immediately
1854 * and wake up by itself.
1857 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1858 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1859 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1864 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1867 /* Check aexcept, add its contents to awrite */
1868 for (i = 0; i < aexcept.fd_count; i++)
1869 FD_SET (aexcept.fd_array[i], &awrite);
1872 returnedpos = returncode - WAIT_OBJECT_0;
1873 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1875 if (nhandles && (returnedpos < nhandles))
1880 retcode += sp.status;
1882 if ((writePipePos != -1) && (returnedpos < writePipePos))
1884 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1885 retcode += write_handles;
1886 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1888 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1889 /* We have some pipes ready for read. */
1890 if (returnedpos < readPipes)
1892 for (i = 0; i < readPipes; i++)
1900 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1901 error = GetLastError ();
1902 LOG (GNUNET_ERROR_TYPE_DEBUG,
1903 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1904 i, readArray[i]->h, bret, waitstatus, error);
1907 /* TODO: either add more errors to this condition, or eliminate it
1908 * entirely (failed to peek -> pipe is in serious trouble, should
1909 * be selected as readable).
1911 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1914 else if (waitstatus <= 0)
1916 GNUNET_CONTAINER_slist_add (handles_read,
1917 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1919 sizeof (struct GNUNET_DISK_FileHandle));
1921 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1922 readArray[i], readArray[i]->h);
1926 if (!nhandles || (returnedpos >= nhandles))
1927 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1930 struct GNUNET_CONTAINER_SList_Iterator t;
1932 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1933 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1934 GNUNET_CONTAINER_slist_next (&t))
1936 struct GNUNET_DISK_FileHandle *fh;
1938 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1940 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1945 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1946 GNUNET_NETWORK_fdset_zero (rfds);
1947 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1948 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1949 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1953 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1954 GNUNET_NETWORK_fdset_zero (wfds);
1955 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1956 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1957 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1961 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1962 GNUNET_NETWORK_fdset_zero (efds);
1963 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1964 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1965 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1967 GNUNET_CONTAINER_slist_destroy (handles_read);
1968 GNUNET_CONTAINER_slist_destroy (handles_write);
1969 GNUNET_CONTAINER_slist_destroy (handles_except);
1973 struct GNUNET_CONTAINER_SList_Iterator t;
1975 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1976 for (i = 0; i < rfds->sds.fd_count; i++)
1978 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1980 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1981 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1982 GNUNET_CONTAINER_slist_next (&t))
1984 struct GNUNET_DISK_FileHandle *fh;
1986 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1988 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1993 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1994 for (i = 0; i < wfds->sds.fd_count; i++)
1996 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
2001 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
2002 for (i = 0; i < efds->sds.fd_count; i++)
2004 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
2007 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
2009 if (nhandles && (returnedpos < nhandles))
2016 /* end of network.c */