trying to fix #3006, libltdl detection on FreeBSD
[oweals/gnunet.git] / src / util / network.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009-2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
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 "disk.h"
29 #include "gnunet_util_lib.h"
30
31 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
32 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
33 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
34
35 #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
36
37
38 #ifndef INVALID_SOCKET
39 #define INVALID_SOCKET -1
40 #endif
41
42
43 struct GNUNET_NETWORK_Handle
44 {
45 #ifndef MINGW
46   int fd;
47 #else
48   SOCKET fd;
49 #endif
50
51   /**
52    * Address family / domain.
53    */
54   int af;
55
56   /**
57    * Type of the socket
58    */
59   int type;
60
61   /**
62    * Number of bytes in addr.
63    */
64   socklen_t addrlen;
65
66   /**
67    * Address we were bound to, or NULL.
68    */
69   struct sockaddr *addr;
70
71 };
72
73
74 /**
75  * Test if the given protocol family is supported by this system.
76  *
77  * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
78  * @return #GNUNET_OK if the PF is supported
79  */
80 int
81 GNUNET_NETWORK_test_pf (int pf)
82 {
83   int s;
84
85   s = socket (pf, SOCK_STREAM, 0);
86   if (-1 == s)
87   {
88     if (EAFNOSUPPORT == errno)
89       return GNUNET_NO;
90     fprintf (stderr, "Failed to create test socket: %s\n", STRERROR (errno));
91     return GNUNET_SYSERR;
92   }
93 #if WINDOWS
94   closesocket (s);
95 #else
96   close (s);
97 #endif
98   return GNUNET_OK;
99 }
100
101
102 /**
103  * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
104  * shorten it to an acceptable length while keeping it unique
105  * and making sure it remains a valid filename (if possible).
106  *
107  * @param unixpath long path, will be freed (or same pointer returned
108  *        with moved 0-termination).
109  * @return shortened unixpath, NULL on error
110  */
111 char *
112 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
113 {
114   struct sockaddr_un dummy;
115   size_t slen;
116   char *end;
117   struct GNUNET_HashCode sh;
118   struct GNUNET_CRYPTO_HashAsciiEncoded ae;
119   size_t upm;
120
121   upm = sizeof (dummy.sun_path);   
122   slen = strlen (unixpath);
123   if (slen < upm)
124     return unixpath; /* no shortening required */
125   GNUNET_CRYPTO_hash (unixpath, slen, &sh);
126   while (sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 
127          strlen (unixpath) >= upm)
128   {
129     if (NULL == (end = strrchr (unixpath, '/')))
130     {
131       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
132                   _("Unable to shorten unix path `%s' while keeping name unique\n"),
133                   unixpath);
134       GNUNET_free (unixpath);
135       return NULL;
136     }
137     *end = '\0';
138   }
139   GNUNET_CRYPTO_hash_to_enc (&sh, &ae);
140   strcat (unixpath, (char*) ae.encoding);
141   return unixpath;
142 }
143
144
145 #ifndef FD_COPY
146 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
147 #endif
148
149
150 /**
151  * Set if a socket should use blocking or non-blocking IO.
152  *
153  * @param fd socket
154  * @param doBlock blocking mode
155  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
156  */
157 int
158 GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
159 {
160
161 #if MINGW
162   u_long mode;
163
164   mode = !doBlock;
165   if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
166
167   {
168     SetErrnoFromWinsockError (WSAGetLastError ());
169     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
170     return GNUNET_SYSERR;
171   }
172   return GNUNET_OK;
173
174 #else
175   /* not MINGW */
176   int flags = fcntl (fd->fd, F_GETFL);
177
178   if (flags == -1)
179
180   {
181     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
182     return GNUNET_SYSERR;
183   }
184   if (doBlock)
185     flags &= ~O_NONBLOCK;
186
187   else
188     flags |= O_NONBLOCK;
189   if (0 != fcntl (fd->fd, F_SETFL, flags))
190
191   {
192     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
193     return GNUNET_SYSERR;
194   }
195   return GNUNET_OK;
196 #endif
197 }
198
199
200 /**
201  * Make a socket non-inheritable to child processes
202  *
203  * @param h the socket to make non-inheritable
204  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
205  * @warning Not implemented on Windows
206  */
207 static int
208 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
209 {
210 #ifndef MINGW
211   int i;
212   i = fcntl (h->fd, F_GETFD);
213   if (i < 0)
214     return GNUNET_SYSERR;
215   if (i == (i | FD_CLOEXEC))
216     return GNUNET_OK;
217   i |= FD_CLOEXEC;
218   if (fcntl (h->fd, F_SETFD, i) < 0)
219     return GNUNET_SYSERR;
220 #else
221   BOOL b;
222   SetLastError (0);
223   b = SetHandleInformation ((HANDLE) h->fd, HANDLE_FLAG_INHERIT, 0);
224   if (!b)
225   {
226     SetErrnoFromWinsockError (WSAGetLastError ());
227     return GNUNET_SYSERR;
228   }
229 #endif
230   return GNUNET_OK;
231 }
232
233
234 #ifdef DARWIN
235 /**
236  * The MSG_NOSIGNAL equivalent on Mac OS X
237  *
238  * @param h the socket to make non-delaying
239  */
240 static void
241 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
242 {
243   int abs_value = 1;
244
245   if (0 !=
246       setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, 
247                   (const void *) &abs_value,
248                   sizeof (abs_value)))
249     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
250 }
251 #endif
252
253
254 /**
255  * Disable delays when sending data via the socket.
256  * (GNUnet makes sure that messages are as big as
257  * possible already).
258  *
259  * @param h the socket to make non-delaying
260  */
261 static void
262 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
263 {
264 #ifndef WINDOWS
265   int value = 1;
266
267   if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
268     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
269 #else
270   const char *abs_value = "1";
271
272   if (0 !=
273       setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, 
274                   (const void *) abs_value,
275                   sizeof (abs_value)))
276     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
277 #endif
278 }
279
280
281 /**
282  * Perform proper canonical initialization for a network handle.
283  * Set it to non-blocking, make it non-inheritable to child
284  * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
285  * stream socket) and check that it is smaller than FD_SETSIZE.
286  *
287  * @param h socket to initialize
288  * @param af address family of the socket
289  * @param type socket type
290  * @return #GNUNET_OK on success, #GNUNET_SYSERR if initialization
291  *         failed and the handle was destroyed
292  */
293 static int
294 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
295                            int af, int type)
296 {
297   h->af = af;
298   h->type = type;
299   if (h->fd == INVALID_SOCKET)
300   {
301 #ifdef MINGW
302     SetErrnoFromWinsockError (WSAGetLastError ());
303 #endif
304     GNUNET_free (h);
305     return GNUNET_SYSERR;
306   }
307 #ifndef MINGW
308   if (h->fd >= FD_SETSIZE)
309   {
310     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
311     errno = EMFILE;
312     return GNUNET_SYSERR;
313   }
314 #endif
315   if (GNUNET_OK != socket_set_inheritable (h))
316     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
317                   "socket_set_inheritable");
318
319   if (GNUNET_SYSERR == GNUNET_NETWORK_socket_set_blocking (h, GNUNET_NO))
320   {
321     GNUNET_break (0);
322     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
323     return GNUNET_SYSERR;
324   }
325 #ifdef DARWIN
326   socket_set_nosigpipe (h);
327 #endif
328   if ( (type == SOCK_STREAM) 
329 #ifdef AF_UNIX
330        && (af != AF_UNIX)
331 #endif
332        )
333     socket_set_nodelay (h);
334   return GNUNET_OK;
335 }
336
337
338 /**
339  * accept a new connection on a socket
340  *
341  * @param desc bound socket
342  * @param address address of the connecting peer, may be NULL
343  * @param address_len length of address
344  * @return client socket
345  */
346 struct GNUNET_NETWORK_Handle *
347 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
348                               struct sockaddr *address, socklen_t * address_len)
349 {
350   struct GNUNET_NETWORK_Handle *ret;
351
352   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
353 #if DEBUG_NETWORK
354   {
355     struct sockaddr name;
356     socklen_t namelen = sizeof (name);
357     int gsn = getsockname (desc->fd, &name, &namelen);
358
359     if (gsn == 0)
360       LOG (GNUNET_ERROR_TYPE_DEBUG, "Accepting connection on `%s'\n",
361            GNUNET_a2s (&name, namelen));
362   }
363 #endif
364   ret->fd = accept (desc->fd, address, address_len);
365   if (GNUNET_OK != initialize_network_handle (ret,
366                                               (NULL != address) ? address->sa_family : desc->af,
367                                               SOCK_STREAM))
368     return NULL;
369   return ret;
370 }
371
372
373 /**
374  * Bind a socket to a particular address.
375  *
376  * @param desc socket to bind
377  * @param address address to be bound
378  * @param address_len length of address
379  * @param flags flags affecting bind behaviour
380  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
381  */
382 int
383 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
384                             const struct sockaddr *address,
385                             socklen_t address_len,
386                             int flags)
387 {
388   int ret;
389
390 #ifdef IPV6_V6ONLY
391 #ifdef IPPROTO_IPV6
392   {
393     const int on = 1;
394
395     if (desc->af == AF_INET6)
396       if (setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, 
397                       (const void *) &on, 
398                       sizeof (on)))
399         LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
400   }
401 #endif
402 #endif
403 #ifndef WINDOWS
404   {
405     const int on = 1;
406   
407     /* This is required here for TCP sockets, but only on UNIX */
408     if ((SOCK_STREAM == desc->type) 
409         && (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on))))
410       LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
411   }
412 #endif
413 #ifndef LINUX
414 #ifndef MINGW
415   if (address->sa_family == AF_UNIX && (flags & GNUNET_BIND_EXCLUSIVE) == 0)
416   {
417     const struct sockaddr_un *un = (const struct sockaddr_un *) address;
418
419     (void) unlink (un->sun_path);
420   }
421 #endif
422 #endif
423   ret = bind (desc->fd, address, address_len);
424 #ifdef MINGW
425   if (SOCKET_ERROR == ret)
426     SetErrnoFromWinsockError (WSAGetLastError ());
427 #endif
428   if (ret != 0)
429     return GNUNET_SYSERR;
430 #ifndef MINGW
431 #ifndef LINUX
432   desc->addr = GNUNET_malloc (address_len);
433   memcpy (desc->addr, address, address_len);
434   desc->addrlen = address_len;
435 #endif
436 #endif
437   return GNUNET_OK;
438 }
439
440
441 /**
442  * Close a socket
443  *
444  * @param desc socket
445  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
446  */
447 int
448 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
449 {
450   int ret;
451
452 #ifdef MINGW
453   DWORD error = 0;
454
455   SetLastError (0);
456   ret = closesocket (desc->fd);
457   error = WSAGetLastError ();
458   SetErrnoFromWinsockError (error);
459   LOG (GNUNET_ERROR_TYPE_DEBUG,
460        "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
461        error);
462 #else
463   ret = close (desc->fd);
464 #endif
465 #ifndef LINUX
466 #ifndef MINGW
467   if ((desc->af == AF_UNIX) && (NULL != desc->addr))
468   {
469     const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
470
471     if (0 != unlink (un->sun_path))
472       LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
473   }
474 #endif
475 #endif
476   GNUNET_free_non_null (desc->addr);
477   GNUNET_free (desc);
478   return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
479 }
480
481
482 /**
483  * Box a native socket (and check that it is a socket).
484  *
485  * @param fd socket to box
486  * @return NULL on error (including not supported on target platform)
487  */
488 struct GNUNET_NETWORK_Handle *
489 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
490 {
491   struct GNUNET_NETWORK_Handle *ret;
492 #if MINGW
493   unsigned long i;
494   DWORD d;
495   /* FIXME: Find a better call to check that FD is valid */
496   if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
497     return NULL;                /* invalid FD */
498   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
499   ret->fd = fd;
500   ret->af = AF_UNSPEC;
501   return ret;
502 #else
503   if (fcntl (fd, F_GETFD) < 0)
504     return NULL;                /* invalid FD */
505   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
506   ret->fd = fd;
507   ret->af = AF_UNSPEC;
508   return ret;
509 #endif
510 }
511
512
513 /**
514  * Connect a socket to some remote address.
515  *
516  * @param desc socket
517  * @param address peer address
518  * @param address_len length of address
519  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
520  */
521 int
522 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
523                                const struct sockaddr *address,
524                                socklen_t address_len)
525 {
526   int ret;
527
528   ret = connect (desc->fd, address, address_len);
529
530 #ifdef MINGW
531   if (SOCKET_ERROR == ret)
532   {
533     SetErrnoFromWinsockError (WSAGetLastError ());
534     if (errno == EWOULDBLOCK)
535       errno = EINPROGRESS;
536   }
537 #endif
538   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
539 }
540
541
542 /**
543  * Get socket options
544  *
545  * @param desc socket
546  * @param level protocol level of the option
547  * @param optname identifier of the option
548  * @param optval options
549  * @param optlen length of optval
550  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
551  */
552 int
553 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
554                                   int level, int optname, void *optval,
555                                   socklen_t * optlen)
556 {
557   int ret;
558
559   ret = getsockopt (desc->fd, level, optname, optval, optlen);
560
561 #ifdef MINGW
562   if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
563     *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
564
565   else if (SOCKET_ERROR == ret)
566     SetErrnoFromWinsockError (WSAGetLastError ());
567 #endif
568   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
569 }
570
571
572 /**
573  * Listen on a socket
574  *
575  * @param desc socket
576  * @param backlog length of the listen queue
577  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
578  */
579 int
580 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
581                               int backlog)
582 {
583   int ret;
584
585   ret = listen (desc->fd, backlog);
586
587 #ifdef MINGW
588   if (SOCKET_ERROR == ret)
589     SetErrnoFromWinsockError (WSAGetLastError ());
590
591 #endif
592   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
593 }
594
595
596 /**
597  * How much data is available to be read on this descriptor?
598  *
599  * @param desc socket
600  * @returns #GNUNET_NO if no data is available, or on error!
601  */
602 ssize_t
603 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
604                                        desc)
605 {
606   int error;
607
608   /* How much is there to be read? */
609 #ifndef WINDOWS
610   int pending;
611
612   error = ioctl (desc->fd, FIONREAD, &pending);
613   if (error == 0)
614     return (ssize_t) pending;
615   return GNUNET_NO;
616 #else
617   u_long pending;
618
619   error = ioctlsocket (desc->fd, FIONREAD, &pending);
620   if (error != SOCKET_ERROR)
621     return (ssize_t) pending;
622   return GNUNET_NO;
623 #endif
624 }
625
626
627 /**
628  * Read data from a socket (always non-blocking).
629  *
630  * @param desc socket
631  * @param buffer buffer
632  * @param length length of buffer
633  * @param src_addr either the source to recv from, or all zeroes
634  *        to be filled in by recvfrom
635  * @param addrlen length of the addr
636  */
637 ssize_t
638 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle *desc,
639                                 void *buffer, size_t length,
640                                 struct sockaddr *src_addr, socklen_t *addrlen)
641 {
642   int ret;
643   int flags;
644
645   flags = 0;
646
647 #ifdef MSG_DONTWAIT
648   flags |= MSG_DONTWAIT;
649
650 #endif
651   ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
652 #ifdef MINGW
653   if (SOCKET_ERROR == ret)
654     SetErrnoFromWinsockError (WSAGetLastError ());
655 #endif
656   return ret;
657 }
658
659
660 /**
661  * Read data from a connected socket (always non-blocking).
662  *
663  * @param desc socket
664  * @param buffer buffer
665  * @param length length of buffer
666  */
667 ssize_t
668 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
669                             void *buffer, size_t length)
670 {
671   int ret;
672   int flags;
673
674   flags = 0;
675
676 #ifdef MSG_DONTWAIT
677   flags |= MSG_DONTWAIT;
678 #endif
679   ret = recv (desc->fd, buffer, length, flags);
680 #ifdef MINGW
681   if (SOCKET_ERROR == ret)
682     SetErrnoFromWinsockError (WSAGetLastError ());
683 #endif
684   return ret;
685 }
686
687
688 /**
689  * Send data (always non-blocking).
690  *
691  * @param desc socket
692  * @param buffer data to send
693  * @param length size of the buffer
694  * @return number of bytes sent, GNUNET_SYSERR on error
695  */
696 ssize_t
697 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
698                             const void *buffer, size_t length)
699 {
700   int ret;
701   int flags;
702
703   flags = 0;
704
705 #ifdef MSG_DONTWAIT
706   flags |= MSG_DONTWAIT;
707
708 #endif
709 #ifdef MSG_NOSIGNAL
710   flags |= MSG_NOSIGNAL;
711
712 #endif
713   ret = send (desc->fd, buffer, length, flags);
714
715 #ifdef MINGW
716   if (SOCKET_ERROR == ret)
717     SetErrnoFromWinsockError (WSAGetLastError ());
718
719 #endif
720   return ret;
721 }
722
723
724 /**
725  * Send data to a particular destination (always non-blocking).
726  * This function only works for UDP sockets.
727  *
728  * @param desc socket
729  * @param message data to send
730  * @param length size of the data
731  * @param dest_addr destination address
732  * @param dest_len length of address
733  * @return number of bytes sent, #GNUNET_SYSERR on error
734  */
735 ssize_t
736 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
737                               const void *message, size_t length,
738                               const struct sockaddr * dest_addr,
739                               socklen_t dest_len)
740 {
741   int ret;
742   int flags;
743
744   flags = 0;
745
746 #ifdef MSG_DONTWAIT
747   flags |= MSG_DONTWAIT;
748 #endif
749 #ifdef MSG_NOSIGNAL
750   flags |= MSG_NOSIGNAL;
751 #endif
752   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
753 #ifdef MINGW
754   if (SOCKET_ERROR == ret)
755     SetErrnoFromWinsockError (WSAGetLastError ());
756 #endif
757   return ret;
758 }
759
760
761 /**
762  * Set socket option
763  *
764  * @param fd socket
765  * @param level protocol level of the option
766  * @param option_name option identifier
767  * @param option_value value to set
768  * @param option_len size of option_value
769  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
770  */
771 int
772 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
773                                   int option_name, const void *option_value,
774                                   socklen_t option_len)
775 {
776   int ret;
777
778   ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
779 #ifdef MINGW
780   if (SOCKET_ERROR == ret)
781     SetErrnoFromWinsockError (WSAGetLastError ());
782 #endif
783   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
784 }
785
786
787 /**
788  * Create a new socket.  Configure it for non-blocking IO and
789  * mark it as non-inheritable to child processes (set the
790  * close-on-exec flag).
791  *
792  * @param domain domain of the socket
793  * @param type socket type
794  * @param protocol network protocol
795  * @return new socket, NULL on error
796  */
797 struct GNUNET_NETWORK_Handle *
798 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
799 {
800   struct GNUNET_NETWORK_Handle *ret;
801
802   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
803   ret->fd = socket (domain, type, protocol);
804   if (GNUNET_OK !=
805       initialize_network_handle (ret, domain, type))
806     return NULL;
807   return ret;
808 }
809
810
811 /**
812  * Shut down socket operations
813  * @param desc socket
814  * @param how type of shutdown
815  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
816  */
817 int
818 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
819 {
820   int ret;
821
822   ret = shutdown (desc->fd, how);
823 #ifdef MINGW
824   if (ret != 0)
825     SetErrnoFromWinsockError (WSAGetLastError ());
826 #endif
827   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
828 }
829
830
831 /**
832  * Disable the "CORK" feature for communication with the given socket,
833  * forcing the OS to immediately flush the buffer on transmission
834  * instead of potentially buffering multiple messages.  Essentially
835  * reduces the OS send buffers to zero.
836  *
837  * @param desc socket
838  * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
839  */
840 int
841 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
842 {
843   int ret = 0;
844
845 #if WINDOWS
846   int value = 0;
847
848   if (0 !=
849       (ret =
850        setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
851                    sizeof (value))))
852     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
853   if (0 !=
854       (ret =
855        setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
856                    sizeof (value))))
857     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
858 #elif LINUX
859   int value = 0;
860
861   if (0 !=
862       (ret =
863        setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
864     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
865   if (0 !=
866       (ret =
867        setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
868     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
869 #endif
870   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
871 }
872
873
874 /**
875  * Reset FD set
876  *
877  * @param fds fd set
878  */
879 void
880 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
881 {
882   FD_ZERO (&fds->sds);
883   fds->nsds = 0;
884 #ifdef MINGW
885   GNUNET_CONTAINER_slist_clear (fds->handles);
886 #endif
887 }
888
889
890 /**
891  * Add a socket to the FD set
892  *
893  * @param fds fd set
894  * @param desc socket to add
895  */
896 void
897 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
898                           const struct GNUNET_NETWORK_Handle *desc)
899 {
900   FD_SET (desc->fd, &fds->sds);
901   if (desc->fd + 1 > fds->nsds)
902     fds->nsds = desc->fd + 1;
903 }
904
905
906 /**
907  * Check whether a socket is part of the fd set
908  *
909  * @param fds fd set
910  * @param desc socket
911  * @return 0 if the FD is not set
912  */
913 int
914 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
915                             const struct GNUNET_NETWORK_Handle *desc)
916 {
917   return FD_ISSET (desc->fd, &fds->sds);
918 }
919
920
921 /**
922  * Add one fd set to another
923  *
924  * @param dst the fd set to add to
925  * @param src the fd set to add from
926  */
927 void
928 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
929                           const struct GNUNET_NETWORK_FDSet *src)
930 {
931 #ifndef MINGW
932   int nfds;
933
934   for (nfds = src->nsds; nfds > 0; nfds--)
935     if (FD_ISSET (nfds, &src->sds))
936
937     {
938       FD_SET (nfds, &dst->sds);
939       if (nfds + 1 > dst->nsds)
940         dst->nsds = nfds + 1;
941     }
942 #else
943   /* This is MinGW32-specific implementation that relies on the code that
944    * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
945    * that fd being added is not already in the set.
946    * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
947    */
948   int i;
949   for (i = 0; i < src->sds.fd_count; i++)
950     FD_SET (src->sds.fd_array[i], &dst->sds);
951   if (src->nsds > dst->nsds)
952     dst->nsds = src->nsds;
953
954   GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
955 #endif
956 }
957
958
959 /**
960  * Copy one fd set to another
961  *
962  * @param to destination
963  * @param from source
964  */
965 void
966 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
967                            const struct GNUNET_NETWORK_FDSet *from)
968 {
969   FD_COPY (&from->sds, &to->sds);
970   to->nsds = from->nsds;
971
972 #ifdef MINGW
973   GNUNET_CONTAINER_slist_clear (to->handles);
974   GNUNET_CONTAINER_slist_append (to->handles, from->handles);
975 #endif
976 }
977
978
979 /**
980  * Return file descriptor for this network handle
981  *
982  * @param desc wrapper to process
983  * @return POSIX file descriptor
984  */
985 int
986 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
987 {
988   return desc->fd;
989 }
990
991
992 /**
993  * Return sockaddr for this network handle
994  *
995  * @param desc wrapper to process
996  * @return sockaddr
997  */
998 struct sockaddr*
999 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
1000 {
1001   return desc->addr;
1002 }
1003
1004
1005 /**
1006  * Return sockaddr length for this network handle
1007  *
1008  * @param desc wrapper to process
1009  * @return socklen_t for sockaddr
1010  */
1011 socklen_t
1012 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1013 {
1014   return desc->addrlen;
1015 }
1016
1017
1018 /**
1019  * Copy a native fd set
1020  *
1021  * @param to destination
1022  * @param from native source set
1023  * @param nfds the biggest socket number in from + 1
1024  */
1025 void
1026 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1027                                   const fd_set * from, int nfds)
1028 {
1029   FD_COPY (from, &to->sds);
1030   to->nsds = nfds;
1031 }
1032
1033
1034 /**
1035  * Set a native fd in a set
1036  *
1037  * @param to destination
1038  * @param nfd native FD to set
1039  */
1040 void
1041 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1042 {
1043   GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1044   FD_SET (nfd, &to->sds);
1045   to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1046 }
1047
1048
1049 /**
1050  * Test native fd in a set
1051  *
1052  * @param to set to test, NULL for empty set
1053  * @param nfd native FD to test, or -1 for none
1054  * @return #GNUNET_YES if FD is set in the set
1055  */
1056 int
1057 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1058                                   int nfd)
1059 {
1060   if ((nfd == -1) || (to == NULL))
1061     return GNUNET_NO;
1062   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1063 }
1064
1065
1066 /**
1067  * Add a file handle to the fd set
1068  * @param fds fd set
1069  * @param h the file handle to add
1070  */
1071 void
1072 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1073                                  const struct GNUNET_DISK_FileHandle *h)
1074 {
1075 #ifdef MINGW
1076   GNUNET_CONTAINER_slist_add (fds->handles,
1077                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1078                               sizeof (struct GNUNET_DISK_FileHandle));
1079
1080 #else
1081   int fd;
1082
1083   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1084   FD_SET (fd, &fds->sds);
1085   if (fd + 1 > fds->nsds)
1086     fds->nsds = fd + 1;
1087
1088 #endif
1089 }
1090
1091
1092 /**
1093  * Check if a file handle is part of an fd set
1094  * @param fds fd set
1095  * @param h file handle
1096  * @return #GNUNET_YES if the file handle is part of the set
1097  */
1098 int
1099 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1100                                    const struct GNUNET_DISK_FileHandle *h)
1101 {
1102
1103 #ifdef MINGW
1104   return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1105                                           sizeof (struct
1106                                                   GNUNET_DISK_FileHandle));
1107 #else
1108   return FD_ISSET (h->fd, &fds->sds);
1109 #endif
1110 }
1111
1112
1113 /**
1114  * Checks if two fd sets overlap
1115  * @param fds1 first fd set
1116  * @param fds2 second fd set
1117  * @return #GNUNET_YES if they do overlap, #GNUNET_NO otherwise
1118  */
1119 int
1120 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1121                               const struct GNUNET_NETWORK_FDSet *fds2)
1122 {
1123 #ifndef MINGW
1124   int nfds;
1125
1126   nfds = fds1->nsds;
1127   if (nfds > fds2->nsds)
1128     nfds = fds2->nsds;
1129   while (nfds > 0)
1130   {
1131     nfds--;
1132     if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1133       return GNUNET_YES;
1134   }
1135 #else
1136   struct GNUNET_CONTAINER_SList_Iterator it;
1137   struct GNUNET_DISK_FileHandle *h;
1138   int i;
1139   int j;
1140
1141   /*This code is somewhat hacky, we are not supposed to know what's
1142    * inside of fd_set; also the O(n^2) is really bad... */
1143
1144   for (i = 0; i < fds1->sds.fd_count; i++)
1145   {
1146     for (j = 0; j < fds2->sds.fd_count; j++)
1147     {
1148       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1149         return GNUNET_YES;
1150     }
1151   }
1152   it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1153   while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1154   {
1155 #if DEBUG_NETWORK
1156     struct GNUNET_CONTAINER_SList_Iterator t;
1157 #endif
1158     h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1159                                                                       NULL);
1160 #if DEBUG_NETWORK
1161     LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1162          h->h);
1163     for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1164          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1165          GNUNET_CONTAINER_slist_next (&t))
1166     {
1167       struct GNUNET_DISK_FileHandle *fh;
1168
1169       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1170                                                                          NULL);
1171       LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1172     }
1173 #endif
1174     if (GNUNET_CONTAINER_slist_contains
1175         (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1176     {
1177       return GNUNET_YES;
1178     }
1179     GNUNET_CONTAINER_slist_next (&it);
1180   }
1181 #endif
1182   return GNUNET_NO;
1183 }
1184
1185
1186 /**
1187  * Creates an fd set
1188  *
1189  * @return a new fd set
1190  */
1191 struct GNUNET_NETWORK_FDSet *
1192 GNUNET_NETWORK_fdset_create ()
1193 {
1194   struct GNUNET_NETWORK_FDSet *fds;
1195
1196   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1197 #ifdef MINGW
1198   fds->handles = GNUNET_CONTAINER_slist_create ();
1199 #endif
1200   GNUNET_NETWORK_fdset_zero (fds);
1201   return fds;
1202 }
1203
1204
1205 /**
1206  * Releases the associated memory of an fd set
1207  *
1208  * @param fds fd set
1209  */
1210 void
1211 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1212 {
1213 #ifdef MINGW
1214   GNUNET_CONTAINER_slist_destroy (fds->handles);
1215 #endif
1216   GNUNET_free (fds);
1217 }
1218
1219 #if MINGW
1220 struct _select_params
1221 {
1222   fd_set *r;
1223   fd_set *w;
1224   fd_set *e;
1225   struct timeval *tv;
1226   HANDLE wakeup;
1227   HANDLE standby;
1228   SOCKET wakeup_socket;
1229   int status;
1230 };
1231
1232 static DWORD WINAPI
1233 _selector (LPVOID p)
1234 {
1235   struct _select_params *sp = p;
1236
1237   while (1)
1238   {
1239     WaitForSingleObject (sp->standby, INFINITE);
1240     ResetEvent (sp->standby);
1241     sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1242     if (FD_ISSET (sp->wakeup_socket, sp->r))
1243     {
1244       FD_CLR (sp->wakeup_socket, sp->r);
1245       sp->status -= 1;
1246     }
1247     SetEvent (sp->wakeup);
1248   }
1249   return 0;
1250 }
1251 #endif
1252
1253
1254 /**
1255  * Check if sockets or pipes meet certain conditions
1256  * @param rfds set of sockets or pipes to be checked for readability
1257  * @param wfds set of sockets or pipes to be checked for writability
1258  * @param efds set of sockets or pipes to be checked for exceptions
1259  * @param timeout relative value when to return
1260  * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1261  */
1262 int
1263 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1264                               struct GNUNET_NETWORK_FDSet *wfds,
1265                               struct GNUNET_NETWORK_FDSet *efds,
1266                               const struct GNUNET_TIME_Relative timeout)
1267 {
1268   int nfds = 0;
1269 #ifdef MINGW
1270   int handles = 0;
1271   int ex_handles = 0;
1272   int read_handles = 0;
1273   int write_handles = 0;
1274
1275   int i = 0;
1276   int retcode = 0;
1277   DWORD ms_total = 0;
1278
1279   int nhandles = 0;
1280
1281   static HANDLE hEventPipeWrite = 0;
1282   static HANDLE hEventReadReady = 0;
1283
1284   static struct _select_params sp;
1285   static HANDLE select_thread = NULL;
1286   static HANDLE select_finished_event = NULL;
1287   static HANDLE select_standby_event = NULL;
1288   static SOCKET select_wakeup_socket = -1;
1289   static SOCKET select_send_socket = -1;
1290   static struct timeval select_timeout;
1291
1292   int readPipes = 0;
1293   int writePipePos = 0;
1294
1295   HANDLE handle_array[FD_SETSIZE + 2];
1296   int returncode = -1;
1297   int returnedpos = 0;
1298
1299   struct GNUNET_CONTAINER_SList *handles_read;
1300   struct GNUNET_CONTAINER_SList *handles_write;
1301   struct GNUNET_CONTAINER_SList *handles_except;
1302
1303   int selectret = 0;
1304
1305   fd_set aread;
1306   fd_set awrite;
1307   fd_set aexcept;
1308
1309 #if DEBUG_NETWORK
1310   fd_set bread;
1311   fd_set bwrite;
1312   fd_set bexcept;
1313 #endif
1314
1315   /* TODO: Make this growable */
1316   struct GNUNET_DISK_FileHandle *readArray[50];
1317 #else
1318   struct timeval tv;
1319 #endif
1320   if (NULL != rfds)
1321   {
1322     nfds = rfds->nsds;
1323 #ifdef MINGW
1324     handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1325 #if DEBUG_NETWORK
1326     {
1327       struct GNUNET_CONTAINER_SList_Iterator t;
1328
1329       for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1330            GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1331            GNUNET_CONTAINER_slist_next (&t))
1332       {
1333         struct GNUNET_DISK_FileHandle *fh;
1334
1335         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1336                                                                            NULL);
1337         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1338              fh);
1339       }
1340     }
1341 #endif
1342 #endif
1343   }
1344   if (NULL != wfds)
1345   {
1346     nfds = GNUNET_MAX (nfds, wfds->nsds);
1347 #ifdef MINGW
1348     handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1349 #endif
1350   }
1351   if (NULL != efds)
1352   {
1353     nfds = GNUNET_MAX (nfds, efds->nsds);
1354 #ifdef MINGW
1355     handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1356 #endif
1357   }
1358
1359   if ((nfds == 0) &&
1360       (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1361 #ifdef MINGW
1362       && handles == 0
1363 #endif
1364       )
1365   {
1366     GNUNET_break (0);
1367     LOG (GNUNET_ERROR_TYPE_ERROR,
1368          _
1369          ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1370          "select");
1371   }
1372 #ifndef MINGW
1373   tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1374   tv.tv_usec =
1375     (timeout.rel_value_us -
1376      (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1377   return select (nfds, 
1378                  (NULL != rfds) ? &rfds->sds : NULL,
1379                  (NULL != wfds) ? &wfds->sds : NULL,
1380                  (NULL != efds) ? &efds->sds : NULL,
1381                  (timeout.rel_value_us ==
1382                   GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1383
1384 #else
1385 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1386   /* calculate how long we need to wait in milliseconds */
1387   if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1388     ms_total = INFINITE;
1389   else
1390   {
1391     ms_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
1392     if (timeout.rel_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us > 0xFFFFFFFFLL - 1)
1393     {
1394       GNUNET_break (0);
1395       ms_total = 0xFFFFFFFF - 1;
1396     }
1397   }
1398   /* select() may be used as a portable way to sleep */
1399   if (!(rfds || wfds || efds))
1400   {
1401     Sleep (ms_total);
1402     return 0;
1403   }
1404
1405   if (NULL == select_thread)
1406   {
1407     SOCKET select_listening_socket = -1;
1408     struct sockaddr_in s_in;
1409     int alen;
1410     int res;
1411     unsigned long p;
1412
1413     select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1414     select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1415
1416     select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1417
1418     select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1419
1420     p = 1;
1421     res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1422     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1423
1424     alen = sizeof (s_in);
1425     s_in.sin_family = AF_INET;
1426     s_in.sin_port = 0;
1427     s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1428     s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1429     s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1430     s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1431     res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1432     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1433
1434     res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1435     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1436
1437     res = listen (select_listening_socket, SOMAXCONN);
1438     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1439
1440     res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1441     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1442
1443     select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1444
1445     closesocket (select_listening_socket);
1446
1447     sp.wakeup = select_finished_event;
1448     sp.standby = select_standby_event;
1449     sp.wakeup_socket = select_wakeup_socket;
1450
1451     select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1452   }
1453
1454
1455   handles_read = GNUNET_CONTAINER_slist_create ();
1456   handles_write = GNUNET_CONTAINER_slist_create ();
1457   handles_except = GNUNET_CONTAINER_slist_create ();
1458   FD_ZERO (&aread);
1459   FD_ZERO (&awrite);
1460   FD_ZERO (&aexcept);
1461 #if DEBUG_NETWORK
1462   FD_ZERO (&bread);
1463   FD_ZERO (&bwrite);
1464   FD_ZERO (&bexcept);
1465 #endif
1466   if (rfds)
1467   {
1468     FD_COPY (&rfds->sds, &aread);
1469 #if DEBUG_NETWORK
1470     FD_COPY (&rfds->sds, &bread);
1471 #endif
1472   }
1473   if (wfds)
1474   {
1475     FD_COPY (&wfds->sds, &awrite);
1476 #if DEBUG_NETWORK
1477     FD_COPY (&wfds->sds, &bwrite);
1478 #endif
1479   }
1480   if (efds)
1481   {
1482     FD_COPY (&efds->sds, &aexcept);
1483 #if DEBUG_NETWORK
1484     FD_COPY (&efds->sds, &bexcept);
1485 #endif
1486   }
1487
1488   /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1489      By profiling we detected that to be true in 90% of the cases.
1490   */
1491
1492   /* Do the select now */
1493   select_timeout.tv_sec = 0;
1494   select_timeout.tv_usec = 0;
1495
1496   /* Copy all the writes to the except, so we can detect connect() errors */
1497   for (i = 0; i < awrite.fd_count; i++)
1498     FD_SET (awrite.fd_array[i], &aexcept);
1499   if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1500     selectret = select (1, (rfds != NULL) ? &aread : NULL,
1501         (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1502   else
1503     selectret = 0;
1504   if (selectret == -1)
1505   {
1506     /* Throw an error early on, while we still have the context. */
1507     LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1508         rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1509     GNUNET_abort ();
1510   }
1511
1512   /* Check aexcept, add its contents to awrite
1513      This is technically wrong (aexcept might have its own descriptors), we should
1514      have checked that descriptors were in awrite originally before re-adding them from
1515      aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1516   for (i = 0; i < aexcept.fd_count; i++)
1517     FD_SET (aexcept.fd_array[i], &awrite);
1518
1519   /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1520   /* Sadly, it means code duplication :( */
1521   if ((selectret > 0) || (ms_total == 0))
1522   {
1523     /* Read Pipes */
1524     if (rfds && read_handles)
1525     {
1526       struct GNUNET_CONTAINER_SList_Iterator i;
1527       int c;
1528
1529       for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1530           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1531           GNUNET_CONTAINER_slist_next (&i), c++)
1532       {
1533         struct GNUNET_DISK_FileHandle *fh;
1534
1535         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1536         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1537         {
1538           DWORD error;
1539           BOOL bret;
1540
1541           SetLastError (0);
1542           DWORD waitstatus = 0;
1543           bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1544           error = GetLastError ();
1545           LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1546               c, fh->h, bret, waitstatus, error);
1547           if (bret == 0)
1548           {
1549             /* TODO: either add more errors to this condition, or eliminate it
1550              * entirely (failed to peek -> pipe is in serious trouble, should
1551              * be selected as readable).
1552              */
1553             if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1554               continue;
1555           }
1556           else if (waitstatus <= 0)
1557             continue;
1558           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1559               fh, sizeof (struct GNUNET_DISK_FileHandle));
1560           retcode++;
1561           LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1562               fh, fh->h);
1563         }
1564         else
1565         {
1566           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1567               fh, sizeof (struct GNUNET_DISK_FileHandle));
1568           retcode++;
1569         }
1570       }
1571     }
1572     if (wfds && write_handles)
1573     {
1574       LOG (GNUNET_ERROR_TYPE_DEBUG,
1575           "Adding the write ready event to the array as %d\n", nhandles);
1576       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1577       retcode += write_handles;
1578     }
1579     if (efds && ex_handles)
1580     {
1581       struct GNUNET_CONTAINER_SList_Iterator i;
1582
1583       for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1584           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1585           GNUNET_CONTAINER_slist_next (&i))
1586       {
1587         struct GNUNET_DISK_FileHandle *fh;
1588         DWORD dwBytes;
1589
1590         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1591         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1592         {
1593           if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1594             continue;
1595           GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1596               fh, sizeof (struct GNUNET_DISK_FileHandle));
1597           retcode++;
1598         }
1599       }
1600     }
1601
1602     /* Add our select() result.*/
1603     if (selectret >= 0)
1604       retcode += selectret;
1605
1606     if (rfds)
1607     {
1608       GNUNET_NETWORK_fdset_zero (rfds);
1609       if (selectret != -1)
1610         GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1611       GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1612     }
1613     if (wfds)
1614     {
1615       GNUNET_NETWORK_fdset_zero (wfds);
1616       if (selectret != -1)
1617         GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1618       GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1619     }
1620     if (efds)
1621     {
1622       GNUNET_NETWORK_fdset_zero (efds);
1623       if (selectret != -1)
1624         GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1625       GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1626     }
1627     GNUNET_CONTAINER_slist_destroy (handles_read);
1628     GNUNET_CONTAINER_slist_destroy (handles_write);
1629     GNUNET_CONTAINER_slist_destroy (handles_except);
1630
1631     if (selectret == -1)
1632       return -1;
1633     return retcode;
1634   }
1635
1636   /* If we got this far, use slower implementation that is able to do a waiting select
1637      on both sockets and pipes simultaneously */
1638
1639   /* Events for pipes */
1640   if (!hEventReadReady)
1641     hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1642   if (!hEventPipeWrite)
1643     hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1644   readPipes = 0;
1645   writePipePos = -1;
1646
1647   retcode = 0;
1648
1649   FD_ZERO (&aread);
1650   FD_ZERO (&awrite);
1651   FD_ZERO (&aexcept);
1652 #if DEBUG_NETWORK
1653   FD_ZERO (&bread);
1654   FD_ZERO (&bwrite);
1655   FD_ZERO (&bexcept);
1656 #endif
1657   if (rfds)
1658   {
1659     FD_COPY (&rfds->sds, &aread);
1660 #if DEBUG_NETWORK
1661     FD_COPY (&rfds->sds, &bread);
1662 #endif
1663   }
1664   if (wfds)
1665   {
1666     FD_COPY (&wfds->sds, &awrite);
1667 #if DEBUG_NETWORK
1668     FD_COPY (&wfds->sds, &bwrite);
1669 #endif
1670   }
1671   if (efds)
1672   {
1673     FD_COPY (&efds->sds, &aexcept);
1674 #if DEBUG_NETWORK
1675     FD_COPY (&efds->sds, &bexcept);
1676 #endif
1677   }
1678   /* We will first Add the PIPES to the events */
1679   /* Read Pipes */
1680   if (rfds && read_handles)
1681   {
1682     struct GNUNET_CONTAINER_SList_Iterator i;
1683
1684     for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1685          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1686          GNUNET_CONTAINER_slist_next (&i))
1687     {
1688       struct GNUNET_DISK_FileHandle *fh;
1689
1690       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1691                                                                          NULL);
1692       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1693       {
1694         /* Read zero bytes to check the status of the pipe */
1695         LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1696              fh->h);
1697         if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1698         {
1699           DWORD error_code = GetLastError ();
1700
1701           if (error_code == ERROR_IO_PENDING)
1702           {
1703             LOG (GNUNET_ERROR_TYPE_DEBUG,
1704                  "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1705                  fh->h, nhandles);
1706             handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1707             readArray[readPipes++] = fh;
1708           }
1709           else
1710           {
1711             LOG (GNUNET_ERROR_TYPE_DEBUG,
1712                  "Read failed, adding the read ready event to the array as %d\n", nhandles);
1713             handle_array[nhandles++] = hEventReadReady;
1714             readArray[readPipes++] = fh;
1715           }
1716         }
1717         else
1718         {
1719           LOG (GNUNET_ERROR_TYPE_DEBUG,
1720                "Adding the read ready event to the array as %d\n", nhandles);
1721           handle_array[nhandles++] = hEventReadReady;
1722           readArray[readPipes++] = fh;
1723         }
1724       }
1725       else
1726       {
1727         GNUNET_CONTAINER_slist_add (handles_read,
1728                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1729                                     fh, sizeof (struct GNUNET_DISK_FileHandle));
1730       }
1731     }
1732   }
1733   if (wfds && write_handles)
1734   {
1735     LOG (GNUNET_ERROR_TYPE_DEBUG,
1736          "Adding the write ready event to the array as %d\n", nhandles);
1737     handle_array[nhandles++] = hEventPipeWrite;
1738     writePipePos = nhandles;
1739   }
1740   if (efds && ex_handles)
1741   {
1742     struct GNUNET_CONTAINER_SList_Iterator i;
1743
1744     for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1745          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1746          GNUNET_CONTAINER_slist_next (&i))
1747     {
1748       struct GNUNET_DISK_FileHandle *fh;
1749       DWORD dwBytes;
1750
1751       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1752                                                                          NULL);
1753       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1754       {
1755         if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1756         {
1757           GNUNET_CONTAINER_slist_add (handles_except,
1758                                       GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1759                                       fh,
1760                                       sizeof (struct GNUNET_DISK_FileHandle));
1761         }
1762       }
1763     }
1764   }
1765
1766   sp.status = 0;
1767
1768   if (nfds > 0)
1769   {
1770     LOG (GNUNET_ERROR_TYPE_DEBUG,
1771          "Adding the socket event to the array as %d\n",
1772          nhandles);
1773     handle_array[nhandles++] = select_finished_event;
1774     if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1775       sp.tv = NULL;
1776     else
1777     {
1778       select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1779       select_timeout.tv_usec =(timeout.rel_value_us -
1780           (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1781       sp.tv = &select_timeout;
1782     }
1783     FD_SET (select_wakeup_socket, &aread);
1784     sp.r = &aread;
1785     sp.w = &awrite;
1786     sp.e = &aexcept;
1787     /* Failed connections cause sockets to be set in errorfds on W32,
1788      * but on POSIX it should set them in writefds.
1789      * First copy all awrite sockets to aexcept, later we'll
1790      * check aexcept and set its contents in awrite as well
1791      * Sockets are also set in errorfds when OOB data is available,
1792      * but we don't use OOB data.
1793      */
1794     for (i = 0; i < awrite.fd_count; i++)
1795       FD_SET (awrite.fd_array[i], &aexcept);
1796     ResetEvent (select_finished_event);
1797     SetEvent (select_standby_event);
1798   }
1799
1800   handle_array[nhandles] = NULL;
1801   LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n", 
1802        nfds, nhandles, (unsigned long long) ms_total);
1803   if (nhandles)
1804   {
1805     returncode =
1806         WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1807     LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1808          returncode);
1809   }
1810   else if (nfds > 0)
1811   {
1812     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1813     returncode = WAIT_TIMEOUT;
1814   }
1815   else
1816   {
1817     /* Shouldn't come this far. If it does - investigate. */
1818     GNUNET_assert (0);
1819   }
1820
1821   if (nfds > 0)
1822   {
1823     /* Don't wake up select-thread when delay is 0, it should return immediately
1824      * and wake up by itself.
1825      */
1826     if (ms_total != 0)
1827       i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1828     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1829     LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1830     if (ms_total != 0)
1831     {
1832       do
1833       {
1834         i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1835       } while (i == 1);
1836     }
1837     /* Check aexcept, add its contents to awrite */
1838     for (i = 0; i < aexcept.fd_count; i++)
1839       FD_SET (aexcept.fd_array[i], &awrite);
1840   }
1841
1842   returnedpos = returncode - WAIT_OBJECT_0;
1843   LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1844
1845   if (nhandles && (returnedpos < nhandles))
1846   {
1847     DWORD waitstatus;
1848
1849     if (sp.status > 0)
1850       retcode += sp.status;
1851
1852     if ((writePipePos != -1) && (returnedpos < writePipePos))
1853     {
1854       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1855       retcode += write_handles;
1856       LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1857     }
1858     LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1859     /* We have some pipes ready for read. */
1860     if (returnedpos < readPipes)
1861     {
1862       for (i = 0; i < readPipes; i++)
1863       {
1864         DWORD error;
1865         BOOL bret;
1866
1867         SetLastError (0);
1868         waitstatus = 0;
1869         bret =
1870             PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1871         error = GetLastError ();
1872         LOG (GNUNET_ERROR_TYPE_DEBUG,
1873              "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1874              i, readArray[i]->h, bret, waitstatus, error);
1875         if (bret == 0)
1876         {
1877           /* TODO: either add more errors to this condition, or eliminate it
1878            * entirely (failed to peek -> pipe is in serious trouble, should
1879            * be selected as readable).
1880            */
1881           if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1882             continue;
1883         }
1884         else if (waitstatus <= 0)
1885           continue;
1886         GNUNET_CONTAINER_slist_add (handles_read,
1887                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1888                                     readArray[i],
1889                                     sizeof (struct GNUNET_DISK_FileHandle));
1890         retcode++;
1891         LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1892              readArray[i], readArray[i]->h);
1893       }
1894     }
1895   }
1896   if (!nhandles || (returnedpos >= nhandles))
1897     LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1898   if (rfds)
1899   {
1900     struct GNUNET_CONTAINER_SList_Iterator t;
1901
1902     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1903          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1904          GNUNET_CONTAINER_slist_next (&t))
1905     {
1906       struct GNUNET_DISK_FileHandle *fh;
1907
1908       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1909                                                                          NULL);
1910       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1911       {
1912         CancelIo (fh->h);
1913       }
1914     }
1915     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1916     GNUNET_NETWORK_fdset_zero (rfds);
1917     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1918       GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1919     GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1920   }
1921   if (wfds)
1922   {
1923     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1924     GNUNET_NETWORK_fdset_zero (wfds);
1925     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1926       GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1927     GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1928   }
1929   if (efds)
1930   {
1931     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1932     GNUNET_NETWORK_fdset_zero (efds);
1933     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1934       GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1935     GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1936   }
1937   GNUNET_CONTAINER_slist_destroy (handles_read);
1938   GNUNET_CONTAINER_slist_destroy (handles_write);
1939   GNUNET_CONTAINER_slist_destroy (handles_except);
1940 #if DEBUG_NETWORK
1941   if (rfds)
1942   {
1943     struct GNUNET_CONTAINER_SList_Iterator t;
1944
1945     LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1946     for (i = 0; i < rfds->sds.fd_count; i++)
1947     {
1948       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1949     }
1950     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1951          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1952          GNUNET_CONTAINER_slist_next (&t))
1953     {
1954       struct GNUNET_DISK_FileHandle *fh;
1955
1956       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1957                                                                          NULL);
1958       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1959     }
1960   }
1961   if (wfds)
1962   {
1963     LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1964     for (i = 0; i < wfds->sds.fd_count; i++)
1965     {
1966       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1967     }
1968   }
1969   if (efds)
1970   {
1971     LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1972     for (i = 0; i < efds->sds.fd_count; i++)
1973     {
1974       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1975     }
1976   }
1977   LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1978 #endif
1979   if (nhandles && (returnedpos < nhandles))
1980     return retcode;
1981   else
1982 #endif
1983     return 0;
1984 }
1985
1986 /* end of network.c */