ref bugnote
[oweals/gnunet.git] / src / util / network.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2013 GNUnet e.V.
4
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.
9
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.
14
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/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21 /**
22  * @file util/network.c
23  * @brief basic, low-level networking interface
24  * @author Nils Durner
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "disk.h"
30
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)
34
35 #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
36
37
38 #ifndef INVALID_SOCKET
39 #define INVALID_SOCKET -1
40 #endif
41
42
43 /**
44  * @brief handle to a socket
45  */
46 struct GNUNET_NETWORK_Handle
47 {
48 #ifndef MINGW
49   int fd;
50 #else
51   SOCKET fd;
52 #endif
53
54   /**
55    * Address family / domain.
56    */
57   int af;
58
59   /**
60    * Type of the socket
61    */
62   int type;
63
64   /**
65    * Number of bytes in addr.
66    */
67   socklen_t addrlen;
68
69   /**
70    * Address we were bound to, or NULL.
71    */
72   struct sockaddr *addr;
73
74 };
75
76
77 /**
78  * Test if the given protocol family is supported by this system.
79  *
80  * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
81  * @return #GNUNET_OK if the PF is supported
82  */
83 int
84 GNUNET_NETWORK_test_pf (int pf)
85 {
86   int s;
87
88   s = socket (pf, SOCK_STREAM, 0);
89   if (-1 == s)
90   {
91     if (EAFNOSUPPORT == errno)
92       return GNUNET_NO;
93     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
94                 "Failed to create test socket: %s\n",
95                 STRERROR (errno));
96     return GNUNET_SYSERR;
97   }
98 #if WINDOWS
99   closesocket (s);
100 #else
101   close (s);
102 #endif
103   return GNUNET_OK;
104 }
105
106
107 /**
108  * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
109  * shorten it to an acceptable length while keeping it unique
110  * and making sure it remains a valid filename (if possible).
111  *
112  * @param unixpath long path, will be freed (or same pointer returned
113  *        with moved 0-termination).
114  * @return shortened unixpath, NULL on error
115  */
116 char *
117 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
118 {
119   struct sockaddr_un dummy;
120   size_t slen;
121   char *end;
122   struct GNUNET_HashCode sh;
123   struct GNUNET_CRYPTO_HashAsciiEncoded ae;
124   size_t upm;
125
126   upm = sizeof (dummy.sun_path);
127   slen = strlen (unixpath);
128   if (slen < upm)
129     return unixpath; /* no shortening required */
130   GNUNET_CRYPTO_hash (unixpath, slen, &sh);
131   while (16 + strlen (unixpath) >= upm)
132   {
133     if (NULL == (end = strrchr (unixpath, '/')))
134     {
135       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
136                   _("Unable to shorten unix path `%s' while keeping name unique\n"),
137                   unixpath);
138       GNUNET_free (unixpath);
139       return NULL;
140     }
141     *end = '\0';
142   }
143   GNUNET_CRYPTO_hash_to_enc (&sh, &ae);
144   strncat (unixpath, (char *) ae.encoding, 16);
145   return unixpath;
146 }
147
148
149 #ifndef WINDOWS
150 /**
151  * If services crash, they can leave a unix domain socket file on the
152  * disk. This needs to be manually removed, because otherwise both
153  * bind() and connect() for the respective address will fail.  In this
154  * function, we test if such a left-over file exists, and if so,
155  * remove it (unless there is a listening service at the address).
156  *
157  * @param un unix domain socket address to check
158  */
159 void
160 GNUNET_NETWORK_unix_precheck (const struct sockaddr_un *un)
161 {
162   int s;
163   int eno;
164   struct stat sbuf;
165   int ret;
166
167   s = socket (AF_UNIX, SOCK_STREAM, 0);
168   if (-1 == s)
169   {
170     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
171                          "Failed to open AF_UNIX socket");
172     return;
173   }
174   ret = connect (s,
175                  (struct sockaddr *) un,
176                  sizeof (struct sockaddr_un));
177   eno = errno;
178   GNUNET_break (0 == close (s));
179   if (0 == ret)
180     return; /* another process is listening, do not remove! */
181   if (ECONNREFUSED != eno)
182     return; /* some other error, likely "no such file or directory" -- all well */
183   /* should unlink, but sanity checks first */
184   if (0 != stat (un->sun_path,
185                  &sbuf))
186     return; /* failed to 'stat', likely does not exist after all */
187   if (S_IFSOCK != (S_IFMT & sbuf.st_mode))
188     return; /* refuse to unlink anything except sockets */
189   /* finally, really unlink */
190   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
191               "Removing left-over `%s' from previous exeuction\n",
192               un->sun_path);
193   if (0 != unlink (un->sun_path))
194     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
195                               "unlink",
196                               un->sun_path);
197 }
198 #endif
199
200
201
202 #ifndef FD_COPY
203 #define FD_COPY(s, d) do { GNUNET_memcpy ((d), (s), sizeof (fd_set)); } while (0)
204 #endif
205
206
207 /**
208  * Set if a socket should use blocking or non-blocking IO.
209  *
210  * @param fd socket
211  * @param doBlock blocking mode
212  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
213  */
214 int
215 GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd,
216                                     int doBlock)
217 {
218
219 #if MINGW
220   u_long mode;
221
222   mode = !doBlock;
223   if (SOCKET_ERROR ==
224       ioctlsocket (fd->fd,
225                    FIONBIO,
226                    &mode))
227
228   {
229     SetErrnoFromWinsockError (WSAGetLastError ());
230     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
231                   "ioctlsocket");
232     return GNUNET_SYSERR;
233   }
234   return GNUNET_OK;
235
236 #else
237   /* not MINGW */
238   int flags = fcntl (fd->fd, F_GETFL);
239
240   if (flags == -1)
241   {
242     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
243                   "fcntl");
244     return GNUNET_SYSERR;
245   }
246   if (doBlock)
247     flags &= ~O_NONBLOCK;
248
249   else
250     flags |= O_NONBLOCK;
251   if (0 != fcntl (fd->fd,
252                   F_SETFL,
253                   flags))
254
255   {
256     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
257                   "fcntl");
258     return GNUNET_SYSERR;
259   }
260   return GNUNET_OK;
261 #endif
262 }
263
264
265 /**
266  * Make a socket non-inheritable to child processes
267  *
268  * @param h the socket to make non-inheritable
269  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
270  * @warning Not implemented on Windows
271  */
272 static int
273 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
274 {
275 #ifndef MINGW
276   int i;
277   i = fcntl (h->fd, F_GETFD);
278   if (i < 0)
279     return GNUNET_SYSERR;
280   if (i == (i | FD_CLOEXEC))
281     return GNUNET_OK;
282   i |= FD_CLOEXEC;
283   if (fcntl (h->fd, F_SETFD, i) < 0)
284     return GNUNET_SYSERR;
285 #else
286   BOOL b;
287   SetLastError (0);
288   b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
289   if (!b)
290   {
291     SetErrnoFromWinsockError (WSAGetLastError ());
292     return GNUNET_SYSERR;
293   }
294 #endif
295   return GNUNET_OK;
296 }
297
298
299 #ifdef DARWIN
300 /**
301  * The MSG_NOSIGNAL equivalent on Mac OS X
302  *
303  * @param h the socket to make non-delaying
304  */
305 static void
306 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
307 {
308   int abs_value = 1;
309
310   if (0 !=
311       setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE,
312                   (const void *) &abs_value,
313                   sizeof (abs_value)))
314     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
315 }
316 #endif
317
318
319 /**
320  * Disable delays when sending data via the socket.
321  * (GNUnet makes sure that messages are as big as
322  * possible already).
323  *
324  * @param h the socket to make non-delaying
325  */
326 static void
327 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
328 {
329 #ifndef WINDOWS
330   int value = 1;
331
332   if (0 !=
333       setsockopt (h->fd,
334                   IPPROTO_TCP,
335                   TCP_NODELAY,
336                   &value, sizeof (value)))
337     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
338                   "setsockopt");
339 #else
340   const char *abs_value = "1";
341
342   if (0 !=
343       setsockopt (h->fd,
344                   IPPROTO_TCP,
345                   TCP_NODELAY,
346                   (const void *) abs_value,
347                   sizeof (abs_value)))
348     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
349                   "setsockopt");
350 #endif
351 }
352
353
354 /**
355  * Perform proper canonical initialization for a network handle.
356  * Set it to non-blocking, make it non-inheritable to child
357  * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
358  * stream socket) and check that it is smaller than FD_SETSIZE.
359  *
360  * @param h socket to initialize
361  * @param af address family of the socket
362  * @param type socket type
363  * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
364  *         failed and the handle was destroyed
365  */
366 static int
367 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
368                            int af,
369                            int type)
370 {
371   int eno;
372
373   h->af = af;
374   h->type = type;
375   if (h->fd == INVALID_SOCKET)
376   {
377 #ifdef MINGW
378     SetErrnoFromWinsockError (WSAGetLastError ());
379 #endif
380     eno = errno;
381     GNUNET_free (h);
382     errno = eno;
383     return GNUNET_SYSERR;
384   }
385 #ifndef MINGW
386   if (h->fd >= FD_SETSIZE)
387   {
388     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
389     errno = EMFILE;
390     return GNUNET_SYSERR;
391   }
392 #endif
393   if (GNUNET_OK != socket_set_inheritable (h))
394     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
395                   "socket_set_inheritable");
396
397   if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
398   {
399     eno = errno;
400     GNUNET_break (0);
401     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
402     errno = eno;
403     return GNUNET_SYSERR;
404   }
405 #ifdef DARWIN
406   socket_set_nosigpipe (h);
407 #endif
408   if ( (type == SOCK_STREAM)
409 #ifdef AF_UNIX
410        && (af != AF_UNIX)
411 #endif
412       )
413     socket_set_nodelay (h);
414   return GNUNET_OK;
415 }
416
417
418 /**
419  * accept a new connection on a socket
420  *
421  * @param desc bound socket
422  * @param address address of the connecting peer, may be NULL
423  * @param address_len length of @a address
424  * @return client socket
425  */
426 struct GNUNET_NETWORK_Handle *
427 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
428                               struct sockaddr *address,
429                               socklen_t *address_len)
430 {
431   struct GNUNET_NETWORK_Handle *ret;
432   int eno;
433
434   ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
435 #if DEBUG_NETWORK
436   {
437     struct sockaddr_storage name;
438     socklen_t namelen = sizeof (name);
439
440     int gsn = getsockname (desc->fd,
441                            (struct sockaddr *) &name,
442                            &namelen);
443
444     if (0 == gsn)
445       LOG (GNUNET_ERROR_TYPE_DEBUG,
446            "Accepting connection on `%s'\n",
447            GNUNET_a2s ((const struct sockaddr *) &name,
448                        namelen));
449   }
450 #endif
451   ret->fd = accept (desc->fd,
452                     address,
453                     address_len);
454   if (-1 == ret->fd)
455   {
456     eno = errno;
457     GNUNET_free (ret);
458     errno = eno;
459     return NULL;
460   }
461   if (GNUNET_OK !=
462       initialize_network_handle (ret,
463                                  (NULL != address) ? address->sa_family : desc->af,
464                                  SOCK_STREAM))
465   {
466     return NULL;
467   }
468   return ret;
469 }
470
471
472 /**
473  * Bind a socket to a particular address.
474  *
475  * @param desc socket to bind
476  * @param address address to be bound
477  * @param address_len length of @a address
478  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
479  */
480 int
481 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
482                             const struct sockaddr *address,
483                             socklen_t address_len)
484 {
485   int ret;
486
487 #ifdef IPV6_V6ONLY
488 #ifdef IPPROTO_IPV6
489   {
490     const int on = 1;
491
492     if (AF_INET6 == desc->af)
493       if (setsockopt (desc->fd,
494                       IPPROTO_IPV6,
495                       IPV6_V6ONLY,
496                       (const void *) &on,
497                       sizeof (on)))
498         LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG,
499                       "setsockopt");
500   }
501 #endif
502 #endif
503 #ifndef WINDOWS
504   if (AF_UNIX == address->sa_family)
505     GNUNET_NETWORK_unix_precheck ((const struct sockaddr_un *) address);
506   {
507     const int on = 1;
508
509     /* This is required here for TCP sockets, but only on UNIX */
510     if ( (SOCK_STREAM == desc->type) &&
511          (0 != setsockopt (desc->fd,
512                            SOL_SOCKET,
513                            SO_REUSEADDR,
514                            &on, sizeof (on))))
515       LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG,
516                     "setsockopt");
517   }
518   {
519     /* set permissions of newly created non-abstract UNIX domain socket to
520        "user-only"; applications can choose to relax this later */
521     mode_t old_mask = 0; /* assigned to make compiler happy */
522     const struct sockaddr_un *un = (const struct sockaddr_un *) address;
523     int not_abstract = 0;
524
525     if ((AF_UNIX == address->sa_family)
526         && ('\0' != un->sun_path[0]) ) /* Not an abstract socket */
527       not_abstract = 1;
528     if (not_abstract)
529       old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | S_IXOTH);
530 #endif
531
532     ret = bind (desc->fd,
533                 address,
534                 address_len);
535
536 #ifndef WINDOWS
537     if (not_abstract)
538       (void) umask (old_mask);
539   }
540 #endif
541 #ifdef MINGW
542   if (SOCKET_ERROR == ret)
543     SetErrnoFromWinsockError (WSAGetLastError ());
544 #endif
545   if (0 != ret)
546     return GNUNET_SYSERR;
547 #ifndef MINGW
548   desc->addr = GNUNET_malloc (address_len);
549   GNUNET_memcpy (desc->addr, address, address_len);
550   desc->addrlen = address_len;
551 #endif
552   return GNUNET_OK;
553 }
554
555
556 /**
557  * Close a socket
558  *
559  * @param desc socket
560  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
561  */
562 int
563 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
564 {
565   int ret;
566
567 #ifdef WINDOWS
568   DWORD error = 0;
569
570   SetLastError (0);
571   ret = closesocket (desc->fd);
572   error = WSAGetLastError ();
573   SetErrnoFromWinsockError (error);
574   LOG (GNUNET_ERROR_TYPE_DEBUG,
575        "Closed 0x%x, closesocket() returned %d, GLE is %u\n",
576        desc->fd,
577        ret,
578        error);
579 #else
580   ret = close (desc->fd);
581 #endif
582 #ifndef WINDOWS
583   const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
584
585   /* Cleanup the UNIX domain socket and its parent directories in case of non
586      abstract sockets */
587   if ( (AF_UNIX == desc->af) &&
588        (NULL != desc->addr) &&
589        ('\0' != un->sun_path[0]) )
590   {
591     char *dirname = GNUNET_strndup (un->sun_path,
592                                     sizeof (un->sun_path));
593
594     if (0 != unlink (dirname))
595     {
596       LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING,
597                          "unlink",
598                          dirname);
599     }
600     else
601     {
602       size_t len;
603
604       len = strlen (dirname);
605       while ((len > 0) && (dirname[len] != DIR_SEPARATOR))
606         len--;
607       dirname[len] = '\0';
608       if ((0 != len) && (0 != rmdir (dirname)))
609       {
610         switch (errno)
611         {
612         case EACCES:
613         case ENOTEMPTY:
614         case EPERM:
615           /* these are normal and can just be ignored */
616           break;
617         default:
618           GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
619                                     "rmdir",
620                                     dirname);
621           break;
622         }
623       }
624     }
625     GNUNET_free (dirname);
626   }
627 #endif
628   GNUNET_NETWORK_socket_free_memory_only_ (desc);
629   return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
630 }
631
632
633 /**
634  * Only free memory of a socket, keep the file descriptor untouched.
635  *
636  * @param desc socket
637  */
638 void
639 GNUNET_NETWORK_socket_free_memory_only_ (struct GNUNET_NETWORK_Handle *desc)
640 {
641   GNUNET_free_non_null (desc->addr);
642   GNUNET_free (desc);
643 }
644
645
646 /**
647  * Box a native socket (and check that it is a socket).
648  *
649  * @param fd socket to box
650  * @return NULL on error (including not supported on target platform)
651  */
652 struct GNUNET_NETWORK_Handle *
653 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
654 {
655   struct GNUNET_NETWORK_Handle *ret;
656 #if MINGW
657   unsigned long i;
658   DWORD d;
659   /* FIXME: Find a better call to check that FD is valid */
660   if (0 !=
661       WSAIoctl (fd, FIONBIO,
662                 (void *) &i, sizeof (i),
663                 NULL, 0, &d,
664                 NULL, NULL))
665     return NULL;                /* invalid FD */
666   ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
667   ret->fd = fd;
668   ret->af = AF_UNSPEC;
669   return ret;
670 #else
671   if (fcntl (fd, F_GETFD) < 0)
672     return NULL;                /* invalid FD */
673   ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
674   ret->fd = fd;
675   ret->af = AF_UNSPEC;
676   return ret;
677 #endif
678 }
679
680
681 /**
682  * Connect a socket to some remote address.
683  *
684  * @param desc socket
685  * @param address peer address
686  * @param address_len length of @a address
687  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
688  */
689 int
690 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
691                                const struct sockaddr *address,
692                                socklen_t address_len)
693 {
694   int ret;
695
696   ret = connect (desc->fd,
697                  address,
698                  address_len);
699 #ifdef MINGW
700   if (SOCKET_ERROR == ret)
701   {
702     SetErrnoFromWinsockError (WSAGetLastError ());
703     if (errno == EWOULDBLOCK)
704       errno = EINPROGRESS;
705   }
706 #endif
707   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
708 }
709
710
711 /**
712  * Get socket options
713  *
714  * @param desc socket
715  * @param level protocol level of the option
716  * @param optname identifier of the option
717  * @param optval options
718  * @param optlen length of @a optval
719  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
720  */
721 int
722 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
723                                   int level,
724                                   int optname,
725                                   void *optval,
726                                   socklen_t *optlen)
727 {
728   int ret;
729
730   ret = getsockopt (desc->fd,
731                     level,
732                     optname,
733                     optval, optlen);
734
735 #ifdef MINGW
736   if ( (0 == ret) &&
737        (SOL_SOCKET == level) &&
738        (SO_ERROR == optname) )
739     *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
740   else if (SOCKET_ERROR == ret)
741     SetErrnoFromWinsockError (WSAGetLastError ());
742 #endif
743   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
744 }
745
746
747 /**
748  * Listen on a socket
749  *
750  * @param desc socket
751  * @param backlog length of the listen queue
752  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
753  */
754 int
755 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
756                               int backlog)
757 {
758   int ret;
759
760   ret = listen (desc->fd,
761                 backlog);
762 #ifdef MINGW
763   if (SOCKET_ERROR == ret)
764     SetErrnoFromWinsockError (WSAGetLastError ());
765 #endif
766   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
767 }
768
769
770 /**
771  * How much data is available to be read on this descriptor?
772  *
773  * @param desc socket
774  * @returns #GNUNET_SYSERR if no data is available, or on error!
775  */
776 ssize_t
777 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *desc)
778 {
779   int error;
780
781   /* How much is there to be read? */
782 #ifndef WINDOWS
783   int pending;
784
785   error = ioctl (desc->fd,
786                  FIONREAD,
787                  &pending);
788   if (0 == error)
789     return (ssize_t) pending;
790   return GNUNET_SYSERR;
791 #else
792   u_long pending;
793
794   error = ioctlsocket (desc->fd,
795                        FIONREAD,
796                        &pending);
797   if (error != SOCKET_ERROR)
798     return (ssize_t) pending;
799   return GNUNET_SYSERR;
800 #endif
801 }
802
803
804 /**
805  * Read data from a socket (always non-blocking).
806  *
807  * @param desc socket
808  * @param buffer buffer
809  * @param length length of @a buffer
810  * @param src_addr either the source to recv from, or all zeroes
811  *        to be filled in by recvfrom
812  * @param addrlen length of the @a src_addr
813  */
814 ssize_t
815 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
816                                 void *buffer,
817                                 size_t length,
818                                 struct sockaddr *src_addr,
819                                 socklen_t *addrlen)
820 {
821   int ret;
822   int flags;
823
824   flags = 0;
825
826 #ifdef MSG_DONTWAIT
827   flags |= MSG_DONTWAIT;
828
829 #endif
830   ret = recvfrom (desc->fd,
831                   buffer,
832                   length,
833                   flags,
834                   src_addr,
835                   addrlen);
836 #ifdef MINGW
837   if (SOCKET_ERROR == ret)
838     SetErrnoFromWinsockError (WSAGetLastError ());
839 #endif
840   return ret;
841 }
842
843
844 /**
845  * Read data from a connected socket (always non-blocking).
846  *
847  * @param desc socket
848  * @param buffer buffer
849  * @param length length of @a buffer
850  * @return number of bytes received, -1 on error
851  */
852 ssize_t
853 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle *desc,
854                             void *buffer,
855                             size_t length)
856 {
857   int ret;
858   int flags;
859
860   flags = 0;
861
862 #ifdef MSG_DONTWAIT
863   flags |= MSG_DONTWAIT;
864 #endif
865   ret = recv (desc->fd,
866               buffer,
867               length,
868               flags);
869 #ifdef MINGW
870   if (SOCKET_ERROR == ret)
871     SetErrnoFromWinsockError (WSAGetLastError ());
872 #endif
873   return ret;
874 }
875
876
877 /**
878  * Send data (always non-blocking).
879  *
880  * @param desc socket
881  * @param buffer data to send
882  * @param length size of the @a buffer
883  * @return number of bytes sent, #GNUNET_SYSERR on error
884  */
885 ssize_t
886 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle *desc,
887                             const void *buffer,
888                             size_t length)
889 {
890   int ret;
891   int flags;
892
893   flags = 0;
894 #ifdef MSG_DONTWAIT
895   flags |= MSG_DONTWAIT;
896
897 #endif
898 #ifdef MSG_NOSIGNAL
899   flags |= MSG_NOSIGNAL;
900
901 #endif
902   ret = send (desc->fd,
903               buffer,
904               length,
905               flags);
906 #ifdef MINGW
907   if (SOCKET_ERROR == ret)
908     SetErrnoFromWinsockError (WSAGetLastError ());
909
910 #endif
911   return ret;
912 }
913
914
915 /**
916  * Send data to a particular destination (always non-blocking).
917  * This function only works for UDP sockets.
918  *
919  * @param desc socket
920  * @param message data to send
921  * @param length size of the @a message
922  * @param dest_addr destination address
923  * @param dest_len length of @a address
924  * @return number of bytes sent, #GNUNET_SYSERR on error
925  */
926 ssize_t
927 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle *desc,
928                               const void *message,
929                               size_t length,
930                               const struct sockaddr *dest_addr,
931                               socklen_t dest_len)
932 {
933   int ret;
934   int flags;
935
936   flags = 0;
937
938 #ifdef MSG_DONTWAIT
939   flags |= MSG_DONTWAIT;
940 #endif
941 #ifdef MSG_NOSIGNAL
942   flags |= MSG_NOSIGNAL;
943 #endif
944   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
945 #ifdef MINGW
946   if (SOCKET_ERROR == ret)
947     SetErrnoFromWinsockError (WSAGetLastError ());
948 #endif
949   return ret;
950 }
951
952
953 /**
954  * Set socket option
955  *
956  * @param fd socket
957  * @param level protocol level of the option
958  * @param option_name option identifier
959  * @param option_value value to set
960  * @param option_len size of @a option_value
961  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
962  */
963 int
964 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd,
965                                   int level,
966                                   int option_name,
967                                   const void *option_value,
968                                   socklen_t option_len)
969 {
970   int ret;
971
972   ret = setsockopt (fd->fd,
973                     level,
974                     option_name,
975                     option_value,
976                     option_len);
977 #ifdef MINGW
978   if (SOCKET_ERROR == ret)
979     SetErrnoFromWinsockError (WSAGetLastError ());
980 #endif
981   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
982 }
983
984
985 /**
986  * Create a new socket.  Configure it for non-blocking IO and
987  * mark it as non-inheritable to child processes (set the
988  * close-on-exec flag).
989  *
990  * @param domain domain of the socket
991  * @param type socket type
992  * @param protocol network protocol
993  * @return new socket, NULL on error
994  */
995 struct GNUNET_NETWORK_Handle *
996 GNUNET_NETWORK_socket_create (int domain,
997                               int type,
998                               int protocol)
999 {
1000   struct GNUNET_NETWORK_Handle *ret;
1001   int fd;
1002
1003   fd = socket (domain, type, protocol);
1004   if (-1 == fd)
1005     return NULL;
1006   ret = GNUNET_new (struct GNUNET_NETWORK_Handle);
1007   ret->fd = fd;
1008   if (GNUNET_OK !=
1009       initialize_network_handle (ret,
1010                                  domain,
1011                                  type))
1012     return NULL;
1013   return ret;
1014 }
1015
1016
1017 /**
1018  * Shut down socket operations
1019  * @param desc socket
1020  * @param how type of shutdown
1021  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1022  */
1023 int
1024 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc,
1025                                 int how)
1026 {
1027   int ret;
1028
1029   ret = shutdown (desc->fd, how);
1030 #ifdef MINGW
1031   if (0 != ret)
1032     SetErrnoFromWinsockError (WSAGetLastError ());
1033 #endif
1034   return (0 == ret) ? GNUNET_OK : GNUNET_SYSERR;
1035 }
1036
1037
1038 /**
1039  * Disable the "CORK" feature for communication with the given socket,
1040  * forcing the OS to immediately flush the buffer on transmission
1041  * instead of potentially buffering multiple messages.  Essentially
1042  * reduces the OS send buffers to zero.
1043  *
1044  * @param desc socket
1045  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
1046  */
1047 int
1048 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
1049 {
1050   int ret = 0;
1051
1052 #if WINDOWS
1053   int value = 0;
1054
1055   if (0 !=
1056       (ret =
1057        setsockopt (desc->fd,
1058                    SOL_SOCKET,
1059                    SO_SNDBUF,
1060                    (char *) &value,
1061                    sizeof (value))))
1062     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
1063                   "setsockopt");
1064   if (0 !=
1065       (ret =
1066        setsockopt (desc->fd,
1067                    SOL_SOCKET,
1068                    SO_RCVBUF,
1069                    (char *) &value,
1070                    sizeof (value))))
1071     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
1072                   "setsockopt");
1073 #elif LINUX
1074   int value = 0;
1075
1076   if (0 !=
1077       (ret =
1078        setsockopt (desc->fd,
1079                    SOL_SOCKET,
1080                    SO_SNDBUF,
1081                    &value,
1082                    sizeof (value))))
1083     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
1084                   "setsockopt");
1085   if (0 !=
1086       (ret =
1087        setsockopt (desc->fd,
1088                    SOL_SOCKET,
1089                    SO_RCVBUF,
1090                    &value,
1091                    sizeof (value))))
1092     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
1093                   "setsockopt");
1094 #endif
1095   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
1096 }
1097
1098
1099 /**
1100  * Reset FD set
1101  *
1102  * @param fds fd set
1103  */
1104 void
1105 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
1106 {
1107   FD_ZERO (&fds->sds);
1108   fds->nsds = 0;
1109 #ifdef MINGW
1110   fds->handles_pos = 0;
1111 #endif
1112 }
1113
1114
1115 /**
1116  * Add a socket to the FD set
1117  *
1118  * @param fds fd set
1119  * @param desc socket to add
1120  */
1121 void
1122 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
1123                           const struct GNUNET_NETWORK_Handle *desc)
1124 {
1125   FD_SET (desc->fd,
1126           &fds->sds);
1127   fds->nsds = GNUNET_MAX (fds->nsds,
1128                           desc->fd + 1);
1129 }
1130
1131
1132 /**
1133  * Check whether a socket is part of the fd set
1134  *
1135  * @param fds fd set
1136  * @param desc socket
1137  * @return 0 if the FD is not set
1138  */
1139 int
1140 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
1141                             const struct GNUNET_NETWORK_Handle *desc)
1142 {
1143   return FD_ISSET (desc->fd,
1144                    &fds->sds);
1145 }
1146
1147
1148 /**
1149  * Add one fd set to another
1150  *
1151  * @param dst the fd set to add to
1152  * @param src the fd set to add from
1153  */
1154 void
1155 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
1156                           const struct GNUNET_NETWORK_FDSet *src)
1157 {
1158 #ifndef MINGW
1159   int nfds;
1160
1161   for (nfds = src->nsds; nfds >= 0; nfds--)
1162     if (FD_ISSET (nfds, &src->sds))
1163       FD_SET (nfds, &dst->sds);
1164   dst->nsds = GNUNET_MAX (dst->nsds,
1165                           src->nsds);
1166 #else
1167   /* This is MinGW32-specific implementation that relies on the code that
1168    * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
1169    * that fd being added is not already in the set.
1170    * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
1171    *
1172    * NOTE: I don't understand why the UNIX-logic wouldn't work
1173    * for the first part here as well. -CG
1174    */
1175   unsigned int i;
1176
1177   for (i = 0; i < src->sds.fd_count; i++)
1178     FD_SET (src->sds.fd_array[i],
1179             &dst->sds);
1180   dst->nsds = GNUNET_MAX (src->nsds,
1181                           dst->nsds);
1182
1183   /* also copy over `struct GNUNET_DISK_FileHandle` array */
1184   if (dst->handles_pos + src->handles_pos > dst->handles_size)
1185     GNUNET_array_grow (dst->handles,
1186                        dst->handles_size,
1187                        ((dst->handles_pos + src->handles_pos) << 1));
1188   for (i = 0; i < src->handles_pos; i++)
1189     dst->handles[dst->handles_pos++] = src->handles[i];
1190 #endif
1191 }
1192
1193
1194 /**
1195  * Copy one fd set to another
1196  *
1197  * @param to destination
1198  * @param from source
1199  */
1200 void
1201 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
1202                            const struct GNUNET_NETWORK_FDSet *from)
1203 {
1204   FD_COPY (&from->sds,
1205            &to->sds);
1206   to->nsds = from->nsds;
1207 #ifdef MINGW
1208   if (from->handles_pos > to->handles_size)
1209     GNUNET_array_grow (to->handles,
1210                        to->handles_size,
1211                        from->handles_pos * 2);
1212   GNUNET_memcpy (to->handles,
1213                  from->handles,
1214                  from->handles_pos * sizeof (struct GNUNET_NETWORK_Handle *));
1215   to->handles_pos = from->handles_pos;
1216 #endif
1217 }
1218
1219
1220 /**
1221  * Return file descriptor for this network handle
1222  *
1223  * @param desc wrapper to process
1224  * @return POSIX file descriptor
1225  */
1226 int
1227 GNUNET_NETWORK_get_fd (const struct GNUNET_NETWORK_Handle *desc)
1228 {
1229   return desc->fd;
1230 }
1231
1232
1233 /**
1234  * Return sockaddr for this network handle
1235  *
1236  * @param desc wrapper to process
1237  * @return sockaddr
1238  */
1239 struct sockaddr*
1240 GNUNET_NETWORK_get_addr (const struct GNUNET_NETWORK_Handle *desc)
1241 {
1242   return desc->addr;
1243 }
1244
1245
1246 /**
1247  * Return sockaddr length for this network handle
1248  *
1249  * @param desc wrapper to process
1250  * @return socklen_t for sockaddr
1251  */
1252 socklen_t
1253 GNUNET_NETWORK_get_addrlen (const struct GNUNET_NETWORK_Handle *desc)
1254 {
1255   return desc->addrlen;
1256 }
1257
1258
1259 /**
1260  * Copy a native fd set
1261  *
1262  * @param to destination
1263  * @param from native source set
1264  * @param nfds the biggest socket number in from + 1
1265  */
1266 void
1267 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1268                                   const fd_set *from,
1269                                   int nfds)
1270 {
1271   FD_COPY (from,
1272            &to->sds);
1273   to->nsds = nfds;
1274 }
1275
1276
1277 /**
1278  * Set a native fd in a set
1279  *
1280  * @param to destination
1281  * @param nfd native FD to set
1282  */
1283 void
1284 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to,
1285                                  int nfd)
1286 {
1287   GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1288   FD_SET (nfd, &to->sds);
1289   to->nsds = GNUNET_MAX (nfd + 1,
1290                          to->nsds);
1291 }
1292
1293
1294 /**
1295  * Test native fd in a set
1296  *
1297  * @param to set to test, NULL for empty set
1298  * @param nfd native FD to test, or -1 for none
1299  * @return #GNUNET_YES if FD is set in the set
1300  */
1301 int
1302 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1303                                   int nfd)
1304 {
1305   if ( (-1 == nfd) ||
1306        (NULL == to) )
1307     return GNUNET_NO;
1308   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1309 }
1310
1311
1312 /**
1313  * Add a file handle to the fd set
1314  * @param fds fd set
1315  * @param h the file handle to add
1316  */
1317 void
1318 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1319                                  const struct GNUNET_DISK_FileHandle *h)
1320 {
1321 #ifdef MINGW
1322   if (fds->handles_pos == fds->handles_size)
1323     GNUNET_array_grow (fds->handles,
1324                        fds->handles_size,
1325                        fds->handles_size * 2 + 2);
1326   fds->handles[fds->handles_pos++] = h;
1327 #else
1328   int fd;
1329
1330   GNUNET_assert (GNUNET_OK ==
1331                  GNUNET_DISK_internal_file_handle_ (h,
1332                                                     &fd,
1333                                                     sizeof (int)));
1334   FD_SET (fd,
1335           &fds->sds);
1336   fds->nsds = GNUNET_MAX (fd + 1,
1337                           fds->nsds);
1338 #endif
1339 }
1340
1341
1342 /**
1343  * Add a file handle to the fd set
1344  * @param fds fd set
1345  * @param h the file handle to add
1346  */
1347 void
1348 GNUNET_NETWORK_fdset_handle_set_first (struct GNUNET_NETWORK_FDSet *fds,
1349                                        const struct GNUNET_DISK_FileHandle *h)
1350 {
1351 #ifdef MINGW
1352   if (fds->handles_pos == fds->handles_size)
1353     GNUNET_array_grow (fds->handles,
1354                        fds->handles_size,
1355                        fds->handles_size * 2 + 2);
1356   fds->handles[fds->handles_pos] = h;
1357   if (fds->handles[0] != h)
1358   {
1359     const struct GNUNET_DISK_FileHandle *bak = fds->handles[0];
1360     fds->handles[0] = h;
1361     fds->handles[fds->handles_pos] = bak;
1362   }
1363   fds->handles_pos++;
1364 #else
1365   GNUNET_NETWORK_fdset_handle_set (fds, h);
1366 #endif
1367 }
1368
1369
1370 /**
1371  * Check if a file handle is part of an fd set
1372  *
1373  * @param fds fd set
1374  * @param h file handle
1375  * @return #GNUNET_YES if the file handle is part of the set
1376  */
1377 int
1378 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1379                                    const struct GNUNET_DISK_FileHandle *h)
1380 {
1381 #ifdef MINGW
1382   unsigned int i;
1383
1384   for (i=0;i<fds->handles_pos;i++)
1385     if (fds->handles[i] == h)
1386       return GNUNET_YES;
1387   return GNUNET_NO;
1388 #else
1389   return FD_ISSET (h->fd,
1390                    &fds->sds);
1391 #endif
1392 }
1393
1394
1395 #ifdef MINGW
1396 /**
1397  * Numerically compare pointers to sort them.
1398  * Used to test for overlap in the arrays.
1399  *
1400  * @param p1 a pointer
1401  * @param p2 a pointer
1402  * @return -1, 0 or 1, if the p1 < p2, p1==p2 or p1 > p2.
1403  */
1404 static int
1405 ptr_cmp (const void *p1,
1406          const void *p2)
1407 {
1408   if (p1 == p2)
1409     return 0;
1410   if ((intptr_t) p1 < (intptr_t) p2)
1411     return -1;
1412   return 1;
1413 }
1414 #endif
1415
1416
1417 /**
1418  * Checks if two fd sets overlap
1419  *
1420  * @param fds1 first fd set
1421  * @param fds2 second fd set
1422  * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1423  */
1424 int
1425 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1426                               const struct GNUNET_NETWORK_FDSet *fds2)
1427 {
1428 #ifndef MINGW
1429   int nfds;
1430
1431   nfds = GNUNET_MIN (fds1->nsds,
1432                      fds2->nsds);
1433   while (nfds > 0)
1434   {
1435     nfds--;
1436     if ( (FD_ISSET (nfds,
1437                     &fds1->sds)) &&
1438          (FD_ISSET (nfds,
1439                     &fds2->sds)) )
1440       return GNUNET_YES;
1441   }
1442   return GNUNET_NO;
1443 #else
1444   unsigned int i;
1445   unsigned int j;
1446
1447   /* This code is somewhat hacky, we are not supposed to know what's
1448    * inside of fd_set; also the O(n^2) is really bad... */
1449   for (i = 0; i < fds1->sds.fd_count; i++)
1450     for (j = 0; j < fds2->sds.fd_count; j++)
1451       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1452         return GNUNET_YES;
1453
1454   /* take a short cut if possible */
1455   if ( (0 == fds1->handles_pos) ||
1456        (0 == fds2->handles_pos) )
1457     return GNUNET_NO;
1458
1459   /* Sort file handles array to avoid quadratic complexity when
1460      checking for overlap */
1461   qsort (fds1->handles,
1462          fds1->handles_pos,
1463          sizeof (void *),
1464          &ptr_cmp);
1465   qsort (fds2->handles,
1466          fds2->handles_pos,
1467          sizeof (void *),
1468          &ptr_cmp);
1469   i = 0;
1470   j = 0;
1471   while ( (i < fds1->handles_pos) &&
1472           (j < fds2->handles_pos) )
1473   {
1474     switch (ptr_cmp (fds1->handles[i],
1475                      fds2->handles[j]))
1476     {
1477     case -1:
1478       i++;
1479       break;
1480     case 0:
1481       return GNUNET_YES;
1482     case 1:
1483       j++;
1484     }
1485   }
1486   return GNUNET_NO;
1487 #endif
1488 }
1489
1490
1491 /**
1492  * Creates an fd set
1493  *
1494  * @return a new fd set
1495  */
1496 struct GNUNET_NETWORK_FDSet *
1497 GNUNET_NETWORK_fdset_create ()
1498 {
1499   struct GNUNET_NETWORK_FDSet *fds;
1500
1501   fds = GNUNET_new (struct GNUNET_NETWORK_FDSet);
1502   GNUNET_NETWORK_fdset_zero (fds);
1503   return fds;
1504 }
1505
1506
1507 /**
1508  * Releases the associated memory of an fd set
1509  *
1510  * @param fds fd set
1511  */
1512 void
1513 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1514 {
1515 #ifdef MINGW
1516   GNUNET_array_grow (fds->handles,
1517                      fds->handles_size,
1518                      0);
1519 #endif
1520   GNUNET_free (fds);
1521 }
1522
1523
1524 #if MINGW
1525 /**
1526  * FIXME.
1527  */
1528 struct _select_params
1529 {
1530   /**
1531    * Read set.
1532    */
1533   fd_set *r;
1534
1535   /**
1536    * Write set.
1537    */
1538   fd_set *w;
1539
1540   /**
1541    * Except set.
1542    */
1543   fd_set *e;
1544
1545   /**
1546    * Timeout for select().
1547    */
1548   struct timeval *tv;
1549
1550   /**
1551    * FIXME.
1552    */
1553   HANDLE wakeup;
1554
1555   /**
1556    * FIXME.
1557    */
1558   HANDLE standby;
1559
1560   /**
1561    * FIXME.
1562    */
1563   SOCKET wakeup_socket;
1564
1565   /**
1566    * Set to return value from select.
1567    */
1568   int status;
1569 };
1570
1571
1572 /**
1573  * FIXME.
1574  */
1575 static DWORD WINAPI
1576 _selector (LPVOID p)
1577 {
1578   struct _select_params *sp = p;
1579
1580   while (1)
1581   {
1582     WaitForSingleObject (sp->standby,
1583                          INFINITE);
1584     ResetEvent (sp->standby);
1585     sp->status = select (1,
1586                          sp->r,
1587                          sp->w,
1588                          sp->e,
1589                          sp->tv);
1590     if (FD_ISSET (sp->wakeup_socket,
1591                   sp->r))
1592     {
1593       FD_CLR (sp->wakeup_socket,
1594               sp->r);
1595       sp->status -= 1;
1596     }
1597     SetEvent (sp->wakeup);
1598   }
1599   return 0;
1600 }
1601
1602
1603 static HANDLE hEventPipeWrite;
1604
1605 static HANDLE hEventReadReady;
1606
1607 static struct _select_params sp;
1608
1609 static HANDLE select_thread;
1610
1611 static HANDLE select_finished_event;
1612
1613 static HANDLE select_standby_event;
1614
1615 static SOCKET select_wakeup_socket = -1;
1616
1617 static SOCKET select_send_socket = -1;
1618
1619 static struct timeval select_timeout;
1620
1621
1622 /**
1623  * On W32, we actually use a thread to help with the
1624  * event loop due to W32-API limitations.  This function
1625  * initializes that thread.
1626  */
1627 static void
1628 initialize_select_thread ()
1629 {
1630   SOCKET select_listening_socket = -1;
1631   struct sockaddr_in s_in;
1632   int alen;
1633   int res;
1634   unsigned long p;
1635
1636   select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1637   select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1638
1639   select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1640
1641   select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1642
1643   p = 1;
1644   res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1645   LOG (GNUNET_ERROR_TYPE_DEBUG,
1646        "Select thread initialization: ioctlsocket() returns %d\n",
1647        res);
1648
1649   alen = sizeof (s_in);
1650   s_in.sin_family = AF_INET;
1651   s_in.sin_port = 0;
1652   s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1653   s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1654   s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1655   s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1656   res = bind (select_listening_socket,
1657               (const struct sockaddr *) &s_in,
1658               sizeof (s_in));
1659   LOG (GNUNET_ERROR_TYPE_DEBUG,
1660        "Select thread initialization: bind() returns %d\n",
1661        res);
1662
1663   res = getsockname (select_listening_socket,
1664                      (struct sockaddr *) &s_in,
1665                      &alen);
1666   LOG (GNUNET_ERROR_TYPE_DEBUG,
1667        "Select thread initialization: getsockname() returns %d\n",
1668        res);
1669
1670   res = listen (select_listening_socket,
1671                 SOMAXCONN);
1672   LOG (GNUNET_ERROR_TYPE_DEBUG,
1673        "Select thread initialization: listen() returns %d\n",
1674        res);
1675   res = connect (select_wakeup_socket,
1676                  (const struct sockaddr *) &s_in,
1677                  sizeof (s_in));
1678   LOG (GNUNET_ERROR_TYPE_DEBUG,
1679        "Select thread initialization: connect() returns %d\n",
1680        res);
1681
1682   select_send_socket = accept (select_listening_socket,
1683                                (struct sockaddr *) &s_in,
1684                                &alen);
1685
1686   closesocket (select_listening_socket);
1687
1688   sp.wakeup = select_finished_event;
1689   sp.standby = select_standby_event;
1690   sp.wakeup_socket = select_wakeup_socket;
1691
1692   select_thread = CreateThread (NULL,
1693                                 0,
1694                                 _selector,
1695                                 &sp,
1696                                 0, NULL);
1697 }
1698
1699
1700 #endif
1701
1702 /**
1703  * Test if the given @a port is available.
1704  *
1705  * @param ipproto transport protocol to test (i.e. IPPROTO_TCP)
1706  * @param port port number to test
1707  * @return #GNUNET_OK if the port is available, #GNUNET_NO if not
1708  */
1709 int
1710 GNUNET_NETWORK_test_port_free (int ipproto,
1711                                uint16_t port)
1712 {
1713   struct GNUNET_NETWORK_Handle *socket;
1714   int bind_status;
1715   int socktype;
1716   char open_port_str[6];
1717   struct addrinfo hint;
1718   struct addrinfo *ret;
1719   struct addrinfo *ai;
1720
1721   GNUNET_snprintf (open_port_str,
1722                    sizeof (open_port_str),
1723                    "%u",
1724                    (unsigned int) port);
1725   socktype = (IPPROTO_TCP == ipproto) ? SOCK_STREAM : SOCK_DGRAM;
1726   ret = NULL;
1727   memset (&hint, 0, sizeof (hint));
1728   hint.ai_family = AF_UNSPEC; /* IPv4 and IPv6 */
1729   hint.ai_socktype = socktype;
1730   hint.ai_protocol = ipproto;
1731   hint.ai_addrlen = 0;
1732   hint.ai_addr = NULL;
1733   hint.ai_canonname = NULL;
1734   hint.ai_next = NULL;
1735   hint.ai_flags = AI_PASSIVE | AI_NUMERICSERV; /* Wild card address */
1736   GNUNET_assert (0 == getaddrinfo (NULL,
1737                                    open_port_str,
1738                                    &hint,
1739                                    &ret));
1740   bind_status = GNUNET_NO;
1741   for (ai = ret; NULL != ai; ai = ai->ai_next)
1742   {
1743     socket = GNUNET_NETWORK_socket_create (ai->ai_family,
1744                                            ai->ai_socktype,
1745                                            ai->ai_protocol);
1746     if (NULL == socket)
1747       continue;
1748     bind_status = GNUNET_NETWORK_socket_bind (socket,
1749                                               ai->ai_addr,
1750                                               ai->ai_addrlen);
1751     GNUNET_NETWORK_socket_close (socket);
1752     if (GNUNET_OK != bind_status)
1753       break;
1754   }
1755   freeaddrinfo (ret);
1756   return bind_status;
1757 }
1758
1759
1760 #ifndef MINGW
1761 /**
1762  * Check if sockets or pipes meet certain conditions
1763  *
1764  * @param rfds set of sockets or pipes to be checked for readability
1765  * @param wfds set of sockets or pipes to be checked for writability
1766  * @param efds set of sockets or pipes to be checked for exceptions
1767  * @param timeout relative value when to return
1768  * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1769  */
1770 int
1771 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1772                               struct GNUNET_NETWORK_FDSet *wfds,
1773                               struct GNUNET_NETWORK_FDSet *efds,
1774                               const struct GNUNET_TIME_Relative timeout)
1775 {
1776   int nfds;
1777   struct timeval tv;
1778
1779   if (NULL != rfds)
1780     nfds = rfds->nsds;
1781   else
1782     nfds = 0;
1783   if (NULL != wfds)
1784     nfds = GNUNET_MAX (nfds,
1785                        wfds->nsds);
1786   if (NULL != efds)
1787     nfds = GNUNET_MAX (nfds,
1788                        efds->nsds);
1789   if ((0 == nfds) &&
1790       (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us))
1791   {
1792     GNUNET_break (0);
1793     LOG (GNUNET_ERROR_TYPE_ERROR,
1794          _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1795          "select");
1796   }
1797   if (timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us > (unsigned long long) LONG_MAX)
1798   {
1799     tv.tv_sec = LONG_MAX;
1800     tv.tv_usec = 999999L;
1801   }
1802   else
1803   {
1804     tv.tv_sec = (long) (timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us);
1805     tv.tv_usec =
1806       (timeout.rel_value_us -
1807        (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1808   }
1809   return select (nfds,
1810                  (NULL != rfds) ? &rfds->sds : NULL,
1811                  (NULL != wfds) ? &wfds->sds : NULL,
1812                  (NULL != efds) ? &efds->sds : NULL,
1813                  (timeout.rel_value_us ==
1814                   GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1815 }
1816
1817
1818 #else
1819 /* MINGW */
1820
1821
1822 /**
1823  * Non-blocking test if a pipe is ready for reading.
1824  *
1825  * @param fh pipe handle
1826  * @return #GNUNET_YES if the pipe is ready for reading
1827  */
1828 static int
1829 pipe_read_ready (const struct GNUNET_DISK_FileHandle *fh)
1830 {
1831   DWORD error;
1832   BOOL bret;
1833   DWORD waitstatus = 0;
1834
1835   SetLastError (0);
1836   bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1837   error = GetLastError ();
1838   if (0 == bret)
1839   {
1840     /* TODO: either add more errors to this condition, or eliminate it
1841      * entirely (failed to peek -> pipe is in serious trouble, should
1842      * be selected as readable).
1843      */
1844     if ( (error != ERROR_BROKEN_PIPE) &&
1845          (error != ERROR_INVALID_HANDLE) )
1846       return GNUNET_NO;
1847   }
1848   else if (waitstatus <= 0)
1849     return GNUNET_NO;
1850   return GNUNET_YES;
1851 }
1852
1853
1854 /**
1855  * Non-blocking test if a pipe is having an IO exception.
1856  *
1857  * @param fh pipe handle
1858  * @return #GNUNET_YES if the pipe is having an IO exception.
1859  */
1860 static int
1861 pipe_except_ready (const struct GNUNET_DISK_FileHandle *fh)
1862 {
1863   DWORD dwBytes;
1864
1865   if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1866     return GNUNET_NO;
1867   return GNUNET_YES;
1868 }
1869
1870
1871 /**
1872  * Iterate over handles in fds, destructively rewrite the
1873  * handles array contents of fds so that it starts with the
1874  * handles that are ready, and update handles_pos accordingly.
1875  *
1876  * @param fds set of handles (usually pipes) to be checked for readiness
1877  * @param except GNUNET_NO if fds should be checked for readiness to read,
1878  * GNUNET_YES if fds should be checked for exceptions
1879  * (there is no way to check for write-readiness - pipes are always write-ready)
1880  * @param set_for_sure a HANDLE that is known to be set already,
1881  * because WaitForMultipleObjects() returned its index.
1882  * @return number of ready handles
1883  */
1884 static int
1885 check_handles_status (struct GNUNET_NETWORK_FDSet *fds,
1886                       int except,
1887                       HANDLE set_for_sure)
1888 {
1889   const struct GNUNET_DISK_FileHandle *fh;
1890   unsigned int roff;
1891   unsigned int woff;
1892
1893   for (woff = 0, roff = 0; roff < fds->handles_pos; roff++)
1894   {
1895     fh = fds->handles[roff];
1896     if (fh == set_for_sure)
1897     {
1898       fds->handles[woff++] = fh;
1899     }
1900     else if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1901     {
1902       if ((except && pipe_except_ready (fh)) ||
1903           (!except && pipe_read_ready (fh)))
1904         fds->handles[woff++] = fh;
1905     }
1906     else if (fh->type == GNUNET_DISK_HANLDE_TYPE_FILE)
1907     {
1908       if (!except)
1909         fds->handles[woff++] = fh;
1910     }
1911     else
1912     {
1913       if (WAIT_OBJECT_0 == WaitForSingleObject (fh->h, 0))
1914         fds->handles[woff++] = fh;
1915     }
1916   }
1917   fds->handles_pos = woff;
1918   return woff;
1919 }
1920
1921
1922 /**
1923  * Check if sockets or pipes meet certain conditions, version for W32.
1924  *
1925  * @param rfds set of sockets or pipes to be checked for readability
1926  * @param wfds set of sockets or pipes to be checked for writability
1927  * @param efds set of sockets or pipes to be checked for exceptions
1928  * @param timeout relative value when to return
1929  * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1930  */
1931 int
1932 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1933                               struct GNUNET_NETWORK_FDSet *wfds,
1934                               struct GNUNET_NETWORK_FDSet *efds,
1935                               const struct GNUNET_TIME_Relative timeout)
1936 {
1937   const struct GNUNET_DISK_FileHandle *fh;
1938   int nfds;
1939   int handles;
1940   unsigned int i;
1941   int retcode;
1942   uint64_t mcs_total;
1943   DWORD ms_rounded;
1944   int nhandles = 0;
1945   int read_pipes_off;
1946   HANDLE handle_array[FD_SETSIZE + 2];
1947   int returncode;
1948   int returnedpos = 0;
1949   int selectret;
1950   fd_set aread;
1951   fd_set awrite;
1952   fd_set aexcept;
1953
1954   nfds = 0;
1955   handles = 0;
1956   if (NULL != rfds)
1957   {
1958     nfds = GNUNET_MAX (nfds, rfds->nsds);
1959     handles += rfds->handles_pos;
1960   }
1961   if (NULL != wfds)
1962   {
1963     nfds = GNUNET_MAX (nfds, wfds->nsds);
1964     handles += wfds->handles_pos;
1965   }
1966   if (NULL != efds)
1967   {
1968     nfds = GNUNET_MAX (nfds, efds->nsds);
1969     handles += efds->handles_pos;
1970   }
1971
1972   if ((0 == nfds) &&
1973       (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == timeout.rel_value_us) &&
1974       (0 == handles) )
1975   {
1976     GNUNET_break (0);
1977     LOG (GNUNET_ERROR_TYPE_ERROR,
1978          _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1979          "select");
1980   }
1981 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1982   /* calculate how long we need to wait in microseconds */
1983   if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1984   {
1985     mcs_total = INFINITE;
1986     ms_rounded = INFINITE;
1987   }
1988   else
1989   {
1990     mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1991     ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1992     if (mcs_total > 0 && ms_rounded == 0)
1993       ms_rounded = 1;
1994   }
1995   /* select() may be used as a portable way to sleep */
1996   if (! (rfds || wfds || efds))
1997   {
1998     Sleep (ms_rounded);
1999     return 0;
2000   }
2001
2002   if (NULL == select_thread)
2003     initialize_select_thread ();
2004
2005   FD_ZERO (&aread);
2006   FD_ZERO (&awrite);
2007   FD_ZERO (&aexcept);
2008   if (rfds)
2009     FD_COPY (&rfds->sds, &aread);
2010   if (wfds)
2011     FD_COPY (&wfds->sds, &awrite);
2012   if (efds)
2013     FD_COPY (&efds->sds, &aexcept);
2014
2015   /* Start by doing a fast check on sockets and pipes (without
2016      waiting). It is cheap, and is sufficient most of the time.  By
2017      profiling we detected that to be true in 90% of the cases.
2018   */
2019
2020   /* Do the select now */
2021   select_timeout.tv_sec = 0;
2022   select_timeout.tv_usec = 0;
2023
2024   /* Copy all the writes to the except, so we can detect connect() errors */
2025   for (i = 0; i < awrite.fd_count; i++)
2026     FD_SET (awrite.fd_array[i],
2027             &aexcept);
2028   if ( (aread.fd_count > 0) ||
2029        (awrite.fd_count > 0) ||
2030        (aexcept.fd_count > 0) )
2031     selectret = select (1,
2032                         (NULL != rfds) ? &aread : NULL,
2033                         (NULL != wfds) ? &awrite : NULL,
2034                         &aexcept,
2035                         &select_timeout);
2036   else
2037     selectret = 0;
2038   if (-1 == selectret)
2039   {
2040     /* Throw an error early on, while we still have the context. */
2041     LOG (GNUNET_ERROR_TYPE_ERROR,
2042          "W32 select(%d, %d, %d) failed: %lu\n",
2043          rfds ? aread.fd_count : 0,
2044          wfds ? awrite.fd_count : 0,
2045          aexcept.fd_count,
2046          GetLastError ());
2047     GNUNET_assert (0);
2048   }
2049
2050   /* Check aexcept, if something is in there and we copied that
2051      FD before to detect connect() errors, add it back to the
2052      write set to report errors. */
2053   if (NULL != wfds)
2054     for (i = 0; i < aexcept.fd_count; i++)
2055       if (FD_ISSET (aexcept.fd_array[i],
2056                     &wfds->sds))
2057         FD_SET (aexcept.fd_array[i],
2058                 &awrite);
2059
2060
2061   /* If our select returned something or is a 0-timed request, then
2062      also check the pipes and get out of here! */
2063   /* Sadly, it means code duplication :( */
2064   if ( (selectret > 0) || (0 == mcs_total) )
2065   {
2066     retcode = 0;
2067
2068     /* Read Pipes */
2069     if (rfds && (rfds->handles_pos > 0))
2070       retcode += check_handles_status (rfds, GNUNET_NO, NULL);
2071
2072     /* wfds handles remain untouched, on W32
2073        we pretend our pipes are "always" write-ready */
2074
2075     /* except pipes */
2076     if (efds && (efds->handles_pos > 0))
2077       retcode += check_handles_status (efds, GNUNET_YES, NULL);
2078
2079     if (rfds)
2080     {
2081       GNUNET_NETWORK_fdset_zero (rfds);
2082       if (selectret != -1)
2083         GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
2084     }
2085     if (wfds)
2086     {
2087       GNUNET_NETWORK_fdset_zero (wfds);
2088       if (selectret != -1)
2089         GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
2090     }
2091     if (efds)
2092     {
2093       GNUNET_NETWORK_fdset_zero (efds);
2094       if (selectret != -1)
2095         GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
2096     }
2097     if (-1 == selectret)
2098       return -1;
2099     /* Add our select() FDs to the total return value */
2100     retcode += selectret;
2101     return retcode;
2102   }
2103
2104   /* If we got this far, use slower implementation that is able to do a waiting select
2105      on both sockets and pipes simultaneously */
2106
2107   /* Events for pipes */
2108   if (! hEventReadReady)
2109     hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
2110   if (! hEventPipeWrite)
2111     hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
2112   retcode = 0;
2113
2114   FD_ZERO (&aread);
2115   FD_ZERO (&awrite);
2116   FD_ZERO (&aexcept);
2117   if (rfds)
2118     FD_COPY (&rfds->sds, &aread);
2119   if (wfds)
2120     FD_COPY (&wfds->sds, &awrite);
2121   if (efds)
2122     FD_COPY (&efds->sds, &aexcept);
2123   /* We will first Add the PIPES to the events */
2124   /* Track how far in `handle_array` the read pipes go,
2125      so we may by-pass them quickly if none of them
2126      are selected. */
2127   read_pipes_off = 0;
2128   if (rfds && (rfds->handles_pos > 0))
2129   {
2130     for (i = 0; i <rfds->handles_pos; i++)
2131     {
2132       fh = rfds->handles[i];
2133       if (fh->type == GNUNET_DISK_HANLDE_TYPE_EVENT)
2134       {
2135         handle_array[nhandles++] = fh->h;
2136         continue;
2137       }
2138       if (fh->type != GNUNET_DISK_HANLDE_TYPE_PIPE)
2139         continue;
2140       /* Read zero bytes to check the status of the pipe */
2141       if (! ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
2142       {
2143         DWORD error_code = GetLastError ();
2144
2145         if (error_code == ERROR_IO_PENDING)
2146         {
2147           /* add as unready */
2148           handle_array[nhandles++] = fh->oOverlapRead->hEvent;
2149           read_pipes_off++;
2150         }
2151         else
2152         {
2153           /* add as ready */
2154           handle_array[nhandles++] = hEventReadReady;
2155           read_pipes_off++;
2156         }
2157       }
2158       else
2159       {
2160         /* error also counts as ready */
2161         handle_array[nhandles++] = hEventReadReady;
2162         read_pipes_off++;
2163       }
2164     }
2165   }
2166
2167   if (wfds && (wfds->handles_pos > 0))
2168   {
2169     LOG (GNUNET_ERROR_TYPE_DEBUG,
2170          "Adding the write ready event to the array as %d\n",
2171          nhandles);
2172     handle_array[nhandles++] = hEventPipeWrite;
2173   }
2174
2175   sp.status = 0;
2176   if (nfds > 0)
2177   {
2178     LOG (GNUNET_ERROR_TYPE_DEBUG,
2179          "Adding the socket event to the array as %d\n",
2180          nhandles);
2181     handle_array[nhandles++] = select_finished_event;
2182     if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
2183     {
2184       sp.tv = NULL;
2185     }
2186     else
2187     {
2188       select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
2189       select_timeout.tv_usec = (timeout.rel_value_us -
2190                                 (select_timeout.tv_sec *
2191                                  GNUNET_TIME_UNIT_SECONDS.rel_value_us));
2192       sp.tv = &select_timeout;
2193     }
2194     FD_SET (select_wakeup_socket, &aread);
2195     do
2196     {
2197       i = recv (select_wakeup_socket,
2198                 (char *) &returnedpos,
2199                 1,
2200                 0);
2201     } while (i == 1);
2202     sp.r = &aread;
2203     sp.w = &awrite;
2204     sp.e = &aexcept;
2205     /* Failed connections cause sockets to be set in errorfds on W32,
2206      * but on POSIX it should set them in writefds.
2207      * First copy all awrite sockets to aexcept, later we'll
2208      * check aexcept and set its contents in awrite as well
2209      * Sockets are also set in errorfds when OOB data is available,
2210      * but we don't use OOB data.
2211      */
2212     for (i = 0; i < awrite.fd_count; i++)
2213       FD_SET (awrite.fd_array[i],
2214               &aexcept);
2215     ResetEvent (select_finished_event);
2216     SetEvent (select_standby_event);
2217   }
2218
2219   /* NULL-terminate array */
2220   handle_array[nhandles] = NULL;
2221   LOG (GNUNET_ERROR_TYPE_DEBUG,
2222        "nfds: %d, handles: %d, will wait: %llu mcs\n",
2223        nfds,
2224        nhandles,
2225        mcs_total);
2226   if (nhandles)
2227   {
2228     returncode
2229       = WaitForMultipleObjects (nhandles,
2230                                 handle_array,
2231                                 FALSE,
2232                                 ms_rounded);
2233     LOG (GNUNET_ERROR_TYPE_DEBUG,
2234          "WaitForMultipleObjects Returned: %d\n",
2235          returncode);
2236   }
2237   else if (nfds > 0)
2238   {
2239     GNUNET_break (0); /* This branch shouldn't actually be executed...*/
2240     i = (int) WaitForSingleObject (select_finished_event,
2241                                    INFINITE);
2242     returncode = WAIT_TIMEOUT;
2243   }
2244   else
2245   {
2246     /* Shouldn't come this far. If it does - investigate. */
2247     GNUNET_assert (0);
2248   }
2249
2250   if (nfds > 0)
2251   {
2252     /* Don't wake up select-thread when delay is 0, it should return immediately
2253      * and wake up by itself.
2254      */
2255     if (0 != mcs_total)
2256       i = send (select_send_socket,
2257                 (const char *) &returnedpos,
2258                 1,
2259                 0);
2260     i = (int) WaitForSingleObject (select_finished_event,
2261                                    INFINITE);
2262     LOG (GNUNET_ERROR_TYPE_DEBUG,
2263          "Finished waiting for the select thread: %d %d\n",
2264          i,
2265          sp.status);
2266     if (0 != mcs_total)
2267     {
2268       do
2269       {
2270         i = recv (select_wakeup_socket,
2271                   (char *) &returnedpos,
2272                   1, 0);
2273       } while (1 == i);
2274     }
2275     /* Check aexcept, add its contents to awrite */
2276     for (i = 0; i < aexcept.fd_count; i++)
2277       FD_SET (aexcept.fd_array[i], &awrite);
2278   }
2279
2280   returnedpos = returncode - WAIT_OBJECT_0;
2281   LOG (GNUNET_ERROR_TYPE_DEBUG,
2282        "return pos is: %d\n",
2283        returnedpos);
2284
2285   if (rfds)
2286   {
2287     /* We queued a zero-long read on each pipe to check
2288      * its state, now we must cancel these read operations.
2289      * This must be done while rfds->handles_pos is still
2290      * intact and matches the number of read handles that we
2291      * got from the caller.
2292      */
2293     for (i = 0; i < rfds->handles_pos; i++)
2294     {
2295       fh = rfds->handles[i];
2296       if (GNUNET_DISK_HANLDE_TYPE_PIPE == fh->type)
2297         CancelIo (fh->h);
2298     }
2299
2300     /* We may have some pipes ready for reading. */
2301     if (returnedpos < read_pipes_off)
2302       retcode += check_handles_status (rfds, GNUNET_NO, handle_array[returnedpos]);
2303     else
2304       rfds->handles_pos = 0;
2305
2306     if (-1 != sp.status)
2307       GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
2308   }
2309   if (wfds)
2310   {
2311     retcode += wfds->handles_pos;
2312     /* wfds handles remain untouched */
2313     if (-1 != sp.status)
2314       GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
2315   }
2316   if (efds)
2317   {
2318     retcode += check_handles_status (rfds,
2319                                      GNUNET_YES,
2320                                      returnedpos < nhandles ? handle_array[returnedpos] : NULL);
2321     if (-1 != sp.status)
2322       GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
2323   }
2324
2325   if (sp.status > 0)
2326     retcode += sp.status;
2327
2328   return retcode;
2329 }
2330
2331 /* MINGW */
2332 #endif
2333
2334 /* end of network.c */