2 This file is part of GNUnet.
3 (C) 2009-2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file util/network.c
23 * @brief basic, low-level networking interface
25 * @author Christian Grothoff
28 #include "gnunet_util_lib.h"
31 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
32 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
33 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
35 #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
38 #ifndef INVALID_SOCKET
39 #define INVALID_SOCKET -1
43 struct GNUNET_NETWORK_Handle
52 * Address family / domain.
62 * Number of bytes in addr.
67 * Address we were bound to, or NULL.
69 struct sockaddr *addr;
75 * Test if the given protocol family is supported by this system.
77 * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
78 * @return #GNUNET_OK if the PF is supported
81 GNUNET_NETWORK_test_pf (int pf)
85 s = socket (pf, SOCK_STREAM, 0);
88 if (EAFNOSUPPORT == errno)
90 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
91 "Failed to create test socket: %s\n",
105 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
106 * shorten it to an acceptable length while keeping it unique
107 * and making sure it remains a valid filename (if possible).
109 * @param unixpath long path, will be freed (or same pointer returned
110 * with moved 0-termination).
111 * @return shortened unixpath, NULL on error
114 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
116 struct sockaddr_un dummy;
119 struct GNUNET_HashCode sh;
120 struct GNUNET_CRYPTO_HashAsciiEncoded ae;
123 upm = sizeof (dummy.sun_path);
124 slen = strlen (unixpath);
126 return unixpath; /* no shortening required */
127 GNUNET_CRYPTO_hash (unixpath, slen, &sh);
129 strlen (unixpath) >= upm)
131 if (NULL == (end = strrchr (unixpath, '/')))
133 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
134 _("Unable to shorten unix path `%s' while keeping name unique\n"),
136 GNUNET_free (unixpath);
141 GNUNET_CRYPTO_hash_to_enc (&sh, &ae);
142 strncat (unixpath, (char*) ae.encoding, 16);
148 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
153 * Set if a socket should use blocking or non-blocking IO.
156 * @param doBlock blocking mode
157 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
160 GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
167 if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
170 SetErrnoFromWinsockError (WSAGetLastError ());
171 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
172 return GNUNET_SYSERR;
178 int flags = fcntl (fd->fd, F_GETFL);
183 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
184 return GNUNET_SYSERR;
187 flags &= ~O_NONBLOCK;
191 if (0 != fcntl (fd->fd, F_SETFL, flags))
194 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
195 return GNUNET_SYSERR;
203 * Make a socket non-inheritable to child processes
205 * @param h the socket to make non-inheritable
206 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
207 * @warning Not implemented on Windows
210 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
214 i = fcntl (h->fd, F_GETFD);
216 return GNUNET_SYSERR;
217 if (i == (i | FD_CLOEXEC))
220 if (fcntl (h->fd, F_SETFD, i) < 0)
221 return GNUNET_SYSERR;
225 b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
228 SetErrnoFromWinsockError (WSAGetLastError ());
229 return GNUNET_SYSERR;
238 * The MSG_NOSIGNAL equivalent on Mac OS X
240 * @param h the socket to make non-delaying
243 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
248 setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE,
249 (const void *) &abs_value,
251 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
257 * Disable delays when sending data via the socket.
258 * (GNUnet makes sure that messages are as big as
261 * @param h the socket to make non-delaying
264 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
269 if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
270 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
272 const char *abs_value = "1";
275 setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY,
276 (const void *) abs_value,
278 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
284 * Perform proper canonical initialization for a network handle.
285 * Set it to non-blocking, make it non-inheritable to child
286 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
287 * stream socket) and check that it is smaller than FD_SETSIZE.
289 * @param h socket to initialize
290 * @param af address family of the socket
291 * @param type socket type
292 * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
293 * failed and the handle was destroyed
296 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
301 if (h->fd == INVALID_SOCKET)
304 SetErrnoFromWinsockError (WSAGetLastError ());
307 return GNUNET_SYSERR;
310 if (h->fd >= FD_SETSIZE)
312 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
314 return GNUNET_SYSERR;
317 if (GNUNET_OK != socket_set_inheritable (h))
318 LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
319 "socket_set_inheritable");
321 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
324 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
325 return GNUNET_SYSERR;
328 socket_set_nosigpipe (h);
330 if ( (type == SOCK_STREAM)
335 socket_set_nodelay (h);
341 * accept a new connection on a socket
343 * @param desc bound socket
344 * @param address address of the connecting peer, may be NULL
345 * @param address_len length of @a address
346 * @return client socket
348 struct GNUNET_NETWORK_Handle *
349 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
350 struct sockaddr *address,
351 socklen_t *address_len)
353 struct GNUNET_NETWORK_Handle *ret;
355 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
358 struct sockaddr name;
359 socklen_t namelen = sizeof (name);
360 int gsn = getsockname (desc->fd, &name, &namelen);
363 LOG (GNUNET_ERROR_TYPE_DEBUG,
364 "Accepting connection on `%s'\n",
365 GNUNET_a2s (&name, namelen));
368 ret->fd = accept (desc->fd, address, address_len);
374 if (GNUNET_OK != initialize_network_handle (ret,
375 (NULL != address) ? address->sa_family : desc->af,
383 * Bind a socket to a particular address.
385 * @param desc socket to bind
386 * @param address address to be bound
387 * @param address_len length of @a address
388 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
391 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
392 const struct sockaddr *address,
393 socklen_t address_len)
402 if (AF_INET6 == desc->af)
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 /* set permissions of newly created UNIX domain socket to "user-only"; applications
423 can choose to relax this later */
424 mode_t old_mask = 0; /* assigned to make compiler happy */
426 if (AF_UNIX == address->sa_family)
427 old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH);
430 ret = bind (desc->fd, address, address_len);
432 if (AF_UNIX == address->sa_family)
433 (void) umask (old_mask);
437 if (SOCKET_ERROR == ret)
438 SetErrnoFromWinsockError (WSAGetLastError ());
441 return GNUNET_SYSERR;
443 desc->addr = GNUNET_malloc (address_len);
444 memcpy (desc->addr, address, address_len);
445 desc->addrlen = address_len;
455 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
458 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
466 ret = closesocket (desc->fd);
467 error = WSAGetLastError ();
468 SetErrnoFromWinsockError (error);
469 LOG (GNUNET_ERROR_TYPE_DEBUG,
470 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
473 ret = close (desc->fd);
476 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
478 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
480 if (0 != unlink (un->sun_path))
481 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
486 GNUNET_NETWORK_socket_free_memory_only_ (desc);
487 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
492 * Only free memory of a socket, keep the file descriptor untouched.
497 GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc)
499 GNUNET_free_non_null (desc->addr);
505 * Box a native socket (and check that it is a socket).
507 * @param fd socket to box
508 * @return NULL on error (including not supported on target platform)
510 struct GNUNET_NETWORK_Handle *
511 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
513 struct GNUNET_NETWORK_Handle *ret;
517 /* FIXME: Find a better call to check that FD is valid */
518 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
519 return NULL; /* invalid FD */
520 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
525 if (fcntl (fd, F_GETFD) < 0)
526 return NULL; /* invalid FD */
527 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
536 * Connect a socket to some remote address.
539 * @param address peer address
540 * @param address_len length of @a address
541 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
544 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
545 const struct sockaddr *address,
546 socklen_t address_len)
550 ret = connect (desc->fd, address, address_len);
553 if (SOCKET_ERROR == ret)
555 SetErrnoFromWinsockError (WSAGetLastError ());
556 if (errno == EWOULDBLOCK)
560 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
568 * @param level protocol level of the option
569 * @param optname identifier of the option
570 * @param optval options
571 * @param optlen length of @a optval
572 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
575 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
576 int level, int optname, void *optval,
581 ret = getsockopt (desc->fd, level, optname, optval, optlen);
584 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
585 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
587 else if (SOCKET_ERROR == ret)
588 SetErrnoFromWinsockError (WSAGetLastError ());
590 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
598 * @param backlog length of the listen queue
599 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
602 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
607 ret = listen (desc->fd, backlog);
610 if (SOCKET_ERROR == ret)
611 SetErrnoFromWinsockError (WSAGetLastError ());
614 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
619 * How much data is available to be read on this descriptor?
622 * @returns #GNUNET_NO if no data is available, or on error!
625 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
630 /* How much is there to be read? */
634 error = ioctl (desc->fd, FIONREAD, &pending);
636 return (ssize_t) pending;
641 error = ioctlsocket (desc->fd, FIONREAD, &pending);
642 if (error != SOCKET_ERROR)
643 return (ssize_t) pending;
650 * Read data from a socket (always non-blocking).
653 * @param buffer buffer
654 * @param length length of @a buffer
655 * @param src_addr either the source to recv from, or all zeroes
656 * to be filled in by recvfrom
657 * @param addrlen length of the @a src_addr
660 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
661 void *buffer, size_t length,
662 struct sockaddr *src_addr, socklen_t *addrlen)
670 flags |= MSG_DONTWAIT;
673 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
675 if (SOCKET_ERROR == ret)
676 SetErrnoFromWinsockError (WSAGetLastError ());
683 * Read data from a connected socket (always non-blocking).
686 * @param buffer buffer
687 * @param length length of @a buffer
690 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
691 void *buffer, size_t length)
699 flags |= MSG_DONTWAIT;
701 ret = recv (desc->fd, buffer, length, flags);
703 if (SOCKET_ERROR == ret)
704 SetErrnoFromWinsockError (WSAGetLastError ());
711 * Send data (always non-blocking).
714 * @param buffer data to send
715 * @param length size of the @a buffer
716 * @return number of bytes sent, #GNUNET_SYSERR on error
719 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
720 const void *buffer, size_t length)
728 flags |= MSG_DONTWAIT;
732 flags |= MSG_NOSIGNAL;
735 ret = send (desc->fd, buffer, length, flags);
738 if (SOCKET_ERROR == ret)
739 SetErrnoFromWinsockError (WSAGetLastError ());
747 * Send data to a particular destination (always non-blocking).
748 * This function only works for UDP sockets.
751 * @param message data to send
752 * @param length size of the data
753 * @param dest_addr destination address
754 * @param dest_len length of @a address
755 * @return number of bytes sent, #GNUNET_SYSERR on error
758 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
759 const void *message, size_t length,
760 const struct sockaddr * dest_addr,
769 flags |= MSG_DONTWAIT;
772 flags |= MSG_NOSIGNAL;
774 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
776 if (SOCKET_ERROR == ret)
777 SetErrnoFromWinsockError (WSAGetLastError ());
787 * @param level protocol level of the option
788 * @param option_name option identifier
789 * @param option_value value to set
790 * @param option_len size of option_value
791 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
794 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
795 int option_name, const void *option_value,
796 socklen_t option_len)
800 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
802 if (SOCKET_ERROR == ret)
803 SetErrnoFromWinsockError (WSAGetLastError ());
805 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
810 * Create a new socket. Configure it for non-blocking IO and
811 * mark it as non-inheritable to child processes (set the
812 * close-on-exec flag).
814 * @param domain domain of the socket
815 * @param type socket type
816 * @param protocol network protocol
817 * @return new socket, NULL on error
819 struct GNUNET_NETWORK_Handle *
820 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
822 struct GNUNET_NETWORK_Handle *ret;
824 ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
825 ret->fd = socket (domain, type, protocol);
832 initialize_network_handle (ret, domain, type))
839 * Shut down socket operations
841 * @param how type of shutdown
842 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
845 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
849 ret = shutdown (desc->fd, how);
852 SetErrnoFromWinsockError (WSAGetLastError ());
854 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
859 * Disable the "CORK" feature for communication with the given socket,
860 * forcing the OS to immediately flush the buffer on transmission
861 * instead of potentially buffering multiple messages. Essentially
862 * reduces the OS send buffers to zero.
865 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
868 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
877 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
879 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
882 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
884 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
890 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
891 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
894 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
895 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
897 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
907 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
912 GNUNET_CONTAINER_slist_clear (fds->handles);
918 * Add a socket to the FD set
921 * @param desc socket to add
924 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
925 const struct GNUNET_NETWORK_Handle *desc)
927 FD_SET (desc->fd, &fds->sds);
928 if (desc->fd + 1 > fds->nsds)
929 fds->nsds = desc->fd + 1;
934 * Check whether a socket is part of the fd set
938 * @return 0 if the FD is not set
941 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
942 const struct GNUNET_NETWORK_Handle *desc)
944 return FD_ISSET (desc->fd, &fds->sds);
949 * Add one fd set to another
951 * @param dst the fd set to add to
952 * @param src the fd set to add from
955 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
956 const struct GNUNET_NETWORK_FDSet *src)
961 for (nfds = src->nsds; nfds > 0; nfds--)
962 if (FD_ISSET (nfds, &src->sds))
965 FD_SET (nfds, &dst->sds);
966 if (nfds + 1 > dst->nsds)
967 dst->nsds = nfds + 1;
970 /* This is MinGW32-specific implementation that relies on the code that
971 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
972 * that fd being added is not already in the set.
973 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
976 for (i = 0; i < src->sds.fd_count; i++)
977 FD_SET (src->sds.fd_array[i], &dst->sds);
978 if (src->nsds > dst->nsds)
979 dst->nsds = src->nsds;
981 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
987 * Copy one fd set to another
989 * @param to destination
993 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
994 const struct GNUNET_NETWORK_FDSet *from)
996 FD_COPY (&from->sds, &to->sds);
997 to->nsds = from->nsds;
1000 GNUNET_CONTAINER_slist_clear (to->handles);
1001 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
1007 * Return file descriptor for this network handle
1009 * @param desc wrapper to process
1010 * @return POSIX file descriptor
1013 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
1020 * Return sockaddr for this network handle
1022 * @param desc wrapper to process
1026 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1033 * Return sockaddr length for this network handle
1035 * @param desc wrapper to process
1036 * @return socklen_t for sockaddr
1039 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1041 return desc->addrlen;
1046 * Copy a native fd set
1048 * @param to destination
1049 * @param from native source set
1050 * @param nfds the biggest socket number in from + 1
1053 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1054 const fd_set * from, int nfds)
1056 FD_COPY (from, &to->sds);
1062 * Set a native fd in a set
1064 * @param to destination
1065 * @param nfd native FD to set
1068 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1070 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1071 FD_SET (nfd, &to->sds);
1072 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1077 * Test native fd in a set
1079 * @param to set to test, NULL for empty set
1080 * @param nfd native FD to test, or -1 for none
1081 * @return #GNUNET_YES if FD is set in the set
1084 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1087 if ((nfd == -1) || (to == NULL))
1089 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1094 * Add a file handle to the fd set
1096 * @param h the file handle to add
1099 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1100 const struct GNUNET_DISK_FileHandle *h)
1103 GNUNET_CONTAINER_slist_add (fds->handles,
1104 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1105 sizeof (struct GNUNET_DISK_FileHandle));
1110 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1111 FD_SET (fd, &fds->sds);
1112 if (fd + 1 > fds->nsds)
1120 * Check if a file handle is part of an fd set
1122 * @param h file handle
1123 * @return #GNUNET_YES if the file handle is part of the set
1126 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1127 const struct GNUNET_DISK_FileHandle *h)
1131 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1133 GNUNET_DISK_FileHandle));
1135 return FD_ISSET (h->fd, &fds->sds);
1141 * Checks if two fd sets overlap
1142 * @param fds1 first fd set
1143 * @param fds2 second fd set
1144 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1147 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1148 const struct GNUNET_NETWORK_FDSet *fds2)
1154 if (nfds > fds2->nsds)
1159 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1163 struct GNUNET_CONTAINER_SList_Iterator it;
1164 struct GNUNET_DISK_FileHandle *h;
1168 /*This code is somewhat hacky, we are not supposed to know what's
1169 * inside of fd_set; also the O(n^2) is really bad... */
1171 for (i = 0; i < fds1->sds.fd_count; i++)
1173 for (j = 0; j < fds2->sds.fd_count; j++)
1175 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1179 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1180 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1183 struct GNUNET_CONTAINER_SList_Iterator t;
1185 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1188 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1190 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1191 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1192 GNUNET_CONTAINER_slist_next (&t))
1194 struct GNUNET_DISK_FileHandle *fh;
1196 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1198 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1201 if (GNUNET_CONTAINER_slist_contains
1202 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1206 GNUNET_CONTAINER_slist_next (&it);
1216 * @return a new fd set
1218 struct GNUNET_NETWORK_FDSet *
1219 GNUNET_NETWORK_fdset_create ()
1221 struct GNUNET_NETWORK_FDSet *fds;
1223 fds = GNUNET_new (struct GNUNET_NETWORK_FDSet);
1225 fds->handles = GNUNET_CONTAINER_slist_create ();
1227 GNUNET_NETWORK_fdset_zero (fds);
1233 * Releases the associated memory of an fd set
1238 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1241 GNUNET_CONTAINER_slist_destroy (fds->handles);
1247 struct _select_params
1255 SOCKET wakeup_socket;
1260 _selector (LPVOID p)
1262 struct _select_params *sp = p;
1266 WaitForSingleObject (sp->standby, INFINITE);
1267 ResetEvent (sp->standby);
1268 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1269 if (FD_ISSET (sp->wakeup_socket, sp->r))
1271 FD_CLR (sp->wakeup_socket, sp->r);
1274 SetEvent (sp->wakeup);
1282 * Check if sockets or pipes meet certain conditions
1283 * @param rfds set of sockets or pipes to be checked for readability
1284 * @param wfds set of sockets or pipes to be checked for writability
1285 * @param efds set of sockets or pipes to be checked for exceptions
1286 * @param timeout relative value when to return
1287 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1290 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1291 struct GNUNET_NETWORK_FDSet *wfds,
1292 struct GNUNET_NETWORK_FDSet *efds,
1293 const struct GNUNET_TIME_Relative timeout)
1299 int read_handles = 0;
1300 int write_handles = 0;
1304 uint64_t mcs_total = 0;
1305 DWORD ms_rounded = 0;
1309 static HANDLE hEventPipeWrite = 0;
1310 static HANDLE hEventReadReady = 0;
1312 static struct _select_params sp;
1313 static HANDLE select_thread = NULL;
1314 static HANDLE select_finished_event = NULL;
1315 static HANDLE select_standby_event = NULL;
1316 static SOCKET select_wakeup_socket = -1;
1317 static SOCKET select_send_socket = -1;
1318 static struct timeval select_timeout;
1321 int writePipePos = 0;
1323 HANDLE handle_array[FD_SETSIZE + 2];
1324 int returncode = -1;
1325 int returnedpos = 0;
1327 struct GNUNET_CONTAINER_SList *handles_read;
1328 struct GNUNET_CONTAINER_SList *handles_write;
1329 struct GNUNET_CONTAINER_SList *handles_except;
1343 /* TODO: Make this growable */
1344 struct GNUNET_DISK_FileHandle *readArray[50];
1352 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1355 struct GNUNET_CONTAINER_SList_Iterator t;
1357 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1358 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1359 GNUNET_CONTAINER_slist_next (&t))
1361 struct GNUNET_DISK_FileHandle *fh;
1363 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1365 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1374 nfds = GNUNET_MAX (nfds, wfds->nsds);
1376 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1381 nfds = GNUNET_MAX (nfds, efds->nsds);
1383 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1388 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1395 LOG (GNUNET_ERROR_TYPE_ERROR,
1397 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1401 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1403 (timeout.rel_value_us -
1404 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1405 return select (nfds,
1406 (NULL != rfds) ? &rfds->sds : NULL,
1407 (NULL != wfds) ? &wfds->sds : NULL,
1408 (NULL != efds) ? &efds->sds : NULL,
1409 (timeout.rel_value_us ==
1410 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1413 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1414 /* calculate how long we need to wait in microseconds */
1415 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1417 mcs_total = INFINITE;
1418 ms_rounded = INFINITE;
1422 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1423 ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1424 if (mcs_total > 0 && ms_rounded == 0)
1427 /* select() may be used as a portable way to sleep */
1428 if (!(rfds || wfds || efds))
1434 if (NULL == select_thread)
1436 SOCKET select_listening_socket = -1;
1437 struct sockaddr_in s_in;
1442 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1443 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1445 select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1447 select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1450 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1451 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1453 alen = sizeof (s_in);
1454 s_in.sin_family = AF_INET;
1456 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1457 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1458 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1459 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1460 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1461 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1463 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1464 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1466 res = listen (select_listening_socket, SOMAXCONN);
1467 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1469 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1470 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1472 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1474 closesocket (select_listening_socket);
1476 sp.wakeup = select_finished_event;
1477 sp.standby = select_standby_event;
1478 sp.wakeup_socket = select_wakeup_socket;
1480 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1484 handles_read = GNUNET_CONTAINER_slist_create ();
1485 handles_write = GNUNET_CONTAINER_slist_create ();
1486 handles_except = GNUNET_CONTAINER_slist_create ();
1497 FD_COPY (&rfds->sds, &aread);
1499 FD_COPY (&rfds->sds, &bread);
1504 FD_COPY (&wfds->sds, &awrite);
1506 FD_COPY (&wfds->sds, &bwrite);
1511 FD_COPY (&efds->sds, &aexcept);
1513 FD_COPY (&efds->sds, &bexcept);
1517 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1518 By profiling we detected that to be true in 90% of the cases.
1521 /* Do the select now */
1522 select_timeout.tv_sec = 0;
1523 select_timeout.tv_usec = 0;
1525 /* Copy all the writes to the except, so we can detect connect() errors */
1526 for (i = 0; i < awrite.fd_count; i++)
1527 FD_SET (awrite.fd_array[i], &aexcept);
1528 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1529 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1530 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1533 if (selectret == -1)
1535 /* Throw an error early on, while we still have the context. */
1536 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1537 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1541 /* Check aexcept, add its contents to awrite
1542 This is technically wrong (aexcept might have its own descriptors), we should
1543 have checked that descriptors were in awrite originally before re-adding them from
1544 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1545 for (i = 0; i < aexcept.fd_count; i++)
1546 FD_SET (aexcept.fd_array[i], &awrite);
1548 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1549 /* Sadly, it means code duplication :( */
1550 if ((selectret > 0) || (mcs_total == 0))
1553 if (rfds && read_handles)
1555 struct GNUNET_CONTAINER_SList_Iterator i;
1558 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1559 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1560 GNUNET_CONTAINER_slist_next (&i), c++)
1562 struct GNUNET_DISK_FileHandle *fh;
1564 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1565 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1571 DWORD waitstatus = 0;
1572 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1573 error = GetLastError ();
1574 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1575 c, fh->h, bret, waitstatus, error);
1578 /* TODO: either add more errors to this condition, or eliminate it
1579 * entirely (failed to peek -> pipe is in serious trouble, should
1580 * be selected as readable).
1582 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1585 else if (waitstatus <= 0)
1587 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1588 fh, sizeof (struct GNUNET_DISK_FileHandle));
1590 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1595 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1596 fh, sizeof (struct GNUNET_DISK_FileHandle));
1601 if (wfds && write_handles)
1603 LOG (GNUNET_ERROR_TYPE_DEBUG,
1604 "Adding the write ready event to the array as %d\n", nhandles);
1605 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1606 retcode += write_handles;
1608 if (efds && ex_handles)
1610 struct GNUNET_CONTAINER_SList_Iterator i;
1612 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1613 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1614 GNUNET_CONTAINER_slist_next (&i))
1616 struct GNUNET_DISK_FileHandle *fh;
1619 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1620 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1622 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1624 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1625 fh, sizeof (struct GNUNET_DISK_FileHandle));
1631 /* Add our select() result.*/
1633 retcode += selectret;
1637 GNUNET_NETWORK_fdset_zero (rfds);
1638 if (selectret != -1)
1639 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1640 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1644 GNUNET_NETWORK_fdset_zero (wfds);
1645 if (selectret != -1)
1646 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1647 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1651 GNUNET_NETWORK_fdset_zero (efds);
1652 if (selectret != -1)
1653 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1654 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1656 GNUNET_CONTAINER_slist_destroy (handles_read);
1657 GNUNET_CONTAINER_slist_destroy (handles_write);
1658 GNUNET_CONTAINER_slist_destroy (handles_except);
1660 if (selectret == -1)
1665 /* If we got this far, use slower implementation that is able to do a waiting select
1666 on both sockets and pipes simultaneously */
1668 /* Events for pipes */
1669 if (!hEventReadReady)
1670 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1671 if (!hEventPipeWrite)
1672 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1688 FD_COPY (&rfds->sds, &aread);
1690 FD_COPY (&rfds->sds, &bread);
1695 FD_COPY (&wfds->sds, &awrite);
1697 FD_COPY (&wfds->sds, &bwrite);
1702 FD_COPY (&efds->sds, &aexcept);
1704 FD_COPY (&efds->sds, &bexcept);
1707 /* We will first Add the PIPES to the events */
1709 if (rfds && read_handles)
1711 struct GNUNET_CONTAINER_SList_Iterator i;
1713 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1714 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1715 GNUNET_CONTAINER_slist_next (&i))
1717 struct GNUNET_DISK_FileHandle *fh;
1719 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1721 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1723 /* Read zero bytes to check the status of the pipe */
1724 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1726 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1728 DWORD error_code = GetLastError ();
1730 if (error_code == ERROR_IO_PENDING)
1732 LOG (GNUNET_ERROR_TYPE_DEBUG,
1733 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1735 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1736 readArray[readPipes++] = fh;
1740 LOG (GNUNET_ERROR_TYPE_DEBUG,
1741 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1742 handle_array[nhandles++] = hEventReadReady;
1743 readArray[readPipes++] = fh;
1748 LOG (GNUNET_ERROR_TYPE_DEBUG,
1749 "Adding the read ready event to the array as %d\n", nhandles);
1750 handle_array[nhandles++] = hEventReadReady;
1751 readArray[readPipes++] = fh;
1756 GNUNET_CONTAINER_slist_add (handles_read,
1757 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1758 fh, sizeof (struct GNUNET_DISK_FileHandle));
1762 if (wfds && write_handles)
1764 LOG (GNUNET_ERROR_TYPE_DEBUG,
1765 "Adding the write ready event to the array as %d\n", nhandles);
1766 handle_array[nhandles++] = hEventPipeWrite;
1767 writePipePos = nhandles;
1769 if (efds && ex_handles)
1771 struct GNUNET_CONTAINER_SList_Iterator i;
1773 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1774 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1775 GNUNET_CONTAINER_slist_next (&i))
1777 struct GNUNET_DISK_FileHandle *fh;
1780 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1782 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1784 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1786 GNUNET_CONTAINER_slist_add (handles_except,
1787 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1789 sizeof (struct GNUNET_DISK_FileHandle));
1799 LOG (GNUNET_ERROR_TYPE_DEBUG,
1800 "Adding the socket event to the array as %d\n",
1802 handle_array[nhandles++] = select_finished_event;
1803 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1807 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1808 select_timeout.tv_usec =(timeout.rel_value_us -
1809 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1810 sp.tv = &select_timeout;
1812 FD_SET (select_wakeup_socket, &aread);
1815 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1820 /* Failed connections cause sockets to be set in errorfds on W32,
1821 * but on POSIX it should set them in writefds.
1822 * First copy all awrite sockets to aexcept, later we'll
1823 * check aexcept and set its contents in awrite as well
1824 * Sockets are also set in errorfds when OOB data is available,
1825 * but we don't use OOB data.
1827 for (i = 0; i < awrite.fd_count; i++)
1828 FD_SET (awrite.fd_array[i], &aexcept);
1829 ResetEvent (select_finished_event);
1830 SetEvent (select_standby_event);
1833 handle_array[nhandles] = NULL;
1834 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
1835 nfds, nhandles, mcs_total);
1839 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
1840 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode);
1844 GNUNET_break (0); /* This branch shouldn't actually be executed...*/
1845 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1846 returncode = WAIT_TIMEOUT;
1850 /* Shouldn't come this far. If it does - investigate. */
1856 /* Don't wake up select-thread when delay is 0, it should return immediately
1857 * and wake up by itself.
1860 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1861 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1862 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1867 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1870 /* Check aexcept, add its contents to awrite */
1871 for (i = 0; i < aexcept.fd_count; i++)
1872 FD_SET (aexcept.fd_array[i], &awrite);
1875 returnedpos = returncode - WAIT_OBJECT_0;
1876 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1878 if (nhandles && (returnedpos < nhandles))
1883 retcode += sp.status;
1885 if ((writePipePos != -1) && (returnedpos < writePipePos))
1887 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1888 retcode += write_handles;
1889 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1891 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1892 /* We have some pipes ready for read. */
1893 if (returnedpos < readPipes)
1895 for (i = 0; i < readPipes; i++)
1903 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1904 error = GetLastError ();
1905 LOG (GNUNET_ERROR_TYPE_DEBUG,
1906 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1907 i, readArray[i]->h, bret, waitstatus, error);
1910 /* TODO: either add more errors to this condition, or eliminate it
1911 * entirely (failed to peek -> pipe is in serious trouble, should
1912 * be selected as readable).
1914 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1917 else if (waitstatus <= 0)
1919 GNUNET_CONTAINER_slist_add (handles_read,
1920 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1922 sizeof (struct GNUNET_DISK_FileHandle));
1924 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1925 readArray[i], readArray[i]->h);
1929 if (!nhandles || (returnedpos >= nhandles))
1930 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1933 struct GNUNET_CONTAINER_SList_Iterator t;
1935 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1936 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1937 GNUNET_CONTAINER_slist_next (&t))
1939 struct GNUNET_DISK_FileHandle *fh;
1941 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1943 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1948 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1949 GNUNET_NETWORK_fdset_zero (rfds);
1950 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1951 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1952 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1956 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1957 GNUNET_NETWORK_fdset_zero (wfds);
1958 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1959 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1960 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1964 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1965 GNUNET_NETWORK_fdset_zero (efds);
1966 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1967 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1968 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1970 GNUNET_CONTAINER_slist_destroy (handles_read);
1971 GNUNET_CONTAINER_slist_destroy (handles_write);
1972 GNUNET_CONTAINER_slist_destroy (handles_except);
1976 struct GNUNET_CONTAINER_SList_Iterator t;
1978 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1979 for (i = 0; i < rfds->sds.fd_count; i++)
1981 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1983 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1984 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1985 GNUNET_CONTAINER_slist_next (&t))
1987 struct GNUNET_DISK_FileHandle *fh;
1989 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1991 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1996 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1997 for (i = 0; i < wfds->sds.fd_count; i++)
1999 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
2004 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
2005 for (i = 0; i < efds->sds.fd_count; i++)
2007 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
2010 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
2012 if (nhandles && (returnedpos < nhandles))
2019 /* end of network.c */