-perform tiny wait if we do get worken up to do no work
[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   uint64_t mcs_total = 0;
1278   DWORD ms_rounded = 0;
1279
1280   int nhandles = 0;
1281
1282   static HANDLE hEventPipeWrite = 0;
1283   static HANDLE hEventReadReady = 0;
1284
1285   static struct _select_params sp;
1286   static HANDLE select_thread = NULL;
1287   static HANDLE select_finished_event = NULL;
1288   static HANDLE select_standby_event = NULL;
1289   static SOCKET select_wakeup_socket = -1;
1290   static SOCKET select_send_socket = -1;
1291   static struct timeval select_timeout;
1292
1293   int readPipes = 0;
1294   int writePipePos = 0;
1295
1296   HANDLE handle_array[FD_SETSIZE + 2];
1297   int returncode = -1;
1298   int returnedpos = 0;
1299
1300   struct GNUNET_CONTAINER_SList *handles_read;
1301   struct GNUNET_CONTAINER_SList *handles_write;
1302   struct GNUNET_CONTAINER_SList *handles_except;
1303
1304   int selectret = 0;
1305
1306   fd_set aread;
1307   fd_set awrite;
1308   fd_set aexcept;
1309
1310 #if DEBUG_NETWORK
1311   fd_set bread;
1312   fd_set bwrite;
1313   fd_set bexcept;
1314 #endif
1315
1316   /* TODO: Make this growable */
1317   struct GNUNET_DISK_FileHandle *readArray[50];
1318 #else
1319   struct timeval tv;
1320 #endif
1321   if (NULL != rfds)
1322   {
1323     nfds = rfds->nsds;
1324 #ifdef MINGW
1325     handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1326 #if DEBUG_NETWORK
1327     {
1328       struct GNUNET_CONTAINER_SList_Iterator t;
1329
1330       for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1331            GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1332            GNUNET_CONTAINER_slist_next (&t))
1333       {
1334         struct GNUNET_DISK_FileHandle *fh;
1335
1336         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1337                                                                            NULL);
1338         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1339              fh);
1340       }
1341     }
1342 #endif
1343 #endif
1344   }
1345   if (NULL != wfds)
1346   {
1347     nfds = GNUNET_MAX (nfds, wfds->nsds);
1348 #ifdef MINGW
1349     handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1350 #endif
1351   }
1352   if (NULL != efds)
1353   {
1354     nfds = GNUNET_MAX (nfds, efds->nsds);
1355 #ifdef MINGW
1356     handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1357 #endif
1358   }
1359
1360   if ((nfds == 0) &&
1361       (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1362 #ifdef MINGW
1363       && handles == 0
1364 #endif
1365       )
1366   {
1367     GNUNET_break (0);
1368     LOG (GNUNET_ERROR_TYPE_ERROR,
1369          _
1370          ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1371          "select");
1372   }
1373 #ifndef MINGW
1374   tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1375   tv.tv_usec =
1376     (timeout.rel_value_us -
1377      (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1378   return select (nfds, 
1379                  (NULL != rfds) ? &rfds->sds : NULL,
1380                  (NULL != wfds) ? &wfds->sds : NULL,
1381                  (NULL != efds) ? &efds->sds : NULL,
1382                  (timeout.rel_value_us ==
1383                   GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1384
1385 #else
1386 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1387   /* calculate how long we need to wait in microseconds */
1388   if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1389   {
1390     mcs_total = INFINITE;
1391     ms_rounded = INFINITE;
1392   }
1393   else
1394   {
1395     mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1396     ms_rounded = (DWORD) (mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1397     if (mcs_total > 0 && ms_rounded == 0)
1398       ms_rounded = 1;
1399   }
1400   /* select() may be used as a portable way to sleep */
1401   if (!(rfds || wfds || efds))
1402   {
1403     Sleep (ms_rounded);
1404     return 0;
1405   }
1406
1407   if (NULL == select_thread)
1408   {
1409     SOCKET select_listening_socket = -1;
1410     struct sockaddr_in s_in;
1411     int alen;
1412     int res;
1413     unsigned long p;
1414
1415     select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1416     select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1417
1418     select_wakeup_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1419
1420     select_listening_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1421
1422     p = 1;
1423     res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1424     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1425
1426     alen = sizeof (s_in);
1427     s_in.sin_family = AF_INET;
1428     s_in.sin_port = 0;
1429     s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1430     s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1431     s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1432     s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1433     res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1434     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1435
1436     res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1437     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1438
1439     res = listen (select_listening_socket, SOMAXCONN);
1440     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1441
1442     res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1443     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1444
1445     select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1446
1447     closesocket (select_listening_socket);
1448
1449     sp.wakeup = select_finished_event;
1450     sp.standby = select_standby_event;
1451     sp.wakeup_socket = select_wakeup_socket;
1452
1453     select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1454   }
1455
1456
1457   handles_read = GNUNET_CONTAINER_slist_create ();
1458   handles_write = GNUNET_CONTAINER_slist_create ();
1459   handles_except = GNUNET_CONTAINER_slist_create ();
1460   FD_ZERO (&aread);
1461   FD_ZERO (&awrite);
1462   FD_ZERO (&aexcept);
1463 #if DEBUG_NETWORK
1464   FD_ZERO (&bread);
1465   FD_ZERO (&bwrite);
1466   FD_ZERO (&bexcept);
1467 #endif
1468   if (rfds)
1469   {
1470     FD_COPY (&rfds->sds, &aread);
1471 #if DEBUG_NETWORK
1472     FD_COPY (&rfds->sds, &bread);
1473 #endif
1474   }
1475   if (wfds)
1476   {
1477     FD_COPY (&wfds->sds, &awrite);
1478 #if DEBUG_NETWORK
1479     FD_COPY (&wfds->sds, &bwrite);
1480 #endif
1481   }
1482   if (efds)
1483   {
1484     FD_COPY (&efds->sds, &aexcept);
1485 #if DEBUG_NETWORK
1486     FD_COPY (&efds->sds, &bexcept);
1487 #endif
1488   }
1489
1490   /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1491      By profiling we detected that to be true in 90% of the cases.
1492   */
1493
1494   /* Do the select now */
1495   select_timeout.tv_sec = 0;
1496   select_timeout.tv_usec = 0;
1497
1498   /* Copy all the writes to the except, so we can detect connect() errors */
1499   for (i = 0; i < awrite.fd_count; i++)
1500     FD_SET (awrite.fd_array[i], &aexcept);
1501   if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1502     selectret = select (1, (rfds != NULL) ? &aread : NULL,
1503         (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1504   else
1505     selectret = 0;
1506   if (selectret == -1)
1507   {
1508     /* Throw an error early on, while we still have the context. */
1509     LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1510         rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1511     GNUNET_abort ();
1512   }
1513
1514   /* Check aexcept, add its contents to awrite
1515      This is technically wrong (aexcept might have its own descriptors), we should
1516      have checked that descriptors were in awrite originally before re-adding them from
1517      aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1518   for (i = 0; i < aexcept.fd_count; i++)
1519     FD_SET (aexcept.fd_array[i], &awrite);
1520
1521   /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1522   /* Sadly, it means code duplication :( */
1523   if ((selectret > 0) || (mcs_total == 0))
1524   {
1525     /* Read Pipes */
1526     if (rfds && read_handles)
1527     {
1528       struct GNUNET_CONTAINER_SList_Iterator i;
1529       int c;
1530
1531       for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1532           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1533           GNUNET_CONTAINER_slist_next (&i), c++)
1534       {
1535         struct GNUNET_DISK_FileHandle *fh;
1536
1537         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1538         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1539         {
1540           DWORD error;
1541           BOOL bret;
1542
1543           SetLastError (0);
1544           DWORD waitstatus = 0;
1545           bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1546           error = GetLastError ();
1547           LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1548               c, fh->h, bret, waitstatus, error);
1549           if (bret == 0)
1550           {
1551             /* TODO: either add more errors to this condition, or eliminate it
1552              * entirely (failed to peek -> pipe is in serious trouble, should
1553              * be selected as readable).
1554              */
1555             if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1556               continue;
1557           }
1558           else if (waitstatus <= 0)
1559             continue;
1560           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1561               fh, sizeof (struct GNUNET_DISK_FileHandle));
1562           retcode++;
1563           LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1564               fh, fh->h);
1565         }
1566         else
1567         {
1568           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1569               fh, sizeof (struct GNUNET_DISK_FileHandle));
1570           retcode++;
1571         }
1572       }
1573     }
1574     if (wfds && write_handles)
1575     {
1576       LOG (GNUNET_ERROR_TYPE_DEBUG,
1577           "Adding the write ready event to the array as %d\n", nhandles);
1578       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1579       retcode += write_handles;
1580     }
1581     if (efds && ex_handles)
1582     {
1583       struct GNUNET_CONTAINER_SList_Iterator i;
1584
1585       for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1586           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1587           GNUNET_CONTAINER_slist_next (&i))
1588       {
1589         struct GNUNET_DISK_FileHandle *fh;
1590         DWORD dwBytes;
1591
1592         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1593         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1594         {
1595           if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1596             continue;
1597           GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1598               fh, sizeof (struct GNUNET_DISK_FileHandle));
1599           retcode++;
1600         }
1601       }
1602     }
1603
1604     /* Add our select() result.*/
1605     if (selectret >= 0)
1606       retcode += selectret;
1607
1608     if (rfds)
1609     {
1610       GNUNET_NETWORK_fdset_zero (rfds);
1611       if (selectret != -1)
1612         GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1613       GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1614     }
1615     if (wfds)
1616     {
1617       GNUNET_NETWORK_fdset_zero (wfds);
1618       if (selectret != -1)
1619         GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1620       GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1621     }
1622     if (efds)
1623     {
1624       GNUNET_NETWORK_fdset_zero (efds);
1625       if (selectret != -1)
1626         GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1627       GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1628     }
1629     GNUNET_CONTAINER_slist_destroy (handles_read);
1630     GNUNET_CONTAINER_slist_destroy (handles_write);
1631     GNUNET_CONTAINER_slist_destroy (handles_except);
1632
1633     if (selectret == -1)
1634       return -1;
1635     return retcode;
1636   }
1637
1638   /* If we got this far, use slower implementation that is able to do a waiting select
1639      on both sockets and pipes simultaneously */
1640
1641   /* Events for pipes */
1642   if (!hEventReadReady)
1643     hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1644   if (!hEventPipeWrite)
1645     hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1646   readPipes = 0;
1647   writePipePos = -1;
1648
1649   retcode = 0;
1650
1651   FD_ZERO (&aread);
1652   FD_ZERO (&awrite);
1653   FD_ZERO (&aexcept);
1654 #if DEBUG_NETWORK
1655   FD_ZERO (&bread);
1656   FD_ZERO (&bwrite);
1657   FD_ZERO (&bexcept);
1658 #endif
1659   if (rfds)
1660   {
1661     FD_COPY (&rfds->sds, &aread);
1662 #if DEBUG_NETWORK
1663     FD_COPY (&rfds->sds, &bread);
1664 #endif
1665   }
1666   if (wfds)
1667   {
1668     FD_COPY (&wfds->sds, &awrite);
1669 #if DEBUG_NETWORK
1670     FD_COPY (&wfds->sds, &bwrite);
1671 #endif
1672   }
1673   if (efds)
1674   {
1675     FD_COPY (&efds->sds, &aexcept);
1676 #if DEBUG_NETWORK
1677     FD_COPY (&efds->sds, &bexcept);
1678 #endif
1679   }
1680   /* We will first Add the PIPES to the events */
1681   /* Read Pipes */
1682   if (rfds && read_handles)
1683   {
1684     struct GNUNET_CONTAINER_SList_Iterator i;
1685
1686     for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1687          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1688          GNUNET_CONTAINER_slist_next (&i))
1689     {
1690       struct GNUNET_DISK_FileHandle *fh;
1691
1692       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1693                                                                          NULL);
1694       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1695       {
1696         /* Read zero bytes to check the status of the pipe */
1697         LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1698              fh->h);
1699         if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1700         {
1701           DWORD error_code = GetLastError ();
1702
1703           if (error_code == ERROR_IO_PENDING)
1704           {
1705             LOG (GNUNET_ERROR_TYPE_DEBUG,
1706                  "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1707                  fh->h, nhandles);
1708             handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1709             readArray[readPipes++] = fh;
1710           }
1711           else
1712           {
1713             LOG (GNUNET_ERROR_TYPE_DEBUG,
1714                  "Read failed, adding the read ready event to the array as %d\n", nhandles);
1715             handle_array[nhandles++] = hEventReadReady;
1716             readArray[readPipes++] = fh;
1717           }
1718         }
1719         else
1720         {
1721           LOG (GNUNET_ERROR_TYPE_DEBUG,
1722                "Adding the read ready event to the array as %d\n", nhandles);
1723           handle_array[nhandles++] = hEventReadReady;
1724           readArray[readPipes++] = fh;
1725         }
1726       }
1727       else
1728       {
1729         GNUNET_CONTAINER_slist_add (handles_read,
1730                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1731                                     fh, sizeof (struct GNUNET_DISK_FileHandle));
1732       }
1733     }
1734   }
1735   if (wfds && write_handles)
1736   {
1737     LOG (GNUNET_ERROR_TYPE_DEBUG,
1738          "Adding the write ready event to the array as %d\n", nhandles);
1739     handle_array[nhandles++] = hEventPipeWrite;
1740     writePipePos = nhandles;
1741   }
1742   if (efds && ex_handles)
1743   {
1744     struct GNUNET_CONTAINER_SList_Iterator i;
1745
1746     for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1747          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1748          GNUNET_CONTAINER_slist_next (&i))
1749     {
1750       struct GNUNET_DISK_FileHandle *fh;
1751       DWORD dwBytes;
1752
1753       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1754                                                                          NULL);
1755       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1756       {
1757         if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1758         {
1759           GNUNET_CONTAINER_slist_add (handles_except,
1760                                       GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1761                                       fh,
1762                                       sizeof (struct GNUNET_DISK_FileHandle));
1763         }
1764       }
1765     }
1766   }
1767
1768   sp.status = 0;
1769
1770   if (nfds > 0)
1771   {
1772     LOG (GNUNET_ERROR_TYPE_DEBUG,
1773          "Adding the socket event to the array as %d\n",
1774          nhandles);
1775     handle_array[nhandles++] = select_finished_event;
1776     if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1777       sp.tv = NULL;
1778     else
1779     {
1780       select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1781       select_timeout.tv_usec =(timeout.rel_value_us -
1782           (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1783       sp.tv = &select_timeout;
1784     }
1785     FD_SET (select_wakeup_socket, &aread);
1786     do
1787     {
1788       i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1789     } while (i == 1);
1790     sp.r = &aread;
1791     sp.w = &awrite;
1792     sp.e = &aexcept;
1793     /* Failed connections cause sockets to be set in errorfds on W32,
1794      * but on POSIX it should set them in writefds.
1795      * First copy all awrite sockets to aexcept, later we'll
1796      * check aexcept and set its contents in awrite as well
1797      * Sockets are also set in errorfds when OOB data is available,
1798      * but we don't use OOB data.
1799      */
1800     for (i = 0; i < awrite.fd_count; i++)
1801       FD_SET (awrite.fd_array[i], &aexcept);
1802     ResetEvent (select_finished_event);
1803     SetEvent (select_standby_event);
1804   }
1805
1806   handle_array[nhandles] = NULL;
1807   LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu mcs\n",
1808        nfds, nhandles, mcs_total);
1809   if (nhandles)
1810   {
1811     returncode =
1812         WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_rounded);
1813     LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n", returncode);
1814   }
1815   else if (nfds > 0)
1816   {
1817     GNUNET_break (0); /* This branch shouldn't actually be executed...*/
1818     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1819     returncode = WAIT_TIMEOUT;
1820   }
1821   else
1822   {
1823     /* Shouldn't come this far. If it does - investigate. */
1824     GNUNET_assert (0);
1825   }
1826
1827   if (nfds > 0)
1828   {
1829     /* Don't wake up select-thread when delay is 0, it should return immediately
1830      * and wake up by itself.
1831      */
1832     if (mcs_total != 0)
1833       i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1834     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1835     LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1836     if (mcs_total != 0)
1837     {
1838       do
1839       {
1840         i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1841       } while (i == 1);
1842     }
1843     /* Check aexcept, add its contents to awrite */
1844     for (i = 0; i < aexcept.fd_count; i++)
1845       FD_SET (aexcept.fd_array[i], &awrite);
1846   }
1847
1848   returnedpos = returncode - WAIT_OBJECT_0;
1849   LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1850
1851   if (nhandles && (returnedpos < nhandles))
1852   {
1853     DWORD waitstatus;
1854
1855     if (sp.status > 0)
1856       retcode += sp.status;
1857
1858     if ((writePipePos != -1) && (returnedpos < writePipePos))
1859     {
1860       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1861       retcode += write_handles;
1862       LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1863     }
1864     LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1865     /* We have some pipes ready for read. */
1866     if (returnedpos < readPipes)
1867     {
1868       for (i = 0; i < readPipes; i++)
1869       {
1870         DWORD error;
1871         BOOL bret;
1872
1873         SetLastError (0);
1874         waitstatus = 0;
1875         bret =
1876             PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1877         error = GetLastError ();
1878         LOG (GNUNET_ERROR_TYPE_DEBUG,
1879              "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1880              i, readArray[i]->h, bret, waitstatus, error);
1881         if (bret == 0)
1882         {
1883           /* TODO: either add more errors to this condition, or eliminate it
1884            * entirely (failed to peek -> pipe is in serious trouble, should
1885            * be selected as readable).
1886            */
1887           if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1888             continue;
1889         }
1890         else if (waitstatus <= 0)
1891           continue;
1892         GNUNET_CONTAINER_slist_add (handles_read,
1893                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1894                                     readArray[i],
1895                                     sizeof (struct GNUNET_DISK_FileHandle));
1896         retcode++;
1897         LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1898              readArray[i], readArray[i]->h);
1899       }
1900     }
1901   }
1902   if (!nhandles || (returnedpos >= nhandles))
1903     LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1904   if (rfds)
1905   {
1906     struct GNUNET_CONTAINER_SList_Iterator t;
1907
1908     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1909          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1910          GNUNET_CONTAINER_slist_next (&t))
1911     {
1912       struct GNUNET_DISK_FileHandle *fh;
1913
1914       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1915                                                                          NULL);
1916       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1917       {
1918         CancelIo (fh->h);
1919       }
1920     }
1921     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1922     GNUNET_NETWORK_fdset_zero (rfds);
1923     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1924       GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1925     GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1926   }
1927   if (wfds)
1928   {
1929     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1930     GNUNET_NETWORK_fdset_zero (wfds);
1931     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1932       GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1933     GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1934   }
1935   if (efds)
1936   {
1937     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1938     GNUNET_NETWORK_fdset_zero (efds);
1939     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1940       GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1941     GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1942   }
1943   GNUNET_CONTAINER_slist_destroy (handles_read);
1944   GNUNET_CONTAINER_slist_destroy (handles_write);
1945   GNUNET_CONTAINER_slist_destroy (handles_except);
1946 #if DEBUG_NETWORK
1947   if (rfds)
1948   {
1949     struct GNUNET_CONTAINER_SList_Iterator t;
1950
1951     LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1952     for (i = 0; i < rfds->sds.fd_count; i++)
1953     {
1954       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1955     }
1956     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1957          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1958          GNUNET_CONTAINER_slist_next (&t))
1959     {
1960       struct GNUNET_DISK_FileHandle *fh;
1961
1962       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1963                                                                          NULL);
1964       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1965     }
1966   }
1967   if (wfds)
1968   {
1969     LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1970     for (i = 0; i < wfds->sds.fd_count; i++)
1971     {
1972       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1973     }
1974   }
1975   if (efds)
1976   {
1977     LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1978     for (i = 0; i < efds->sds.fd_count; i++)
1979     {
1980       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1981     }
1982   }
1983   LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1984 #endif
1985   if (nhandles && (returnedpos < nhandles))
1986     return retcode;
1987   else
1988 #endif
1989     return 0;
1990 }
1991
1992 /* end of network.c */