2 This file is part of GNUnet.
3 Copyright (C) 2009-2013 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
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-network", __VA_ARGS__)
32 #define LOG_STRERROR_FILE(kind, syscall, filename) GNUNET_log_from_strerror_file(kind, "util-network", syscall, filename)
33 #define LOG_STRERROR(kind, syscall) GNUNET_log_from_strerror(kind, "util-network", syscall)
35 #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
38 #ifndef INVALID_SOCKET
39 #define INVALID_SOCKET -1
44 * @brief handle to a socket
46 struct GNUNET_NETWORK_Handle {
54 * Address family / domain.
64 * Number of bytes in addr.
69 * Address we were bound to, or NULL.
71 struct sockaddr *addr;
76 * Test if the given protocol family is supported by this system.
78 * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
79 * @return #GNUNET_OK if the PF is supported
82 GNUNET_NETWORK_test_pf(int pf)
84 static int cache_v4 = -1;
85 static int cache_v6 = -1;
86 static int cache_un = -1;
109 s = socket(pf, SOCK_STREAM, 0);
112 if (EAFNOSUPPORT != errno)
114 GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING,
116 return GNUNET_SYSERR;
150 * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
151 * shorten it to an acceptable length while keeping it unique
152 * and making sure it remains a valid filename (if possible).
154 * @param unixpath long path, will be freed (or same pointer returned
155 * with moved 0-termination).
156 * @return shortened unixpath, NULL on error
159 GNUNET_NETWORK_shorten_unixpath(char *unixpath)
161 struct sockaddr_un dummy;
164 struct GNUNET_HashCode sh;
165 struct GNUNET_CRYPTO_HashAsciiEncoded ae;
168 upm = sizeof(dummy.sun_path);
169 slen = strlen(unixpath);
171 return unixpath; /* no shortening required */
172 GNUNET_CRYPTO_hash(unixpath, slen, &sh);
173 while (16 + strlen(unixpath) >= upm)
175 if (NULL == (end = strrchr(unixpath, '/')))
177 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
178 _("Unable to shorten unix path `%s' while keeping name unique\n"),
180 GNUNET_free(unixpath);
185 GNUNET_CRYPTO_hash_to_enc(&sh, &ae);
186 ae.encoding[16] = '\0';
187 strcat(unixpath, (char *)ae.encoding);
194 * If services crash, they can leave a unix domain socket file on the
195 * disk. This needs to be manually removed, because otherwise both
196 * bind() and connect() for the respective address will fail. In this
197 * function, we test if such a left-over file exists, and if so,
198 * remove it (unless there is a listening service at the address).
200 * @param un unix domain socket address to check
203 GNUNET_NETWORK_unix_precheck(const struct sockaddr_un *un)
210 s = socket(AF_UNIX, SOCK_STREAM, 0);
213 GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING,
214 "Failed to open AF_UNIX socket");
218 (struct sockaddr *)un,
219 sizeof(struct sockaddr_un));
221 GNUNET_break(0 == close(s));
223 return; /* another process is listening, do not remove! */
224 if (ECONNREFUSED != eno)
225 return; /* some other error, likely "no such file or directory" -- all well */
226 /* should unlink, but sanity checks first */
227 if (0 != stat(un->sun_path,
229 return; /* failed to 'stat', likely does not exist after all */
230 if (S_IFSOCK != (S_IFMT & sbuf.st_mode))
231 return; /* refuse to unlink anything except sockets */
232 /* finally, really unlink */
233 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
234 "Removing left-over `%s' from previous exeuction\n",
236 if (0 != unlink(un->sun_path))
237 GNUNET_log_strerror_file(GNUNET_ERROR_TYPE_WARNING,
246 #define FD_COPY(s, d) do { GNUNET_memcpy((d), (s), sizeof(fd_set)); } while (0)
251 * Set if a socket should use blocking or non-blocking IO.
254 * @param doBlock blocking mode
255 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
258 GNUNET_NETWORK_socket_set_blocking(struct GNUNET_NETWORK_Handle *fd,
271 SetErrnoFromWinsockError(WSAGetLastError());
272 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING,
274 return GNUNET_SYSERR;
279 int flags = fcntl(fd->fd, F_GETFL);
283 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING,
285 return GNUNET_SYSERR;
288 flags &= ~O_NONBLOCK;
292 if (0 != fcntl(fd->fd,
297 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING,
299 return GNUNET_SYSERR;
307 * Make a socket non-inheritable to child processes
309 * @param h the socket to make non-inheritable
310 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
311 * @warning Not implemented on Windows
314 socket_set_inheritable(const struct GNUNET_NETWORK_Handle *h)
318 i = fcntl(h->fd, F_GETFD);
320 return GNUNET_SYSERR;
321 if (i == (i | FD_CLOEXEC))
324 if (fcntl(h->fd, F_SETFD, i) < 0)
325 return GNUNET_SYSERR;
329 b = SetHandleInformation((HANDLE)h->fd, HANDLE_FLAG_INHERIT, 0);
332 SetErrnoFromWinsockError(WSAGetLastError());
333 return GNUNET_SYSERR;
342 * The MSG_NOSIGNAL equivalent on Mac OS X
344 * @param h the socket to make non-delaying
347 socket_set_nosigpipe(const struct GNUNET_NETWORK_Handle *h)
352 setsockopt(h->fd, SOL_SOCKET, SO_NOSIGPIPE,
353 (const void *)&abs_value,
355 return GNUNET_SYSERR;
362 * Disable delays when sending data via the socket.
363 * (GNUnet makes sure that messages are as big as
366 * @param h the socket to make non-delaying
369 socket_set_nodelay(const struct GNUNET_NETWORK_Handle *h)
378 &value, sizeof(value)))
379 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING,
382 const char *abs_value = "1";
388 (const void *)abs_value,
390 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING,
397 * Perform proper canonical initialization for a network handle.
398 * Set it to non-blocking, make it non-inheritable to child
399 * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
400 * stream socket) and check that it is smaller than FD_SETSIZE.
402 * @param h socket to initialize
403 * @param af address family of the socket
404 * @param type socket type
405 * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
406 * failed and the handle was destroyed
409 initialize_network_handle(struct GNUNET_NETWORK_Handle *h,
417 if (h->fd == INVALID_SOCKET)
420 SetErrnoFromWinsockError(WSAGetLastError());
425 return GNUNET_SYSERR;
428 if (h->fd >= FD_SETSIZE)
430 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(h));
432 return GNUNET_SYSERR;
435 if (GNUNET_OK != socket_set_inheritable(h))
436 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
437 "socket_set_inheritable");
439 if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking(h, GNUNET_NO))
443 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(h));
445 return GNUNET_SYSERR;
448 if (GNUNET_SYSERR == socket_set_nosigpipe(h))
452 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(h));
454 return GNUNET_SYSERR;
457 if ((type == SOCK_STREAM)
462 socket_set_nodelay(h);
468 * accept a new connection on a socket
470 * @param desc bound socket
471 * @param address address of the connecting peer, may be NULL
472 * @param address_len length of @a address
473 * @return client socket
475 struct GNUNET_NETWORK_Handle *
476 GNUNET_NETWORK_socket_accept(const struct GNUNET_NETWORK_Handle *desc,
477 struct sockaddr *address,
478 socklen_t *address_len)
480 struct GNUNET_NETWORK_Handle *ret;
483 ret = GNUNET_new(struct GNUNET_NETWORK_Handle);
486 struct sockaddr_storage name;
487 socklen_t namelen = sizeof(name);
489 int gsn = getsockname(desc->fd,
490 (struct sockaddr *)&name,
494 LOG(GNUNET_ERROR_TYPE_DEBUG,
495 "Accepting connection on `%s'\n",
496 GNUNET_a2s((const struct sockaddr *)&name,
500 ret->fd = accept(desc->fd,
511 initialize_network_handle(ret,
512 (NULL != address) ? address->sa_family : desc->af,
522 * Bind a socket to a particular address.
524 * @param desc socket to bind
525 * @param address address to be bound
526 * @param address_len length of @a address
527 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
530 GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc,
531 const struct sockaddr *address,
532 socklen_t address_len)
541 if (AF_INET6 == desc->af)
542 if (setsockopt(desc->fd,
547 LOG_STRERROR(GNUNET_ERROR_TYPE_DEBUG,
553 if (AF_UNIX == address->sa_family)
554 GNUNET_NETWORK_unix_precheck((const struct sockaddr_un *)address);
558 /* This is required here for TCP sockets, but only on UNIX */
559 if ((SOCK_STREAM == desc->type) &&
560 (0 != setsockopt(desc->fd,
564 LOG_STRERROR(GNUNET_ERROR_TYPE_DEBUG,
568 /* set permissions of newly created non-abstract UNIX domain socket to
569 "user-only"; applications can choose to relax this later */
570 mode_t old_mask = 0; /* assigned to make compiler happy */
571 const struct sockaddr_un *un = (const struct sockaddr_un *)address;
572 int not_abstract = 0;
574 if ((AF_UNIX == address->sa_family)
575 && ('\0' != un->sun_path[0])) /* Not an abstract socket */
578 old_mask = umask(S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH);
587 (void)umask(old_mask);
591 if (SOCKET_ERROR == ret)
592 SetErrnoFromWinsockError(WSAGetLastError());
595 return GNUNET_SYSERR;
597 desc->addr = GNUNET_malloc(address_len);
598 GNUNET_memcpy(desc->addr, address, address_len);
599 desc->addrlen = address_len;
609 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
612 GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
620 ret = closesocket(desc->fd);
621 error = WSAGetLastError();
622 SetErrnoFromWinsockError(error);
623 LOG(GNUNET_ERROR_TYPE_DEBUG,
624 "Closed 0x%x, closesocket() returned %d, GLE is %u\n",
629 ret = close(desc->fd);
632 const struct sockaddr_un *un = (const struct sockaddr_un *)desc->addr;
634 /* Cleanup the UNIX domain socket and its parent directories in case of non
636 if ((AF_UNIX == desc->af) &&
637 (NULL != desc->addr) &&
638 ('\0' != un->sun_path[0]))
640 char *dirname = GNUNET_strndup(un->sun_path,
641 sizeof(un->sun_path));
643 if (0 != unlink(dirname))
645 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_WARNING,
653 len = strlen(dirname);
654 while ((len > 0) && (dirname[len] != DIR_SEPARATOR))
657 if ((0 != len) && (0 != rmdir(dirname)))
664 /* these are normal and can just be ignored */
668 GNUNET_log_strerror_file(GNUNET_ERROR_TYPE_WARNING,
675 GNUNET_free(dirname);
678 GNUNET_NETWORK_socket_free_memory_only_(desc);
679 return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
684 * Only free memory of a socket, keep the file descriptor untouched.
689 GNUNET_NETWORK_socket_free_memory_only_(struct GNUNET_NETWORK_Handle *desc)
691 GNUNET_free_non_null(desc->addr);
697 * Box a native socket (and check that it is a socket).
699 * @param fd socket to box
700 * @return NULL on error (including not supported on target platform)
702 struct GNUNET_NETWORK_Handle *
703 GNUNET_NETWORK_socket_box_native(SOCKTYPE fd)
705 struct GNUNET_NETWORK_Handle *ret;
710 /* FIXME: Find a better call to check that FD is valid */
712 WSAIoctl(fd, FIONBIO,
713 (void *)&i, sizeof(i),
716 return NULL; /* invalid FD */
717 ret = GNUNET_new(struct GNUNET_NETWORK_Handle);
722 if (fcntl(fd, F_GETFD) < 0)
723 return NULL; /* invalid FD */
724 ret = GNUNET_new(struct GNUNET_NETWORK_Handle);
733 * Connect a socket to some remote address.
736 * @param address peer address
737 * @param address_len length of @a address
738 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
741 GNUNET_NETWORK_socket_connect(const struct GNUNET_NETWORK_Handle *desc,
742 const struct sockaddr *address,
743 socklen_t address_len)
747 ret = connect(desc->fd,
751 if (SOCKET_ERROR == ret)
753 SetErrnoFromWinsockError(WSAGetLastError());
754 if (errno == EWOULDBLOCK)
758 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
766 * @param level protocol level of the option
767 * @param optname identifier of the option
768 * @param optval options
769 * @param optlen length of @a optval
770 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
773 GNUNET_NETWORK_socket_getsockopt(const struct GNUNET_NETWORK_Handle *desc,
781 ret = getsockopt(desc->fd,
788 (SOL_SOCKET == level) &&
789 (SO_ERROR == optname))
790 *((int *)optval) = GetErrnoFromWinsockError(*((int *)optval));
791 else if (SOCKET_ERROR == ret)
792 SetErrnoFromWinsockError(WSAGetLastError());
794 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
802 * @param backlog length of the listen queue
803 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
806 GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc,
811 ret = listen(desc->fd,
814 if (SOCKET_ERROR == ret)
815 SetErrnoFromWinsockError(WSAGetLastError());
817 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
822 * How much data is available to be read on this descriptor?
825 * @returns #GNUNET_SYSERR if no data is available, or on error!
828 GNUNET_NETWORK_socket_recvfrom_amount(const struct GNUNET_NETWORK_Handle *desc)
832 /* How much is there to be read? */
836 error = ioctl(desc->fd,
840 return (ssize_t)pending;
841 return GNUNET_SYSERR;
845 error = ioctlsocket(desc->fd,
848 if (error != SOCKET_ERROR)
849 return (ssize_t)pending;
850 return GNUNET_SYSERR;
856 * Read data from a socket (always non-blocking).
859 * @param buffer buffer
860 * @param length length of @a buffer
861 * @param src_addr either the source to recv from, or all zeroes
862 * to be filled in by recvfrom
863 * @param addrlen length of the @a src_addr
866 GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc,
869 struct sockaddr *src_addr,
878 flags |= MSG_DONTWAIT;
880 ret = recvfrom(desc->fd,
887 if (SOCKET_ERROR == ret)
888 SetErrnoFromWinsockError(WSAGetLastError());
895 * Read data from a connected socket (always non-blocking).
898 * @param buffer buffer
899 * @param length length of @a buffer
900 * @return number of bytes received, -1 on error
903 GNUNET_NETWORK_socket_recv(const struct GNUNET_NETWORK_Handle *desc,
913 flags |= MSG_DONTWAIT;
920 if (SOCKET_ERROR == ret)
921 SetErrnoFromWinsockError(WSAGetLastError());
928 * Send data (always non-blocking).
931 * @param buffer data to send
932 * @param length size of the @a buffer
933 * @return number of bytes sent, #GNUNET_SYSERR on error
936 GNUNET_NETWORK_socket_send(const struct GNUNET_NETWORK_Handle *desc,
945 flags |= MSG_DONTWAIT;
948 flags |= MSG_NOSIGNAL;
955 if (SOCKET_ERROR == ret)
956 SetErrnoFromWinsockError(WSAGetLastError());
963 * Send data to a particular destination (always non-blocking).
964 * This function only works for UDP sockets.
967 * @param message data to send
968 * @param length size of the @a message
969 * @param dest_addr destination address
970 * @param dest_len length of @a address
971 * @return number of bytes sent, #GNUNET_SYSERR on error
974 GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc,
977 const struct sockaddr *dest_addr,
986 flags |= MSG_DONTWAIT;
989 flags |= MSG_NOSIGNAL;
991 ret = sendto(desc->fd, message, length, flags, dest_addr, dest_len);
993 if (SOCKET_ERROR == ret)
994 SetErrnoFromWinsockError(WSAGetLastError());
1004 * @param level protocol level of the option
1005 * @param option_name option identifier
1006 * @param option_value value to set
1007 * @param option_len size of @a option_value
1008 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1011 GNUNET_NETWORK_socket_setsockopt(struct GNUNET_NETWORK_Handle *fd,
1014 const void *option_value,
1015 socklen_t option_len)
1019 ret = setsockopt(fd->fd,
1025 if (SOCKET_ERROR == ret)
1026 SetErrnoFromWinsockError(WSAGetLastError());
1028 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
1033 * Create a new socket. Configure it for non-blocking IO and
1034 * mark it as non-inheritable to child processes (set the
1035 * close-on-exec flag).
1037 * @param domain domain of the socket
1038 * @param type socket type
1039 * @param protocol network protocol
1040 * @return new socket, NULL on error
1042 struct GNUNET_NETWORK_Handle *
1043 GNUNET_NETWORK_socket_create(int domain,
1047 struct GNUNET_NETWORK_Handle *ret;
1050 fd = socket(domain, type, protocol);
1053 ret = GNUNET_new(struct GNUNET_NETWORK_Handle);
1056 initialize_network_handle(ret,
1065 * Shut down socket operations
1066 * @param desc socket
1067 * @param how type of shutdown
1068 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1071 GNUNET_NETWORK_socket_shutdown(struct GNUNET_NETWORK_Handle *desc,
1076 ret = shutdown(desc->fd, how);
1079 SetErrnoFromWinsockError(WSAGetLastError());
1081 return (0 == ret) ? GNUNET_OK : GNUNET_SYSERR;
1086 * Disable the "CORK" feature for communication with the given socket,
1087 * forcing the OS to immediately flush the buffer on transmission
1088 * instead of potentially buffering multiple messages. Essentially
1089 * reduces the OS send buffers to zero.
1091 * @param desc socket
1092 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1095 GNUNET_NETWORK_socket_disable_corking(struct GNUNET_NETWORK_Handle *desc)
1104 setsockopt(desc->fd,
1109 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING,
1113 setsockopt(desc->fd,
1118 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING,
1125 setsockopt(desc->fd,
1130 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING,
1134 setsockopt(desc->fd,
1139 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING,
1142 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
1152 GNUNET_NETWORK_fdset_zero(struct GNUNET_NETWORK_FDSet *fds)
1157 fds->handles_pos = 0;
1163 * Add a socket to the FD set
1166 * @param desc socket to add
1169 GNUNET_NETWORK_fdset_set(struct GNUNET_NETWORK_FDSet *fds,
1170 const struct GNUNET_NETWORK_Handle *desc)
1174 fds->nsds = GNUNET_MAX(fds->nsds,
1180 * Check whether a socket is part of the fd set
1183 * @param desc socket
1184 * @return 0 if the FD is not set
1187 GNUNET_NETWORK_fdset_isset(const struct GNUNET_NETWORK_FDSet *fds,
1188 const struct GNUNET_NETWORK_Handle *desc)
1190 return FD_ISSET(desc->fd,
1196 * Add one fd set to another
1198 * @param dst the fd set to add to
1199 * @param src the fd set to add from
1202 GNUNET_NETWORK_fdset_add(struct GNUNET_NETWORK_FDSet *dst,
1203 const struct GNUNET_NETWORK_FDSet *src)
1208 for (nfds = src->nsds; nfds >= 0; nfds--)
1209 if (FD_ISSET(nfds, &src->sds))
1210 FD_SET(nfds, &dst->sds);
1211 dst->nsds = GNUNET_MAX(dst->nsds,
1214 /* This is MinGW32-specific implementation that relies on the code that
1215 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
1216 * that fd being added is not already in the set.
1217 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
1219 * NOTE: I don't understand why the UNIX-logic wouldn't work
1220 * for the first part here as well. -CG
1224 for (i = 0; i < src->sds.fd_count; i++)
1225 FD_SET(src->sds.fd_array[i],
1227 dst->nsds = GNUNET_MAX(src->nsds,
1230 /* also copy over `struct GNUNET_DISK_FileHandle` array */
1231 if (dst->handles_pos + src->handles_pos > dst->handles_size)
1232 GNUNET_array_grow(dst->handles,
1234 ((dst->handles_pos + src->handles_pos) << 1));
1235 for (i = 0; i < src->handles_pos; i++)
1236 dst->handles[dst->handles_pos++] = src->handles[i];
1242 * Copy one fd set to another
1244 * @param to destination
1245 * @param from source
1248 GNUNET_NETWORK_fdset_copy(struct GNUNET_NETWORK_FDSet *to,
1249 const struct GNUNET_NETWORK_FDSet *from)
1253 to->nsds = from->nsds;
1255 if (from->handles_pos > to->handles_size)
1256 GNUNET_array_grow(to->handles,
1258 from->handles_pos * 2);
1259 GNUNET_memcpy(to->handles,
1261 from->handles_pos * sizeof(struct GNUNET_NETWORK_Handle *));
1262 to->handles_pos = from->handles_pos;
1268 * Return file descriptor for this network handle
1270 * @param desc wrapper to process
1271 * @return POSIX file descriptor
1274 GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
1281 * Return sockaddr for this network handle
1283 * @param desc wrapper to process
1287 GNUNET_NETWORK_get_addr(const struct GNUNET_NETWORK_Handle *desc)
1294 * Return sockaddr length for this network handle
1296 * @param desc wrapper to process
1297 * @return socklen_t for sockaddr
1300 GNUNET_NETWORK_get_addrlen(const struct GNUNET_NETWORK_Handle *desc)
1302 return desc->addrlen;
1307 * Copy a native fd set
1309 * @param to destination
1310 * @param from native source set
1311 * @param nfds the biggest socket number in from + 1
1314 GNUNET_NETWORK_fdset_copy_native(struct GNUNET_NETWORK_FDSet *to,
1325 * Set a native fd in a set
1327 * @param to destination
1328 * @param nfd native FD to set
1331 GNUNET_NETWORK_fdset_set_native(struct GNUNET_NETWORK_FDSet *to,
1334 GNUNET_assert((nfd >= 0) && (nfd < FD_SETSIZE));
1335 FD_SET(nfd, &to->sds);
1336 to->nsds = GNUNET_MAX(nfd + 1,
1342 * Test native fd in a set
1344 * @param to set to test, NULL for empty set
1345 * @param nfd native FD to test, or -1 for none
1346 * @return #GNUNET_YES if FD is set in the set
1349 GNUNET_NETWORK_fdset_test_native(const struct GNUNET_NETWORK_FDSet *to,
1355 return FD_ISSET(nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1360 * Add a file handle to the fd set
1362 * @param h the file handle to add
1365 GNUNET_NETWORK_fdset_handle_set(struct GNUNET_NETWORK_FDSet *fds,
1366 const struct GNUNET_DISK_FileHandle *h)
1369 if (fds->handles_pos == fds->handles_size)
1370 GNUNET_array_grow(fds->handles,
1372 fds->handles_size * 2 + 2);
1373 fds->handles[fds->handles_pos++] = h;
1377 GNUNET_assert(GNUNET_OK ==
1378 GNUNET_DISK_internal_file_handle_(h,
1383 fds->nsds = GNUNET_MAX(fd + 1,
1390 * Add a file handle to the fd set
1392 * @param h the file handle to add
1395 GNUNET_NETWORK_fdset_handle_set_first(struct GNUNET_NETWORK_FDSet *fds,
1396 const struct GNUNET_DISK_FileHandle *h)
1399 if (fds->handles_pos == fds->handles_size)
1400 GNUNET_array_grow(fds->handles,
1402 fds->handles_size * 2 + 2);
1403 fds->handles[fds->handles_pos] = h;
1404 if (fds->handles[0] != h)
1406 const struct GNUNET_DISK_FileHandle *bak = fds->handles[0];
1407 fds->handles[0] = h;
1408 fds->handles[fds->handles_pos] = bak;
1412 GNUNET_NETWORK_fdset_handle_set(fds, h);
1418 * Check if a file handle is part of an fd set
1421 * @param h file handle
1422 * @return #GNUNET_YES if the file handle is part of the set
1425 GNUNET_NETWORK_fdset_handle_isset(const struct GNUNET_NETWORK_FDSet *fds,
1426 const struct GNUNET_DISK_FileHandle *h)
1431 for (i = 0; i < fds->handles_pos; i++)
1432 if (fds->handles[i] == h)
1436 return FD_ISSET(h->fd,
1444 * Numerically compare pointers to sort them.
1445 * Used to test for overlap in the arrays.
1447 * @param p1 a pointer
1448 * @param p2 a pointer
1449 * @return -1, 0 or 1, if the p1 < p2, p1==p2 or p1 > p2.
1452 ptr_cmp(const void *p1,
1457 if ((intptr_t)p1 < (intptr_t)p2)
1465 * Checks if two fd sets overlap
1467 * @param fds1 first fd set
1468 * @param fds2 second fd set
1469 * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1472 GNUNET_NETWORK_fdset_overlap(const struct GNUNET_NETWORK_FDSet *fds1,
1473 const struct GNUNET_NETWORK_FDSet *fds2)
1478 nfds = GNUNET_MIN(fds1->nsds,
1494 /* This code is somewhat hacky, we are not supposed to know what's
1495 * inside of fd_set; also the O(n^2) is really bad... */
1496 for (i = 0; i < fds1->sds.fd_count; i++)
1497 for (j = 0; j < fds2->sds.fd_count; j++)
1498 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1501 /* take a short cut if possible */
1502 if ((0 == fds1->handles_pos) ||
1503 (0 == fds2->handles_pos))
1506 /* Sort file handles array to avoid quadratic complexity when
1507 checking for overlap */
1508 qsort(fds1->handles,
1512 qsort(fds2->handles,
1518 while ((i < fds1->handles_pos) &&
1519 (j < fds2->handles_pos))
1521 switch (ptr_cmp(fds1->handles[i],
1543 * @return a new fd set
1545 struct GNUNET_NETWORK_FDSet *
1546 GNUNET_NETWORK_fdset_create()
1548 struct GNUNET_NETWORK_FDSet *fds;
1550 fds = GNUNET_new(struct GNUNET_NETWORK_FDSet);
1551 GNUNET_NETWORK_fdset_zero(fds);
1557 * Releases the associated memory of an fd set
1562 GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
1565 GNUNET_array_grow(fds->handles,
1577 struct _select_params {
1594 * Timeout for select().
1611 _win_socket wakeup_socket;
1614 * Set to return value from select.
1626 struct _select_params *sp = p;
1630 WaitForSingleObject(sp->standby,
1632 ResetEvent(sp->standby);
1633 sp->status = select(1,
1638 if (FD_ISSET(sp->wakeup_socket,
1641 FD_CLR(sp->wakeup_socket,
1645 SetEvent(sp->wakeup);
1651 static HANDLE hEventPipeWrite;
1653 static HANDLE hEventReadReady;
1655 static struct _select_params sp;
1657 static HANDLE select_thread;
1659 static HANDLE select_finished_event;
1661 static HANDLE select_standby_event;
1663 static _win_socket select_wakeup_socket = -1;
1665 static _win_socket select_send_socket = -1;
1667 static struct timeval select_timeout;
1671 * On W32, we actually use a thread to help with the
1672 * event loop due to W32-API limitations. This function
1673 * initializes that thread.
1676 initialize_select_thread()
1678 _win_socket select_listening_socket = -1;
1679 struct sockaddr_in s_in;
1684 select_standby_event = CreateEvent(NULL, TRUE, FALSE, NULL);
1685 select_finished_event = CreateEvent(NULL, TRUE, FALSE, NULL);
1687 select_wakeup_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1689 select_listening_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1692 res = ioctlsocket(select_wakeup_socket, FIONBIO, &p);
1693 LOG(GNUNET_ERROR_TYPE_DEBUG,
1694 "Select thread initialization: ioctlsocket() returns %d\n",
1697 alen = sizeof(s_in);
1698 s_in.sin_family = AF_INET;
1700 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1701 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1702 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1703 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1704 res = bind(select_listening_socket,
1705 (const struct sockaddr *)&s_in,
1707 LOG(GNUNET_ERROR_TYPE_DEBUG,
1708 "Select thread initialization: bind() returns %d\n",
1711 res = getsockname(select_listening_socket,
1712 (struct sockaddr *)&s_in,
1714 LOG(GNUNET_ERROR_TYPE_DEBUG,
1715 "Select thread initialization: getsockname() returns %d\n",
1718 res = listen(select_listening_socket,
1720 LOG(GNUNET_ERROR_TYPE_DEBUG,
1721 "Select thread initialization: listen() returns %d\n",
1723 res = connect(select_wakeup_socket,
1724 (const struct sockaddr *)&s_in,
1726 LOG(GNUNET_ERROR_TYPE_DEBUG,
1727 "Select thread initialization: connect() returns %d\n",
1730 select_send_socket = accept(select_listening_socket,
1731 (struct sockaddr *)&s_in,
1734 closesocket(select_listening_socket);
1736 sp.wakeup = select_finished_event;
1737 sp.standby = select_standby_event;
1738 sp.wakeup_socket = select_wakeup_socket;
1740 select_thread = CreateThread(NULL,
1751 * Test if the given @a port is available.
1753 * @param ipproto transport protocol to test (i.e. IPPROTO_TCP)
1754 * @param port port number to test
1755 * @return #GNUNET_OK if the port is available, #GNUNET_NO if not
1758 GNUNET_NETWORK_test_port_free(int ipproto,
1761 struct GNUNET_NETWORK_Handle *socket;
1764 char open_port_str[6];
1765 struct addrinfo hint;
1766 struct addrinfo *ret;
1767 struct addrinfo *ai;
1769 GNUNET_snprintf(open_port_str,
1770 sizeof(open_port_str),
1772 (unsigned int)port);
1773 socktype = (IPPROTO_TCP == ipproto) ? SOCK_STREAM : SOCK_DGRAM;
1775 memset(&hint, 0, sizeof(hint));
1776 hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
1777 hint.ai_socktype = socktype;
1778 hint.ai_protocol = ipproto;
1779 hint.ai_addrlen = 0;
1780 hint.ai_addr = NULL;
1781 hint.ai_canonname = NULL;
1782 hint.ai_next = NULL;
1783 hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
1784 GNUNET_assert(0 == getaddrinfo(NULL,
1788 bind_status = GNUNET_NO;
1789 for (ai = ret; NULL != ai; ai = ai->ai_next)
1791 socket = GNUNET_NETWORK_socket_create(ai->ai_family,
1796 bind_status = GNUNET_NETWORK_socket_bind(socket,
1799 GNUNET_NETWORK_socket_close(socket);
1800 if (GNUNET_OK != bind_status)
1810 * Check if sockets or pipes meet certain conditions
1812 * @param rfds set of sockets or pipes to be checked for readability
1813 * @param wfds set of sockets or pipes to be checked for writability
1814 * @param efds set of sockets or pipes to be checked for exceptions
1815 * @param timeout relative value when to return
1816 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1819 GNUNET_NETWORK_socket_select(struct GNUNET_NETWORK_FDSet *rfds,
1820 struct GNUNET_NETWORK_FDSet *wfds,
1821 struct GNUNET_NETWORK_FDSet *efds,
1822 const struct GNUNET_TIME_Relative timeout)
1832 nfds = GNUNET_MAX(nfds,
1835 nfds = GNUNET_MAX(nfds,
1838 (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us))
1841 LOG(GNUNET_ERROR_TYPE_ERROR,
1842 _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1845 if (timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us > (unsigned long long)LONG_MAX)
1847 tv.tv_sec = LONG_MAX;
1848 tv.tv_usec = 999999L;
1852 tv.tv_sec = (long)(timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us);
1854 (timeout.rel_value_us -
1855 (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1858 (NULL != rfds) ? &rfds->sds : NULL,
1859 (NULL != wfds) ? &wfds->sds : NULL,
1860 (NULL != efds) ? &efds->sds : NULL,
1861 (timeout.rel_value_us ==
1862 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1871 * Non-blocking test if a pipe is ready for reading.
1873 * @param fh pipe handle
1874 * @return #GNUNET_YES if the pipe is ready for reading
1877 pipe_read_ready(const struct GNUNET_DISK_FileHandle *fh)
1881 DWORD waitstatus = 0;
1884 bret = PeekNamedPipe(fh->h, NULL, 0, NULL, &waitstatus, NULL);
1885 error = GetLastError();
1888 /* TODO: either add more errors to this condition, or eliminate it
1889 * entirely (failed to peek -> pipe is in serious trouble, should
1890 * be selected as readable).
1892 if ((error != ERROR_BROKEN_PIPE) &&
1893 (error != ERROR_INVALID_HANDLE))
1896 else if (waitstatus <= 0)
1903 * Non-blocking test if a pipe is having an IO exception.
1905 * @param fh pipe handle
1906 * @return #GNUNET_YES if the pipe is having an IO exception.
1909 pipe_except_ready(const struct GNUNET_DISK_FileHandle *fh)
1913 if (PeekNamedPipe(fh->h, NULL, 0, NULL, &dwBytes, NULL))
1920 * Iterate over handles in fds, destructively rewrite the
1921 * handles array contents of fds so that it starts with the
1922 * handles that are ready, and update handles_pos accordingly.
1924 * @param fds set of handles (usually pipes) to be checked for readiness
1925 * @param except GNUNET_NO if fds should be checked for readiness to read,
1926 * GNUNET_YES if fds should be checked for exceptions
1927 * (there is no way to check for write-readiness - pipes are always write-ready)
1928 * @param set_for_sure a HANDLE that is known to be set already,
1929 * because WaitForMultipleObjects() returned its index.
1930 * @return number of ready handles
1933 check_handles_status(struct GNUNET_NETWORK_FDSet *fds,
1935 HANDLE set_for_sure)
1937 const struct GNUNET_DISK_FileHandle *fh;
1941 for (woff = 0, roff = 0; roff < fds->handles_pos; roff++)
1943 fh = fds->handles[roff];
1944 if (fh == set_for_sure)
1946 fds->handles[woff++] = fh;
1948 else if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1950 if ((except && pipe_except_ready(fh)) ||
1951 (!except && pipe_read_ready(fh)))
1952 fds->handles[woff++] = fh;
1954 else if (fh->type == GNUNET_DISK_HANLDE_TYPE_FILE)
1957 fds->handles[woff++] = fh;
1961 if (WAIT_OBJECT_0 == WaitForSingleObject(fh->h, 0))
1962 fds->handles[woff++] = fh;
1965 fds->handles_pos = woff;
1971 * Check if sockets or pipes meet certain conditions, version for W32.
1973 * @param rfds set of sockets or pipes to be checked for readability
1974 * @param wfds set of sockets or pipes to be checked for writability
1975 * @param efds set of sockets or pipes to be checked for exceptions
1976 * @param timeout relative value when to return
1977 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1980 GNUNET_NETWORK_socket_select(struct GNUNET_NETWORK_FDSet *rfds,
1981 struct GNUNET_NETWORK_FDSet *wfds,
1982 struct GNUNET_NETWORK_FDSet *efds,
1983 const struct GNUNET_TIME_Relative timeout)
1985 const struct GNUNET_DISK_FileHandle *fh;
1994 HANDLE handle_array[FD_SETSIZE + 2];
1996 int returnedpos = 0;
2006 nfds = GNUNET_MAX(nfds, rfds->nsds);
2007 handles += rfds->handles_pos;
2011 nfds = GNUNET_MAX(nfds, wfds->nsds);
2012 handles += wfds->handles_pos;
2016 nfds = GNUNET_MAX(nfds, efds->nsds);
2017 handles += efds->handles_pos;
2021 (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == timeout.rel_value_us) &&
2025 LOG(GNUNET_ERROR_TYPE_ERROR,
2026 _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
2029 #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
2030 /* calculate how long we need to wait in microseconds */
2031 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
2033 mcs_total = INFINITE;
2034 ms_rounded = INFINITE;
2038 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
2039 ms_rounded = (DWORD)(mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
2040 if (mcs_total > 0 && ms_rounded == 0)
2043 /* select() may be used as a portable way to sleep */
2044 if (!(rfds || wfds || efds))
2050 if (NULL == select_thread)
2051 initialize_select_thread();
2057 FD_COPY(&rfds->sds, &aread);
2059 FD_COPY(&wfds->sds, &awrite);
2061 FD_COPY(&efds->sds, &aexcept);
2063 /* Start by doing a fast check on sockets and pipes (without
2064 waiting). It is cheap, and is sufficient most of the time. By
2065 profiling we detected that to be true in 90% of the cases.
2068 /* Do the select now */
2069 select_timeout.tv_sec = 0;
2070 select_timeout.tv_usec = 0;
2072 /* Copy all the writes to the except, so we can detect connect() errors */
2073 for (i = 0; i < awrite.fd_count; i++)
2074 FD_SET(awrite.fd_array[i],
2076 if ((aread.fd_count > 0) ||
2077 (awrite.fd_count > 0) ||
2078 (aexcept.fd_count > 0))
2079 selectret = select(1,
2080 (NULL != rfds) ? &aread : NULL,
2081 (NULL != wfds) ? &awrite : NULL,
2086 if (-1 == selectret)
2088 /* Throw an error early on, while we still have the context. */
2089 LOG(GNUNET_ERROR_TYPE_ERROR,
2090 "W32 select(%d, %d, %d) failed: %lu\n",
2091 rfds ? aread.fd_count : 0,
2092 wfds ? awrite.fd_count : 0,
2098 /* Check aexcept, if something is in there and we copied that
2099 FD before to detect connect() errors, add it back to the
2100 write set to report errors. */
2102 for (i = 0; i < aexcept.fd_count; i++)
2103 if (FD_ISSET(aexcept.fd_array[i],
2105 FD_SET(aexcept.fd_array[i],
2109 /* If our select returned something or is a 0-timed request, then
2110 also check the pipes and get out of here! */
2111 /* Sadly, it means code duplication :( */
2112 if ((selectret > 0) || (0 == mcs_total))
2117 if (rfds && (rfds->handles_pos > 0))
2118 retcode += check_handles_status(rfds, GNUNET_NO, NULL);
2120 /* wfds handles remain untouched, on W32
2121 we pretend our pipes are "always" write-ready */
2124 if (efds && (efds->handles_pos > 0))
2125 retcode += check_handles_status(efds, GNUNET_YES, NULL);
2129 GNUNET_NETWORK_fdset_zero(rfds);
2130 if (selectret != -1)
2131 GNUNET_NETWORK_fdset_copy_native(rfds, &aread, selectret);
2135 GNUNET_NETWORK_fdset_zero(wfds);
2136 if (selectret != -1)
2137 GNUNET_NETWORK_fdset_copy_native(wfds, &awrite, selectret);
2141 GNUNET_NETWORK_fdset_zero(efds);
2142 if (selectret != -1)
2143 GNUNET_NETWORK_fdset_copy_native(efds, &aexcept, selectret);
2145 if (-1 == selectret)
2147 /* Add our select() FDs to the total return value */
2148 retcode += selectret;
2152 /* If we got this far, use slower implementation that is able to do a waiting select
2153 on both sockets and pipes simultaneously */
2155 /* Events for pipes */
2156 if (!hEventReadReady)
2157 hEventReadReady = CreateEvent(NULL, TRUE, TRUE, NULL);
2158 if (!hEventPipeWrite)
2159 hEventPipeWrite = CreateEvent(NULL, TRUE, TRUE, NULL);
2166 FD_COPY(&rfds->sds, &aread);
2168 FD_COPY(&wfds->sds, &awrite);
2170 FD_COPY(&efds->sds, &aexcept);
2171 /* We will first Add the PIPES to the events */
2172 /* Track how far in `handle_array` the read pipes go,
2173 so we may by-pass them quickly if none of them
2176 if (rfds && (rfds->handles_pos > 0))
2178 for (i = 0; i < rfds->handles_pos; i++)
2180 fh = rfds->handles[i];
2181 if (fh->type == GNUNET_DISK_HANLDE_TYPE_EVENT)
2183 handle_array[nhandles++] = fh->h;
2186 if (fh->type != GNUNET_DISK_HANLDE_TYPE_PIPE)
2188 /* Read zero bytes to check the status of the pipe */
2189 if (!ReadFile(fh->h, NULL, 0, NULL, fh->oOverlapRead))
2191 DWORD error_code = GetLastError();
2193 if (error_code == ERROR_IO_PENDING)
2195 /* add as unready */
2196 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
2202 handle_array[nhandles++] = hEventReadReady;
2208 /* error also counts as ready */
2209 handle_array[nhandles++] = hEventReadReady;
2215 if (wfds && (wfds->handles_pos > 0))
2217 LOG(GNUNET_ERROR_TYPE_DEBUG,
2218 "Adding the write ready event to the array as %d\n",
2220 handle_array[nhandles++] = hEventPipeWrite;
2226 LOG(GNUNET_ERROR_TYPE_DEBUG,
2227 "Adding the socket event to the array as %d\n",
2229 handle_array[nhandles++] = select_finished_event;
2230 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
2236 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
2237 select_timeout.tv_usec = (timeout.rel_value_us -
2238 (select_timeout.tv_sec *
2239 GNUNET_TIME_UNIT_SECONDS.rel_value_us));
2240 sp.tv = &select_timeout;
2242 FD_SET(select_wakeup_socket, &aread);
2245 i = recv(select_wakeup_socket,
2246 (char *)&returnedpos,
2254 /* Failed connections cause sockets to be set in errorfds on W32,
2255 * but on POSIX it should set them in writefds.
2256 * First copy all awrite sockets to aexcept, later we'll
2257 * check aexcept and set its contents in awrite as well
2258 * Sockets are also set in errorfds when OOB data is available,
2259 * but we don't use OOB data.
2261 for (i = 0; i < awrite.fd_count; i++)
2262 FD_SET(awrite.fd_array[i],
2264 ResetEvent(select_finished_event);
2265 SetEvent(select_standby_event);
2268 /* NULL-terminate array */
2269 handle_array[nhandles] = NULL;
2270 LOG(GNUNET_ERROR_TYPE_DEBUG,
2271 "nfds: %d, handles: %d, will wait: %llu mcs\n",
2278 = WaitForMultipleObjects(nhandles,
2282 LOG(GNUNET_ERROR_TYPE_DEBUG,
2283 "WaitForMultipleObjects Returned: %d\n",
2288 GNUNET_break(0); /* This branch shouldn't actually be executed...*/
2289 i = (int)WaitForSingleObject(select_finished_event,
2291 returncode = WAIT_TIMEOUT;
2295 /* Shouldn't come this far. If it does - investigate. */
2301 /* Don't wake up select-thread when delay is 0, it should return immediately
2302 * and wake up by itself.
2305 i = send(select_send_socket,
2306 (const char *)&returnedpos,
2309 i = (int)WaitForSingleObject(select_finished_event,
2311 LOG(GNUNET_ERROR_TYPE_DEBUG,
2312 "Finished waiting for the select thread: %d %d\n",
2319 i = recv(select_wakeup_socket,
2320 (char *)&returnedpos,
2325 /* Check aexcept, add its contents to awrite */
2326 for (i = 0; i < aexcept.fd_count; i++)
2327 FD_SET(aexcept.fd_array[i], &awrite);
2330 returnedpos = returncode - WAIT_OBJECT_0;
2331 LOG(GNUNET_ERROR_TYPE_DEBUG,
2332 "return pos is: %d\n",
2337 /* We queued a zero-long read on each pipe to check
2338 * its state, now we must cancel these read operations.
2339 * This must be done while rfds->handles_pos is still
2340 * intact and matches the number of read handles that we
2341 * got from the caller.
2343 for (i = 0; i < rfds->handles_pos; i++)
2345 fh = rfds->handles[i];
2346 if (GNUNET_DISK_HANLDE_TYPE_PIPE == fh->type)
2350 /* We may have some pipes ready for reading. */
2351 if (returnedpos < read_pipes_off)
2352 retcode += check_handles_status(rfds, GNUNET_NO, handle_array[returnedpos]);
2354 rfds->handles_pos = 0;
2356 if (-1 != sp.status)
2357 GNUNET_NETWORK_fdset_copy_native(rfds, &aread, retcode);
2361 retcode += wfds->handles_pos;
2362 /* wfds handles remain untouched */
2363 if (-1 != sp.status)
2364 GNUNET_NETWORK_fdset_copy_native(wfds, &awrite, retcode);
2368 retcode += check_handles_status(rfds,
2370 returnedpos < nhandles ? handle_array[returnedpos] : NULL);
2371 if (-1 != sp.status)
2372 GNUNET_NETWORK_fdset_copy_native(efds, &aexcept, retcode);
2376 retcode += sp.status;
2384 /* end of network.c */