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