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 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, socklen_t * address_len)
350 struct GNUNET_NETWORK_Handle *ret;
352 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
355 struct sockaddr name;
356 socklen_t namelen = sizeof (name);
357 int gsn = getsockname (desc->fd, &name, &namelen);
360 LOG (GNUNET_ERROR_TYPE_DEBUG, "Accepting connection on `%s'\n",
361 GNUNET_a2s (&name, namelen));
364 ret->fd = accept (desc->fd, address, address_len);
365 if (GNUNET_OK != initialize_network_handle (ret,
366 (NULL != address) ? address->sa_family : desc->af,
374 * Bind a socket to a particular address.
376 * @param desc socket to bind
377 * @param address address to be bound
378 * @param address_len length of address
379 * @param flags flags affecting bind behaviour
380 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
383 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
384 const struct sockaddr *address,
385 socklen_t address_len,
395 if (desc->af == AF_INET6)
396 if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY,
399 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
407 /* This is required here for TCP sockets, but only on UNIX */
408 if ((SOCK_STREAM == desc->type)
409 && (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))))
410 LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
415 if (address->sa_family == AF_UNIX && (flags & GNUNET_BIND_EXCLUSIVE) == 0)
417 const struct sockaddr_un *un = (const struct sockaddr_un *) address;
419 (void) unlink (un->sun_path);
423 ret = bind (desc->fd, address, address_len);
425 if (SOCKET_ERROR == ret)
426 SetErrnoFromWinsockError (WSAGetLastError ());
429 return GNUNET_SYSERR;
432 desc->addr = GNUNET_malloc (address_len);
433 memcpy (desc->addr, address, address_len);
434 desc->addrlen = address_len;
445 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
448 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
456 ret = closesocket (desc->fd);
457 error = WSAGetLastError ();
458 SetErrnoFromWinsockError (error);
459 LOG (GNUNET_ERROR_TYPE_DEBUG,
460 "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
463 ret = close (desc->fd);
467 if ((desc->af == AF_UNIX) && (NULL != desc->addr))
469 const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
471 if (0 != unlink (un->sun_path))
472 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
476 GNUNET_NETWORK_socket_free_memory_only_ (desc);
477 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
482 * Only free memory of a socket, keep the file descriptor untouched.
487 GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc)
489 GNUNET_free_non_null (desc->addr);
495 * Box a native socket (and check that it is a socket).
497 * @param fd socket to box
498 * @return NULL on error (including not supported on target platform)
500 struct GNUNET_NETWORK_Handle *
501 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
503 struct GNUNET_NETWORK_Handle *ret;
507 /* FIXME: Find a better call to check that FD is valid */
508 if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
509 return NULL; /* invalid FD */
510 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
515 if (fcntl (fd, F_GETFD) < 0)
516 return NULL; /* invalid FD */
517 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
526 * Connect a socket to some remote address.
529 * @param address peer address
530 * @param address_len length of address
531 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
534 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
535 const struct sockaddr *address,
536 socklen_t address_len)
540 ret = connect (desc->fd, address, address_len);
543 if (SOCKET_ERROR == ret)
545 SetErrnoFromWinsockError (WSAGetLastError ());
546 if (errno == EWOULDBLOCK)
550 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
558 * @param level protocol level of the option
559 * @param optname identifier of the option
560 * @param optval options
561 * @param optlen length of optval
562 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
565 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
566 int level, int optname, void *optval,
571 ret = getsockopt (desc->fd, level, optname, optval, optlen);
574 if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
575 *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
577 else if (SOCKET_ERROR == ret)
578 SetErrnoFromWinsockError (WSAGetLastError ());
580 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
588 * @param backlog length of the listen queue
589 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
592 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
597 ret = listen (desc->fd, backlog);
600 if (SOCKET_ERROR == ret)
601 SetErrnoFromWinsockError (WSAGetLastError ());
604 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
609 * How much data is available to be read on this descriptor?
612 * @returns #GNUNET_NO if no data is available, or on error!
615 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
620 /* How much is there to be read? */
624 error = ioctl (desc->fd, FIONREAD, &pending);
626 return (ssize_t) pending;
631 error = ioctlsocket (desc->fd, FIONREAD, &pending);
632 if (error != SOCKET_ERROR)
633 return (ssize_t) pending;
640 * Read data from a socket (always non-blocking).
643 * @param buffer buffer
644 * @param length length of buffer
645 * @param src_addr either the source to recv from, or all zeroes
646 * to be filled in by recvfrom
647 * @param addrlen length of the addr
650 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
651 void *buffer, size_t length,
652 struct sockaddr *src_addr, socklen_t *addrlen)
660 flags |= MSG_DONTWAIT;
663 ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
665 if (SOCKET_ERROR == ret)
666 SetErrnoFromWinsockError (WSAGetLastError ());
673 * Read data from a connected socket (always non-blocking).
676 * @param buffer buffer
677 * @param length length of buffer
680 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
681 void *buffer, size_t length)
689 flags |= MSG_DONTWAIT;
691 ret = recv (desc->fd, buffer, length, flags);
693 if (SOCKET_ERROR == ret)
694 SetErrnoFromWinsockError (WSAGetLastError ());
701 * Send data (always non-blocking).
704 * @param buffer data to send
705 * @param length size of the buffer
706 * @return number of bytes sent, GNUNET_SYSERR on error
709 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
710 const void *buffer, size_t length)
718 flags |= MSG_DONTWAIT;
722 flags |= MSG_NOSIGNAL;
725 ret = send (desc->fd, buffer, length, flags);
728 if (SOCKET_ERROR == ret)
729 SetErrnoFromWinsockError (WSAGetLastError ());
737 * Send data to a particular destination (always non-blocking).
738 * This function only works for UDP sockets.
741 * @param message data to send
742 * @param length size of the data
743 * @param dest_addr destination address
744 * @param dest_len length of address
745 * @return number of bytes sent, #GNUNET_SYSERR on error
748 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
749 const void *message, size_t length,
750 const struct sockaddr * dest_addr,
759 flags |= MSG_DONTWAIT;
762 flags |= MSG_NOSIGNAL;
764 ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
766 if (SOCKET_ERROR == ret)
767 SetErrnoFromWinsockError (WSAGetLastError ());
777 * @param level protocol level of the option
778 * @param option_name option identifier
779 * @param option_value value to set
780 * @param option_len size of option_value
781 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
784 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
785 int option_name, const void *option_value,
786 socklen_t option_len)
790 ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
792 if (SOCKET_ERROR == ret)
793 SetErrnoFromWinsockError (WSAGetLastError ());
795 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
800 * Create a new socket. Configure it for non-blocking IO and
801 * mark it as non-inheritable to child processes (set the
802 * close-on-exec flag).
804 * @param domain domain of the socket
805 * @param type socket type
806 * @param protocol network protocol
807 * @return new socket, NULL on error
809 struct GNUNET_NETWORK_Handle *
810 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
812 struct GNUNET_NETWORK_Handle *ret;
814 ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
815 ret->fd = socket (domain, type, protocol);
817 initialize_network_handle (ret, domain, type))
824 * Shut down socket operations
826 * @param how type of shutdown
827 * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
830 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
834 ret = shutdown (desc->fd, how);
837 SetErrnoFromWinsockError (WSAGetLastError ());
839 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
844 * Disable the "CORK" feature for communication with the given socket,
845 * forcing the OS to immediately flush the buffer on transmission
846 * instead of potentially buffering multiple messages. Essentially
847 * reduces the OS send buffers to zero.
850 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
853 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
862 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
864 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
867 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
869 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
875 setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
876 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
879 setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
880 LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
882 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
892 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
897 GNUNET_CONTAINER_slist_clear (fds->handles);
903 * Add a socket to the FD set
906 * @param desc socket to add
909 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
910 const struct GNUNET_NETWORK_Handle *desc)
912 FD_SET (desc->fd, &fds->sds);
913 if (desc->fd + 1 > fds->nsds)
914 fds->nsds = desc->fd + 1;
919 * Check whether a socket is part of the fd set
923 * @return 0 if the FD is not set
926 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
927 const struct GNUNET_NETWORK_Handle *desc)
929 return FD_ISSET (desc->fd, &fds->sds);
934 * Add one fd set to another
936 * @param dst the fd set to add to
937 * @param src the fd set to add from
940 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
941 const struct GNUNET_NETWORK_FDSet *src)
946 for (nfds = src->nsds; nfds > 0; nfds--)
947 if (FD_ISSET (nfds, &src->sds))
950 FD_SET (nfds, &dst->sds);
951 if (nfds + 1 > dst->nsds)
952 dst->nsds = nfds + 1;
955 /* This is MinGW32-specific implementation that relies on the code that
956 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
957 * that fd being added is not already in the set.
958 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
961 for (i = 0; i < src->sds.fd_count; i++)
962 FD_SET (src->sds.fd_array[i], &dst->sds);
963 if (src->nsds > dst->nsds)
964 dst->nsds = src->nsds;
966 GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
972 * Copy one fd set to another
974 * @param to destination
978 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
979 const struct GNUNET_NETWORK_FDSet *from)
981 FD_COPY (&from->sds, &to->sds);
982 to->nsds = from->nsds;
985 GNUNET_CONTAINER_slist_clear (to->handles);
986 GNUNET_CONTAINER_slist_append (to->handles, from->handles);
992 * Return file descriptor for this network handle
994 * @param desc wrapper to process
995 * @return POSIX file descriptor
998 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
1005 * Return sockaddr for this network handle
1007 * @param desc wrapper to process
1011 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1018 * Return sockaddr length for this network handle
1020 * @param desc wrapper to process
1021 * @return socklen_t for sockaddr
1024 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1026 return desc->addrlen;
1031 * Copy a native fd set
1033 * @param to destination
1034 * @param from native source set
1035 * @param nfds the biggest socket number in from + 1
1038 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1039 const fd_set * from, int nfds)
1041 FD_COPY (from, &to->sds);
1047 * Set a native fd in a set
1049 * @param to destination
1050 * @param nfd native FD to set
1053 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1055 GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1056 FD_SET (nfd, &to->sds);
1057 to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1062 * Test native fd in a set
1064 * @param to set to test, NULL for empty set
1065 * @param nfd native FD to test, or -1 for none
1066 * @return #GNUNET_YES if FD is set in the set
1069 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1072 if ((nfd == -1) || (to == NULL))
1074 return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1079 * Add a file handle to the fd set
1081 * @param h the file handle to add
1084 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1085 const struct GNUNET_DISK_FileHandle *h)
1088 GNUNET_CONTAINER_slist_add (fds->handles,
1089 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1090 sizeof (struct GNUNET_DISK_FileHandle));
1095 GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1096 FD_SET (fd, &fds->sds);
1097 if (fd + 1 > fds->nsds)
1105 * Check if a file handle is part of an fd set
1107 * @param h file handle
1108 * @return #GNUNET_YES if the file handle is part of the set
1111 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1112 const struct GNUNET_DISK_FileHandle *h)
1116 return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1118 GNUNET_DISK_FileHandle));
1120 return FD_ISSET (h->fd, &fds->sds);
1126 * Checks if two fd sets overlap
1127 * @param fds1 first fd set
1128 * @param fds2 second fd set
1129 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1132 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1133 const struct GNUNET_NETWORK_FDSet *fds2)
1139 if (nfds > fds2->nsds)
1144 if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1148 struct GNUNET_CONTAINER_SList_Iterator it;
1149 struct GNUNET_DISK_FileHandle *h;
1153 /*This code is somewhat hacky, we are not supposed to know what's
1154 * inside of fd_set; also the O(n^2) is really bad... */
1156 for (i = 0; i < fds1->sds.fd_count; i++)
1158 for (j = 0; j < fds2->sds.fd_count; j++)
1160 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1164 it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1165 while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1168 struct GNUNET_CONTAINER_SList_Iterator t;
1170 h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1173 LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1175 for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1176 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1177 GNUNET_CONTAINER_slist_next (&t))
1179 struct GNUNET_DISK_FileHandle *fh;
1181 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1183 LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1186 if (GNUNET_CONTAINER_slist_contains
1187 (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1191 GNUNET_CONTAINER_slist_next (&it);
1201 * @return a new fd set
1203 struct GNUNET_NETWORK_FDSet *
1204 GNUNET_NETWORK_fdset_create ()
1206 struct GNUNET_NETWORK_FDSet *fds;
1208 fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1210 fds->handles = GNUNET_CONTAINER_slist_create ();
1212 GNUNET_NETWORK_fdset_zero (fds);
1218 * Releases the associated memory of an fd set
1223 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1226 GNUNET_CONTAINER_slist_destroy (fds->handles);
1232 struct _select_params
1240 SOCKET wakeup_socket;
1245 _selector (LPVOID p)
1247 struct _select_params *sp = p;
1251 WaitForSingleObject (sp->standby, INFINITE);
1252 ResetEvent (sp->standby);
1253 sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1254 if (FD_ISSET (sp->wakeup_socket, sp->r))
1256 FD_CLR (sp->wakeup_socket, sp->r);
1259 SetEvent (sp->wakeup);
1267 * Check if sockets or pipes meet certain conditions
1268 * @param rfds set of sockets or pipes to be checked for readability
1269 * @param wfds set of sockets or pipes to be checked for writability
1270 * @param efds set of sockets or pipes to be checked for exceptions
1271 * @param timeout relative value when to return
1272 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1275 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1276 struct GNUNET_NETWORK_FDSet *wfds,
1277 struct GNUNET_NETWORK_FDSet *efds,
1278 const struct GNUNET_TIME_Relative timeout)
1284 int read_handles = 0;
1285 int write_handles = 0;
1289 uint64_t mcs_total = 0;
1290 DWORD ms_rounded = 0;
1294 static HANDLE hEventPipeWrite = 0;
1295 static HANDLE hEventReadReady = 0;
1297 static struct _select_params sp;
1298 static HANDLE select_thread = NULL;
1299 static HANDLE select_finished_event = NULL;
1300 static HANDLE select_standby_event = NULL;
1301 static SOCKET select_wakeup_socket = -1;
1302 static SOCKET select_send_socket = -1;
1303 static struct timeval select_timeout;
1306 int writePipePos = 0;
1308 HANDLE handle_array[FD_SETSIZE + 2];
1309 int returncode = -1;
1310 int returnedpos = 0;
1312 struct GNUNET_CONTAINER_SList *handles_read;
1313 struct GNUNET_CONTAINER_SList *handles_write;
1314 struct GNUNET_CONTAINER_SList *handles_except;
1328 /* TODO: Make this growable */
1329 struct GNUNET_DISK_FileHandle *readArray[50];
1337 handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1340 struct GNUNET_CONTAINER_SList_Iterator t;
1342 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1343 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1344 GNUNET_CONTAINER_slist_next (&t))
1346 struct GNUNET_DISK_FileHandle *fh;
1348 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1350 LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1359 nfds = GNUNET_MAX (nfds, wfds->nsds);
1361 handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1366 nfds = GNUNET_MAX (nfds, efds->nsds);
1368 handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1373 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1380 LOG (GNUNET_ERROR_TYPE_ERROR,
1382 ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1386 tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1388 (timeout.rel_value_us -
1389 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1390 return select (nfds,
1391 (NULL != rfds) ? &rfds->sds : NULL,
1392 (NULL != wfds) ? &wfds->sds : NULL,
1393 (NULL != efds) ? &efds->sds : NULL,
1394 (timeout.rel_value_us ==
1395 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1398 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1399 /* calculate how long we need to wait in microseconds */
1400 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1402 mcs_total = INFINITE;
1403 ms_rounded = INFINITE;
1407 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1408 ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1409 if (mcs_total > 0 && ms_rounded == 0)
1412 /* select() may be used as a portable way to sleep */
1413 if (!(rfds || wfds || efds))
1419 if (NULL == select_thread)
1421 SOCKET select_listening_socket = -1;
1422 struct sockaddr_in s_in;
1427 select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1428 select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1430 select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1432 select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1435 res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1436 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1438 alen = sizeof (s_in);
1439 s_in.sin_family = AF_INET;
1441 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1442 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1443 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1444 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1445 res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1446 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1448 res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1449 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1451 res = listen (select_listening_socket, SOMAXCONN);
1452 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1454 res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1455 LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1457 select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1459 closesocket (select_listening_socket);
1461 sp.wakeup = select_finished_event;
1462 sp.standby = select_standby_event;
1463 sp.wakeup_socket = select_wakeup_socket;
1465 select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1469 handles_read = GNUNET_CONTAINER_slist_create ();
1470 handles_write = GNUNET_CONTAINER_slist_create ();
1471 handles_except = GNUNET_CONTAINER_slist_create ();
1482 FD_COPY (&rfds->sds, &aread);
1484 FD_COPY (&rfds->sds, &bread);
1489 FD_COPY (&wfds->sds, &awrite);
1491 FD_COPY (&wfds->sds, &bwrite);
1496 FD_COPY (&efds->sds, &aexcept);
1498 FD_COPY (&efds->sds, &bexcept);
1502 /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1503 By profiling we detected that to be true in 90% of the cases.
1506 /* Do the select now */
1507 select_timeout.tv_sec = 0;
1508 select_timeout.tv_usec = 0;
1510 /* Copy all the writes to the except, so we can detect connect() errors */
1511 for (i = 0; i < awrite.fd_count; i++)
1512 FD_SET (awrite.fd_array[i], &aexcept);
1513 if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1514 selectret = select (1, (rfds != NULL) ? &aread : NULL,
1515 (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1518 if (selectret == -1)
1520 /* Throw an error early on, while we still have the context. */
1521 LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1522 rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1526 /* Check aexcept, add its contents to awrite
1527 This is technically wrong (aexcept might have its own descriptors), we should
1528 have checked that descriptors were in awrite originally before re-adding them from
1529 aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1530 for (i = 0; i < aexcept.fd_count; i++)
1531 FD_SET (aexcept.fd_array[i], &awrite);
1533 /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1534 /* Sadly, it means code duplication :( */
1535 if ((selectret > 0) || (mcs_total == 0))
1538 if (rfds && read_handles)
1540 struct GNUNET_CONTAINER_SList_Iterator i;
1543 for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1544 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1545 GNUNET_CONTAINER_slist_next (&i), c++)
1547 struct GNUNET_DISK_FileHandle *fh;
1549 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1550 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1556 DWORD waitstatus = 0;
1557 bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1558 error = GetLastError ();
1559 LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1560 c, fh->h, bret, waitstatus, error);
1563 /* TODO: either add more errors to this condition, or eliminate it
1564 * entirely (failed to peek -> pipe is in serious trouble, should
1565 * be selected as readable).
1567 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1570 else if (waitstatus <= 0)
1572 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1573 fh, sizeof (struct GNUNET_DISK_FileHandle));
1575 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1580 GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1581 fh, sizeof (struct GNUNET_DISK_FileHandle));
1586 if (wfds && write_handles)
1588 LOG (GNUNET_ERROR_TYPE_DEBUG,
1589 "Adding the write ready event to the array as %d\n", nhandles);
1590 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1591 retcode += write_handles;
1593 if (efds && ex_handles)
1595 struct GNUNET_CONTAINER_SList_Iterator i;
1597 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1598 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1599 GNUNET_CONTAINER_slist_next (&i))
1601 struct GNUNET_DISK_FileHandle *fh;
1604 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1605 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1607 if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1609 GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1610 fh, sizeof (struct GNUNET_DISK_FileHandle));
1616 /* Add our select() result.*/
1618 retcode += selectret;
1622 GNUNET_NETWORK_fdset_zero (rfds);
1623 if (selectret != -1)
1624 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1625 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1629 GNUNET_NETWORK_fdset_zero (wfds);
1630 if (selectret != -1)
1631 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1632 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1636 GNUNET_NETWORK_fdset_zero (efds);
1637 if (selectret != -1)
1638 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1639 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1641 GNUNET_CONTAINER_slist_destroy (handles_read);
1642 GNUNET_CONTAINER_slist_destroy (handles_write);
1643 GNUNET_CONTAINER_slist_destroy (handles_except);
1645 if (selectret == -1)
1650 /* If we got this far, use slower implementation that is able to do a waiting select
1651 on both sockets and pipes simultaneously */
1653 /* Events for pipes */
1654 if (!hEventReadReady)
1655 hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1656 if (!hEventPipeWrite)
1657 hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1673 FD_COPY (&rfds->sds, &aread);
1675 FD_COPY (&rfds->sds, &bread);
1680 FD_COPY (&wfds->sds, &awrite);
1682 FD_COPY (&wfds->sds, &bwrite);
1687 FD_COPY (&efds->sds, &aexcept);
1689 FD_COPY (&efds->sds, &bexcept);
1692 /* We will first Add the PIPES to the events */
1694 if (rfds && read_handles)
1696 struct GNUNET_CONTAINER_SList_Iterator i;
1698 for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1699 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1700 GNUNET_CONTAINER_slist_next (&i))
1702 struct GNUNET_DISK_FileHandle *fh;
1704 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1706 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1708 /* Read zero bytes to check the status of the pipe */
1709 LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1711 if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1713 DWORD error_code = GetLastError ();
1715 if (error_code == ERROR_IO_PENDING)
1717 LOG (GNUNET_ERROR_TYPE_DEBUG,
1718 "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1720 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1721 readArray[readPipes++] = fh;
1725 LOG (GNUNET_ERROR_TYPE_DEBUG,
1726 "Read failed, adding the read ready event to the array as %d\n", nhandles);
1727 handle_array[nhandles++] = hEventReadReady;
1728 readArray[readPipes++] = fh;
1733 LOG (GNUNET_ERROR_TYPE_DEBUG,
1734 "Adding the read ready event to the array as %d\n", nhandles);
1735 handle_array[nhandles++] = hEventReadReady;
1736 readArray[readPipes++] = fh;
1741 GNUNET_CONTAINER_slist_add (handles_read,
1742 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1743 fh, sizeof (struct GNUNET_DISK_FileHandle));
1747 if (wfds && write_handles)
1749 LOG (GNUNET_ERROR_TYPE_DEBUG,
1750 "Adding the write ready event to the array as %d\n", nhandles);
1751 handle_array[nhandles++] = hEventPipeWrite;
1752 writePipePos = nhandles;
1754 if (efds && ex_handles)
1756 struct GNUNET_CONTAINER_SList_Iterator i;
1758 for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1759 GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1760 GNUNET_CONTAINER_slist_next (&i))
1762 struct GNUNET_DISK_FileHandle *fh;
1765 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1767 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1769 if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1771 GNUNET_CONTAINER_slist_add (handles_except,
1772 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1774 sizeof (struct GNUNET_DISK_FileHandle));
1784 LOG (GNUNET_ERROR_TYPE_DEBUG,
1785 "Adding the socket event to the array as %d\n",
1787 handle_array[nhandles++] = select_finished_event;
1788 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1792 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1793 select_timeout.tv_usec =(timeout.rel_value_us -
1794 (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1795 sp.tv = &select_timeout;
1797 FD_SET (select_wakeup_socket, &aread);
1800 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1805 /* Failed connections cause sockets to be set in errorfds on W32,
1806 * but on POSIX it should set them in writefds.
1807 * First copy all awrite sockets to aexcept, later we'll
1808 * check aexcept and set its contents in awrite as well
1809 * Sockets are also set in errorfds when OOB data is available,
1810 * but we don't use OOB data.
1812 for (i = 0; i < awrite.fd_count; i++)
1813 FD_SET (awrite.fd_array[i], &aexcept);
1814 ResetEvent (select_finished_event);
1815 SetEvent (select_standby_event);
1818 handle_array[nhandles] = NULL;
1819 LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
1820 nfds, nhandles, mcs_total);
1824 WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
1825 LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode);
1829 GNUNET_break (0); /* This branch shouldn't actually be executed...*/
1830 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1831 returncode = WAIT_TIMEOUT;
1835 /* Shouldn't come this far. If it does - investigate. */
1841 /* Don't wake up select-thread when delay is 0, it should return immediately
1842 * and wake up by itself.
1845 i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1846 i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1847 LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1852 i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1855 /* Check aexcept, add its contents to awrite */
1856 for (i = 0; i < aexcept.fd_count; i++)
1857 FD_SET (aexcept.fd_array[i], &awrite);
1860 returnedpos = returncode - WAIT_OBJECT_0;
1861 LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1863 if (nhandles && (returnedpos < nhandles))
1868 retcode += sp.status;
1870 if ((writePipePos != -1) && (returnedpos < writePipePos))
1872 GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1873 retcode += write_handles;
1874 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1876 LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1877 /* We have some pipes ready for read. */
1878 if (returnedpos < readPipes)
1880 for (i = 0; i < readPipes; i++)
1888 PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1889 error = GetLastError ();
1890 LOG (GNUNET_ERROR_TYPE_DEBUG,
1891 "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1892 i, readArray[i]->h, bret, waitstatus, error);
1895 /* TODO: either add more errors to this condition, or eliminate it
1896 * entirely (failed to peek -> pipe is in serious trouble, should
1897 * be selected as readable).
1899 if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1902 else if (waitstatus <= 0)
1904 GNUNET_CONTAINER_slist_add (handles_read,
1905 GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1907 sizeof (struct GNUNET_DISK_FileHandle));
1909 LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1910 readArray[i], readArray[i]->h);
1914 if (!nhandles || (returnedpos >= nhandles))
1915 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1918 struct GNUNET_CONTAINER_SList_Iterator t;
1920 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1921 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1922 GNUNET_CONTAINER_slist_next (&t))
1924 struct GNUNET_DISK_FileHandle *fh;
1926 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1928 if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1933 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1934 GNUNET_NETWORK_fdset_zero (rfds);
1935 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1936 GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1937 GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1941 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1942 GNUNET_NETWORK_fdset_zero (wfds);
1943 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1944 GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1945 GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1949 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1950 GNUNET_NETWORK_fdset_zero (efds);
1951 if (retcode != -1 && nhandles && (returnedpos < nhandles))
1952 GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1953 GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1955 GNUNET_CONTAINER_slist_destroy (handles_read);
1956 GNUNET_CONTAINER_slist_destroy (handles_write);
1957 GNUNET_CONTAINER_slist_destroy (handles_except);
1961 struct GNUNET_CONTAINER_SList_Iterator t;
1963 LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1964 for (i = 0; i < rfds->sds.fd_count; i++)
1966 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1968 for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1969 GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1970 GNUNET_CONTAINER_slist_next (&t))
1972 struct GNUNET_DISK_FileHandle *fh;
1974 fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1976 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1981 LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1982 for (i = 0; i < wfds->sds.fd_count; i++)
1984 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1989 LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1990 for (i = 0; i < efds->sds.fd_count; i++)
1992 LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1995 LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1997 if (nhandles && (returnedpos < nhandles))
2004 /* end of network.c */