missing check
[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 FS_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 to a connected socket
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  * @param desc socket
444  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
445  */
446 int
447 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
448 {
449   int ret;
450
451 #ifdef MINGW
452   DWORD error = 0;
453
454   SetLastError (0);
455   ret = closesocket (desc->fd);
456   error = WSAGetLastError ();
457   SetErrnoFromWinsockError (error);
458   LOG (GNUNET_ERROR_TYPE_DEBUG,
459        "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
460        error);
461 #else
462   ret = close (desc->fd);
463 #endif
464 #ifndef LINUX
465 #ifndef MINGW
466   if ((desc->af == AF_UNIX) && (NULL != desc->addr))
467   {
468     const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
469
470     if (0 != unlink (un->sun_path))
471       LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
472   }
473 #endif
474 #endif
475   GNUNET_free_non_null (desc->addr);
476   GNUNET_free (desc);
477   return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
478 }
479
480
481 /**
482  * Box a native socket (and check that it is a socket).
483  *
484  * @param fd socket to box
485  * @return NULL on error (including not supported on target platform)
486  */
487 struct GNUNET_NETWORK_Handle *
488 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
489 {
490   struct GNUNET_NETWORK_Handle *ret;
491 #if MINGW
492   unsigned long i;
493   DWORD d;
494   /* FIXME: Find a better call to check that FD is valid */
495   if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
496     return NULL;                /* invalid FD */
497   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
498   ret->fd = fd;
499   ret->af = AF_UNSPEC;
500   return ret;
501 #else
502   if (fcntl (fd, F_GETFD) < 0)
503     return NULL;                /* invalid FD */
504   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
505   ret->fd = fd;
506   ret->af = AF_UNSPEC;
507   return ret;
508 #endif
509 }
510
511
512 /**
513  * Connect a socket
514  * @param desc socket
515  * @param address peer address
516  * @param address_len length of address
517  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
518  */
519 int
520 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
521                                const struct sockaddr *address,
522                                socklen_t address_len)
523 {
524   int ret;
525
526   ret = connect (desc->fd, address, address_len);
527
528 #ifdef MINGW
529   if (SOCKET_ERROR == ret)
530   {
531     SetErrnoFromWinsockError (WSAGetLastError ());
532     if (errno == EWOULDBLOCK)
533       errno = EINPROGRESS;
534   }
535 #endif
536   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
537 }
538
539
540 /**
541  * Get socket options
542  *
543  * @param desc socket
544  * @param level protocol level of the option
545  * @param optname identifier of the option
546  * @param optval options
547  * @param optlen length of optval
548  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
549  */
550 int
551 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
552                                   int level, int optname, void *optval,
553                                   socklen_t * optlen)
554 {
555   int ret;
556
557   ret = getsockopt (desc->fd, level, optname, optval, optlen);
558
559 #ifdef MINGW
560   if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
561     *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
562
563   else if (SOCKET_ERROR == ret)
564     SetErrnoFromWinsockError (WSAGetLastError ());
565 #endif
566   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
567 }
568
569
570 /**
571  * Listen on a socket
572  * @param desc socket
573  * @param backlog length of the listen queue
574  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
575  */
576 int
577 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
578                               int backlog)
579 {
580   int ret;
581
582   ret = listen (desc->fd, backlog);
583
584 #ifdef MINGW
585   if (SOCKET_ERROR == ret)
586     SetErrnoFromWinsockError (WSAGetLastError ());
587
588 #endif
589   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
590 }
591
592
593 /**
594  * How much data is available to be read on this descriptor?
595  *
596  * Returns GNUNET_NO if no data is available, or on error!
597  * @param desc socket
598  */
599 ssize_t
600 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
601                                        desc)
602 {
603   int error;
604
605   /* How much is there to be read? */
606 #ifndef WINDOWS
607   int pending;
608
609   error = ioctl (desc->fd, FIONREAD, &pending);
610   if (error == 0)
611     return (ssize_t) pending;
612   return GNUNET_NO;
613 #else
614   u_long pending;
615
616   error = ioctlsocket (desc->fd, FIONREAD, &pending);
617   if (error != SOCKET_ERROR)
618     return (ssize_t) pending;
619   return GNUNET_NO;
620 #endif
621 }
622
623
624 /**
625  * Read data from a connected socket (always non-blocking).
626  * @param desc socket
627  * @param buffer buffer
628  * @param length length of buffer
629  * @param src_addr either the source to recv from, or all zeroes
630  *        to be filled in by recvfrom
631  * @param addrlen length of the addr
632  */
633 ssize_t
634 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
635                                 void *buffer, size_t length,
636                                 struct sockaddr * src_addr, socklen_t * addrlen)
637 {
638   int ret;
639   int flags;
640
641   flags = 0;
642
643 #ifdef MSG_DONTWAIT
644   flags |= MSG_DONTWAIT;
645
646 #endif
647   ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
648 #ifdef MINGW
649   if (SOCKET_ERROR == ret)
650     SetErrnoFromWinsockError (WSAGetLastError ());
651 #endif
652   return ret;
653 }
654
655
656 /**
657  * Read data from a connected socket (always non-blocking).
658  * @param desc socket
659  * @param buffer buffer
660  * @param length length of buffer
661  */
662 ssize_t
663 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
664                             void *buffer, size_t length)
665 {
666   int ret;
667   int flags;
668
669   flags = 0;
670
671 #ifdef MSG_DONTWAIT
672   flags |= MSG_DONTWAIT;
673 #endif
674   ret = recv (desc->fd, buffer, length, flags);
675 #ifdef MINGW
676   if (SOCKET_ERROR == ret)
677     SetErrnoFromWinsockError (WSAGetLastError ());
678 #endif
679   return ret;
680 }
681
682
683 /**
684  * Send data (always non-blocking).
685  *
686  * @param desc socket
687  * @param buffer data to send
688  * @param length size of the buffer
689  * @return number of bytes sent, GNUNET_SYSERR on error
690  */
691 ssize_t
692 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
693                             const void *buffer, size_t length)
694 {
695   int ret;
696   int flags;
697
698   flags = 0;
699
700 #ifdef MSG_DONTWAIT
701   flags |= MSG_DONTWAIT;
702
703 #endif
704 #ifdef MSG_NOSIGNAL
705   flags |= MSG_NOSIGNAL;
706
707 #endif
708   ret = send (desc->fd, buffer, length, flags);
709
710 #ifdef MINGW
711   if (SOCKET_ERROR == ret)
712     SetErrnoFromWinsockError (WSAGetLastError ());
713
714 #endif
715   return ret;
716 }
717
718
719 /**
720  * Send data to a particular destination (always non-blocking).
721  * This function only works for UDP sockets.
722  *
723  * @param desc socket
724  * @param message data to send
725  * @param length size of the data
726  * @param dest_addr destination address
727  * @param dest_len length of address
728  * @return number of bytes sent, GNUNET_SYSERR on error
729  */
730 ssize_t
731 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
732                               const void *message, size_t length,
733                               const struct sockaddr * dest_addr,
734                               socklen_t dest_len)
735 {
736   int ret;
737   int flags;
738
739   flags = 0;
740
741 #ifdef MSG_DONTWAIT
742   flags |= MSG_DONTWAIT;
743 #endif
744 #ifdef MSG_NOSIGNAL
745   flags |= MSG_NOSIGNAL;
746 #endif
747   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
748 #ifdef MINGW
749   if (SOCKET_ERROR == ret)
750     SetErrnoFromWinsockError (WSAGetLastError ());
751 #endif
752   return ret;
753 }
754
755
756 /**
757  * Set socket option
758  * @param fd socket
759  * @param level protocol level of the option
760  * @param option_name option identifier
761  * @param option_value value to set
762  * @param option_len size of option_value
763  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
764  */
765 int
766 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
767                                   int option_name, const void *option_value,
768                                   socklen_t option_len)
769 {
770   int ret;
771
772   ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
773 #ifdef MINGW
774   if (SOCKET_ERROR == ret)
775     SetErrnoFromWinsockError (WSAGetLastError ());
776 #endif
777   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
778 }
779
780
781 /**
782  * Create a new socket.  Configure it for non-blocking IO and
783  * mark it as non-inheritable to child processes (set the
784  * close-on-exec flag).
785  *
786  * @param domain domain of the socket
787  * @param type socket type
788  * @param protocol network protocol
789  * @return new socket, NULL on error
790  */
791 struct GNUNET_NETWORK_Handle *
792 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
793 {
794   struct GNUNET_NETWORK_Handle *ret;
795
796   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
797   ret->fd = socket (domain, type, protocol);
798   if (GNUNET_OK !=
799       initialize_network_handle (ret, domain, type))
800     return NULL;
801   return ret;
802 }
803
804
805 /**
806  * Shut down socket operations
807  * @param desc socket
808  * @param how type of shutdown
809  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
810  */
811 int
812 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
813 {
814   int ret;
815
816   ret = shutdown (desc->fd, how);
817 #ifdef MINGW
818   if (ret != 0)
819     SetErrnoFromWinsockError (WSAGetLastError ());
820 #endif
821   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
822 }
823
824
825 /**
826  * Disable the "CORK" feature for communication with the given socket,
827  * forcing the OS to immediately flush the buffer on transmission
828  * instead of potentially buffering multiple messages.  Essentially
829  * reduces the OS send buffers to zero.
830  *
831  * @param desc socket
832  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
833  */
834 int
835 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
836 {
837   int ret = 0;
838
839 #if WINDOWS
840   int value = 0;
841
842   if (0 !=
843       (ret =
844        setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
845                    sizeof (value))))
846     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
847   if (0 !=
848       (ret =
849        setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
850                    sizeof (value))))
851     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
852 #elif LINUX
853   int value = 0;
854
855   if (0 !=
856       (ret =
857        setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
858     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
859   if (0 !=
860       (ret =
861        setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
862     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
863 #endif
864   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
865 }
866
867
868 /**
869  * Reset FD set
870  * @param fds fd set
871  */
872 void
873 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
874 {
875   FD_ZERO (&fds->sds);
876   fds->nsds = 0;
877 #ifdef MINGW
878   GNUNET_CONTAINER_slist_clear (fds->handles);
879 #endif
880 }
881
882 /**
883  * Add a socket to the FD set
884  * @param fds fd set
885  * @param desc socket to add
886  */
887 void
888 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
889                           const struct GNUNET_NETWORK_Handle *desc)
890 {
891   FD_SET (desc->fd, &fds->sds);
892   if (desc->fd + 1 > fds->nsds)
893     fds->nsds = desc->fd + 1;
894 }
895
896
897 /**
898  * Check whether a socket is part of the fd set
899  * @param fds fd set
900  * @param desc socket
901  * @return 0 if the FD is not set
902  */
903 int
904 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
905                             const struct GNUNET_NETWORK_Handle *desc)
906 {
907   return FD_ISSET (desc->fd, &fds->sds);
908 }
909
910
911 /**
912  * Add one fd set to another
913  * @param dst the fd set to add to
914  * @param src the fd set to add from
915  */
916 void
917 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
918                           const struct GNUNET_NETWORK_FDSet *src)
919 {
920 #ifndef MINGW
921   int nfds;
922
923   for (nfds = src->nsds; nfds > 0; nfds--)
924     if (FD_ISSET (nfds, &src->sds))
925
926     {
927       FD_SET (nfds, &dst->sds);
928       if (nfds + 1 > dst->nsds)
929         dst->nsds = nfds + 1;
930     }
931 #else
932   /* This is MinGW32-specific implementation that relies on the code that
933    * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
934    * that fd being added is not already in the set.
935    * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
936    */
937   int i;
938   for (i = 0; i < src->sds.fd_count; i++)
939     FD_SET (src->sds.fd_array[i], &dst->sds);
940   if (src->nsds > dst->nsds)
941     dst->nsds = src->nsds;
942
943   GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
944 #endif
945 }
946
947
948 /**
949  * Copy one fd set to another
950  *
951  * @param to destination
952  * @param from source
953  */
954 void
955 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
956                            const struct GNUNET_NETWORK_FDSet *from)
957 {
958   FD_COPY (&from->sds, &to->sds);
959   to->nsds = from->nsds;
960
961 #ifdef MINGW
962   GNUNET_CONTAINER_slist_clear (to->handles);
963   GNUNET_CONTAINER_slist_append (to->handles, from->handles);
964 #endif
965 }
966
967
968 /**
969  * Return file descriptor for this network handle
970  *
971  * @param desc wrapper to process
972  * @return POSIX file descriptor
973  */
974 int
975 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
976 {
977   return desc->fd;
978 }
979
980 /**
981  * Return sockaddr for this network handle
982  *
983  * @param desc wrapper to process
984  * @return sockaddr
985  */
986 struct sockaddr*
987 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
988 {
989   return desc->addr;
990 }
991
992 /**
993  * Return sockaddr length for this network handle
994  *
995  * @param desc wrapper to process
996  * @return socklen_t for sockaddr
997  */
998 socklen_t
999 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
1000 {
1001   return desc->addrlen;
1002 }
1003 /**
1004  * Copy a native fd set
1005  *
1006  * @param to destination
1007  * @param from native source set
1008  * @param nfds the biggest socket number in from + 1
1009  */
1010 void
1011 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
1012                                   const fd_set * from, int nfds)
1013 {
1014   FD_COPY (from, &to->sds);
1015   to->nsds = nfds;
1016 }
1017
1018
1019 /**
1020  * Set a native fd in a set
1021  *
1022  * @param to destination
1023  * @param nfd native FD to set
1024  */
1025 void
1026 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1027 {
1028   GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1029   FD_SET (nfd, &to->sds);
1030   to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1031 }
1032
1033
1034 /**
1035  * Test native fd in a set
1036  *
1037  * @param to set to test, NULL for empty set
1038  * @param nfd native FD to test, or -1 for none
1039  * @return GNUNET_YES if FD is set in the set
1040  */
1041 int
1042 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1043                                   int nfd)
1044 {
1045   if ((nfd == -1) || (to == NULL))
1046     return GNUNET_NO;
1047   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1048 }
1049
1050
1051 /**
1052  * Add a file handle to the fd set
1053  * @param fds fd set
1054  * @param h the file handle to add
1055  */
1056 void
1057 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1058                                  const struct GNUNET_DISK_FileHandle *h)
1059 {
1060 #ifdef MINGW
1061   GNUNET_CONTAINER_slist_add (fds->handles,
1062                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1063                               sizeof (struct GNUNET_DISK_FileHandle));
1064
1065 #else
1066   int fd;
1067
1068   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1069   FD_SET (fd, &fds->sds);
1070   if (fd + 1 > fds->nsds)
1071     fds->nsds = fd + 1;
1072
1073 #endif
1074 }
1075
1076
1077 /**
1078  * Check if a file handle is part of an fd set
1079  * @param fds fd set
1080  * @param h file handle
1081  * @return GNUNET_YES if the file handle is part of the set
1082  */
1083 int
1084 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1085                                    const struct GNUNET_DISK_FileHandle *h)
1086 {
1087
1088 #ifdef MINGW
1089   return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1090                                           sizeof (struct
1091                                                   GNUNET_DISK_FileHandle));
1092 #else
1093   return FD_ISSET (h->fd, &fds->sds);
1094 #endif
1095 }
1096
1097
1098 /**
1099  * Checks if two fd sets overlap
1100  * @param fds1 first fd set
1101  * @param fds2 second fd set
1102  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
1103  */
1104 int
1105 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1106                               const struct GNUNET_NETWORK_FDSet *fds2)
1107 {
1108 #ifndef MINGW
1109   int nfds;
1110
1111   nfds = fds1->nsds;
1112   if (nfds > fds2->nsds)
1113     nfds = fds2->nsds;
1114   while (nfds > 0)
1115   {
1116     nfds--;
1117     if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1118       return GNUNET_YES;
1119   }
1120 #else
1121   struct GNUNET_CONTAINER_SList_Iterator it;
1122   struct GNUNET_DISK_FileHandle *h;
1123   int i;
1124   int j;
1125
1126   /*This code is somewhat hacky, we are not supposed to know what's
1127    * inside of fd_set; also the O(n^2) is really bad... */
1128
1129   for (i = 0; i < fds1->sds.fd_count; i++)
1130   {
1131     for (j = 0; j < fds2->sds.fd_count; j++)
1132     {
1133       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1134         return GNUNET_YES;
1135     }
1136   }
1137   it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1138   while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1139   {
1140 #if DEBUG_NETWORK
1141     struct GNUNET_CONTAINER_SList_Iterator t;
1142 #endif
1143     h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1144                                                                       NULL);
1145 #if DEBUG_NETWORK
1146     LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1147          h->h);
1148     for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1149          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1150          GNUNET_CONTAINER_slist_next (&t))
1151     {
1152       struct GNUNET_DISK_FileHandle *fh;
1153
1154       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1155                                                                          NULL);
1156       LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1157     }
1158 #endif
1159     if (GNUNET_CONTAINER_slist_contains
1160         (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1161     {
1162       return GNUNET_YES;
1163     }
1164     GNUNET_CONTAINER_slist_next (&it);
1165   }
1166 #endif
1167   return GNUNET_NO;
1168 }
1169
1170
1171 /**
1172  * Creates an fd set
1173  * @return a new fd set
1174  */
1175 struct GNUNET_NETWORK_FDSet *
1176 GNUNET_NETWORK_fdset_create ()
1177 {
1178   struct GNUNET_NETWORK_FDSet *fds;
1179
1180   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1181 #ifdef MINGW
1182   fds->handles = GNUNET_CONTAINER_slist_create ();
1183 #endif
1184   GNUNET_NETWORK_fdset_zero (fds);
1185   return fds;
1186 }
1187
1188
1189 /**
1190  * Releases the associated memory of an fd set
1191  * @param fds fd set
1192  */
1193 void
1194 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1195 {
1196 #ifdef MINGW
1197   GNUNET_CONTAINER_slist_destroy (fds->handles);
1198 #endif
1199   GNUNET_free (fds);
1200 }
1201
1202 #if MINGW
1203 struct _select_params
1204 {
1205   fd_set *r;
1206   fd_set *w;
1207   fd_set *e;
1208   struct timeval *tv;
1209   HANDLE wakeup;
1210   HANDLE standby;
1211   SOCKET wakeup_socket;
1212   int status;
1213 };
1214
1215 static DWORD WINAPI
1216 _selector (LPVOID p)
1217 {
1218   struct _select_params *sp = p;
1219
1220   while (1)
1221   {
1222     WaitForSingleObject (sp->standby, INFINITE);
1223     ResetEvent (sp->standby);
1224     sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1225     if (FD_ISSET (sp->wakeup_socket, sp->r))
1226     {
1227       FD_CLR (sp->wakeup_socket, sp->r);
1228       sp->status -= 1;
1229     }
1230     SetEvent (sp->wakeup);
1231   }
1232   return 0;
1233 }
1234 #endif
1235
1236 /**
1237  * Check if sockets or pipes meet certain conditions
1238  * @param rfds set of sockets or pipes to be checked for readability
1239  * @param wfds set of sockets or pipes to be checked for writability
1240  * @param efds set of sockets or pipes to be checked for exceptions
1241  * @param timeout relative value when to return
1242  * @return number of selected sockets or pipes, GNUNET_SYSERR on error
1243  */
1244 int
1245 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1246                               struct GNUNET_NETWORK_FDSet *wfds,
1247                               struct GNUNET_NETWORK_FDSet *efds,
1248                               const struct GNUNET_TIME_Relative timeout)
1249 {
1250   int nfds = 0;
1251 #ifdef MINGW
1252   int handles = 0;
1253   int ex_handles = 0;
1254   int read_handles = 0;
1255   int write_handles = 0;
1256
1257   int i = 0;
1258   int retcode = 0;
1259   DWORD ms_total = 0;
1260
1261   int nhandles = 0;
1262
1263   static HANDLE hEventPipeWrite = 0;
1264   static HANDLE hEventReadReady = 0;
1265
1266   static struct _select_params sp;
1267   static HANDLE select_thread = NULL;
1268   static HANDLE select_finished_event = NULL;
1269   static HANDLE select_standby_event = NULL;
1270   static SOCKET select_wakeup_socket = -1;
1271   static SOCKET select_send_socket = -1;
1272   static struct timeval select_timeout;
1273
1274   int readPipes = 0;
1275   int writePipePos = 0;
1276
1277   HANDLE handle_array[FD_SETSIZE + 2];
1278   int returncode = -1;
1279   int returnedpos = 0;
1280
1281   struct GNUNET_CONTAINER_SList *handles_read;
1282   struct GNUNET_CONTAINER_SList *handles_write;
1283   struct GNUNET_CONTAINER_SList *handles_except;
1284
1285   int selectret = 0;
1286
1287   fd_set aread;
1288   fd_set awrite;
1289   fd_set aexcept;
1290
1291 #if DEBUG_NETWORK
1292   fd_set bread;
1293   fd_set bwrite;
1294   fd_set bexcept;
1295 #endif
1296
1297   /* TODO: Make this growable */
1298   struct GNUNET_DISK_FileHandle *readArray[50];
1299 #else
1300   struct timeval tv;
1301 #endif
1302   if (NULL != rfds)
1303   {
1304     nfds = rfds->nsds;
1305 #ifdef MINGW
1306     handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1307 #if DEBUG_NETWORK
1308     {
1309       struct GNUNET_CONTAINER_SList_Iterator t;
1310
1311       for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1312            GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1313            GNUNET_CONTAINER_slist_next (&t))
1314       {
1315         struct GNUNET_DISK_FileHandle *fh;
1316
1317         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1318                                                                            NULL);
1319         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1320              fh);
1321       }
1322     }
1323 #endif
1324 #endif
1325   }
1326   if (NULL != wfds)
1327   {
1328     nfds = GNUNET_MAX (nfds, wfds->nsds);
1329 #ifdef MINGW
1330     handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1331 #endif
1332   }
1333   if (NULL != efds)
1334   {
1335     nfds = GNUNET_MAX (nfds, efds->nsds);
1336 #ifdef MINGW
1337     handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1338 #endif
1339   }
1340
1341   if ((nfds == 0) &&
1342       (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1343 #ifdef MINGW
1344       && handles == 0
1345 #endif
1346       )
1347   {
1348     GNUNET_break (0);
1349     LOG (GNUNET_ERROR_TYPE_ERROR,
1350          _
1351          ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1352          "select");
1353   }
1354 #ifndef MINGW
1355   tv.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1356   tv.tv_usec =
1357     (timeout.rel_value_us -
1358      (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1359   return select (nfds, 
1360                  (NULL != rfds) ? &rfds->sds : NULL,
1361                  (NULL != wfds) ? &wfds->sds : NULL,
1362                  (NULL != efds) ? &efds->sds : NULL,
1363                  (timeout.rel_value_us ==
1364                   GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1365
1366 #else
1367 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1368   /* calculate how long we need to wait in milliseconds */
1369   if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1370     ms_total = INFINITE;
1371   else
1372   {
1373     ms_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us;
1374     if (timeout.rel_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us > 0xFFFFFFFFLL - 1)
1375     {
1376       GNUNET_break (0);
1377       ms_total = 0xFFFFFFFF - 1;
1378     }
1379   }
1380   /* select() may be used as a portable way to sleep */
1381   if (!(rfds || wfds || efds))
1382   {
1383     Sleep (ms_total);
1384     return 0;
1385   }
1386
1387   if (NULL == select_thread)
1388   {
1389     SOCKET select_listening_socket = -1;
1390     struct sockaddr_in s_in;
1391     int alen;
1392     int res;
1393     unsigned long p;
1394
1395     select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1396     select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1397
1398     select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1399
1400     select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1401
1402     p = 1;
1403     res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1404     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: ioctlsocket() returns %d\n", res);
1405
1406     alen = sizeof (s_in);
1407     s_in.sin_family = AF_INET;
1408     s_in.sin_port = 0;
1409     s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1410     s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1411     s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1412     s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1413     res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1414     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: bind() returns %d\n", res);
1415
1416     res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1417     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: getsockname() returns %d\n", res);
1418
1419     res = listen (select_listening_socket, SOMAXCONN);
1420     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: listen() returns %d\n", res);
1421
1422     res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1423     LOG (GNUNET_ERROR_TYPE_DEBUG, "Select thread initialization: connect() returns %d\n", res);
1424
1425     select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1426
1427     closesocket (select_listening_socket);
1428
1429     sp.wakeup = select_finished_event;
1430     sp.standby = select_standby_event;
1431     sp.wakeup_socket = select_wakeup_socket;
1432
1433     select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1434   }
1435
1436
1437   handles_read = GNUNET_CONTAINER_slist_create ();
1438   handles_write = GNUNET_CONTAINER_slist_create ();
1439   handles_except = GNUNET_CONTAINER_slist_create ();
1440   FD_ZERO (&aread);
1441   FD_ZERO (&awrite);
1442   FD_ZERO (&aexcept);
1443 #if DEBUG_NETWORK
1444   FD_ZERO (&bread);
1445   FD_ZERO (&bwrite);
1446   FD_ZERO (&bexcept);
1447 #endif
1448   if (rfds)
1449   {
1450     FD_COPY (&rfds->sds, &aread);
1451 #if DEBUG_NETWORK
1452     FD_COPY (&rfds->sds, &bread);
1453 #endif
1454   }
1455   if (wfds)
1456   {
1457     FD_COPY (&wfds->sds, &awrite);
1458 #if DEBUG_NETWORK
1459     FD_COPY (&wfds->sds, &bwrite);
1460 #endif
1461   }
1462   if (efds)
1463   {
1464     FD_COPY (&efds->sds, &aexcept);
1465 #if DEBUG_NETWORK
1466     FD_COPY (&efds->sds, &bexcept);
1467 #endif
1468   }
1469
1470   /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1471      By profiling we detected that to be true in 90% of the cases.
1472   */
1473
1474   /* Do the select now */
1475   select_timeout.tv_sec = 0;
1476   select_timeout.tv_usec = 0;
1477
1478   /* Copy all the writes to the except, so we can detect connect() errors */
1479   for (i = 0; i < awrite.fd_count; i++)
1480     FD_SET (awrite.fd_array[i], &aexcept);
1481   if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1482     selectret = select (1, (rfds != NULL) ? &aread : NULL,
1483         (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1484   else
1485     selectret = 0;
1486   if (selectret == -1)
1487   {
1488     /* Throw an error early on, while we still have the context. */
1489     LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1490         rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1491     GNUNET_abort ();
1492   }
1493
1494   /* Check aexcept, add its contents to awrite
1495      This is technically wrong (aexcept might have its own descriptors), we should
1496      have checked that descriptors were in awrite originally before re-adding them from
1497      aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1498   for (i = 0; i < aexcept.fd_count; i++)
1499     FD_SET (aexcept.fd_array[i], &awrite);
1500
1501   /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1502   /* Sadly, it means code duplication :( */
1503   if ((selectret > 0) || (ms_total == 0))
1504   {
1505     /* Read Pipes */
1506     if (rfds && read_handles)
1507     {
1508       struct GNUNET_CONTAINER_SList_Iterator i;
1509       int c;
1510
1511       for (c = 0, i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1512           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1513           GNUNET_CONTAINER_slist_next (&i), c++)
1514       {
1515         struct GNUNET_DISK_FileHandle *fh;
1516
1517         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1518         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1519         {
1520           DWORD error;
1521           BOOL bret;
1522
1523           SetLastError (0);
1524           DWORD waitstatus = 0;
1525           bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1526           error = GetLastError ();
1527           LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1528               c, fh->h, bret, waitstatus, error);
1529           if (bret == 0)
1530           {
1531             /* TODO: either add more errors to this condition, or eliminate it
1532              * entirely (failed to peek -> pipe is in serious trouble, should
1533              * be selected as readable).
1534              */
1535             if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1536               continue;
1537           }
1538           else if (waitstatus <= 0)
1539             continue;
1540           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1541               fh, sizeof (struct GNUNET_DISK_FileHandle));
1542           retcode++;
1543           LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1544               fh, fh->h);
1545         }
1546         else
1547         {
1548           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1549               fh, sizeof (struct GNUNET_DISK_FileHandle));
1550           retcode++;
1551         }
1552       }
1553     }
1554     if (wfds && write_handles)
1555     {
1556       LOG (GNUNET_ERROR_TYPE_DEBUG,
1557           "Adding the write ready event to the array as %d\n", nhandles);
1558       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1559       retcode += write_handles;
1560     }
1561     if (efds && ex_handles)
1562     {
1563       struct GNUNET_CONTAINER_SList_Iterator i;
1564
1565       for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1566           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1567           GNUNET_CONTAINER_slist_next (&i))
1568       {
1569         struct GNUNET_DISK_FileHandle *fh;
1570         DWORD dwBytes;
1571
1572         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1573         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1574         {
1575           if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1576             continue;
1577           GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1578               fh, sizeof (struct GNUNET_DISK_FileHandle));
1579           retcode++;
1580         }
1581       }
1582     }
1583
1584     /* Add our select() result.*/
1585     if (selectret >= 0)
1586       retcode += selectret;
1587
1588     if (rfds)
1589     {
1590       GNUNET_NETWORK_fdset_zero (rfds);
1591       if (selectret != -1)
1592         GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1593       GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1594     }
1595     if (wfds)
1596     {
1597       GNUNET_NETWORK_fdset_zero (wfds);
1598       if (selectret != -1)
1599         GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1600       GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1601     }
1602     if (efds)
1603     {
1604       GNUNET_NETWORK_fdset_zero (efds);
1605       if (selectret != -1)
1606         GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1607       GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1608     }
1609     GNUNET_CONTAINER_slist_destroy (handles_read);
1610     GNUNET_CONTAINER_slist_destroy (handles_write);
1611     GNUNET_CONTAINER_slist_destroy (handles_except);
1612
1613     if (selectret == -1)
1614       return -1;
1615     return retcode;
1616   }
1617
1618   /* If we got this far, use slower implementation that is able to do a waiting select
1619      on both sockets and pipes simultaneously */
1620
1621   /* Events for pipes */
1622   if (!hEventReadReady)
1623     hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1624   if (!hEventPipeWrite)
1625     hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1626   readPipes = 0;
1627   writePipePos = -1;
1628
1629   retcode = 0;
1630
1631   FD_ZERO (&aread);
1632   FD_ZERO (&awrite);
1633   FD_ZERO (&aexcept);
1634 #if DEBUG_NETWORK
1635   FD_ZERO (&bread);
1636   FD_ZERO (&bwrite);
1637   FD_ZERO (&bexcept);
1638 #endif
1639   if (rfds)
1640   {
1641     FD_COPY (&rfds->sds, &aread);
1642 #if DEBUG_NETWORK
1643     FD_COPY (&rfds->sds, &bread);
1644 #endif
1645   }
1646   if (wfds)
1647   {
1648     FD_COPY (&wfds->sds, &awrite);
1649 #if DEBUG_NETWORK
1650     FD_COPY (&wfds->sds, &bwrite);
1651 #endif
1652   }
1653   if (efds)
1654   {
1655     FD_COPY (&efds->sds, &aexcept);
1656 #if DEBUG_NETWORK
1657     FD_COPY (&efds->sds, &bexcept);
1658 #endif
1659   }
1660   /* We will first Add the PIPES to the events */
1661   /* Read Pipes */
1662   if (rfds && read_handles)
1663   {
1664     struct GNUNET_CONTAINER_SList_Iterator i;
1665
1666     for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1667          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1668          GNUNET_CONTAINER_slist_next (&i))
1669     {
1670       struct GNUNET_DISK_FileHandle *fh;
1671
1672       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1673                                                                          NULL);
1674       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1675       {
1676         /* Read zero bytes to check the status of the pipe */
1677         LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1678              fh->h);
1679         if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1680         {
1681           DWORD error_code = GetLastError ();
1682
1683           if (error_code == ERROR_IO_PENDING)
1684           {
1685             LOG (GNUNET_ERROR_TYPE_DEBUG,
1686                  "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1687                  fh->h, nhandles);
1688             handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1689             readArray[readPipes++] = fh;
1690           }
1691           else
1692           {
1693             LOG (GNUNET_ERROR_TYPE_DEBUG,
1694                  "Read failed, adding the read ready event to the array as %d\n", nhandles);
1695             handle_array[nhandles++] = hEventReadReady;
1696             readArray[readPipes++] = fh;
1697           }
1698         }
1699         else
1700         {
1701           LOG (GNUNET_ERROR_TYPE_DEBUG,
1702                "Adding the read ready event to the array as %d\n", nhandles);
1703           handle_array[nhandles++] = hEventReadReady;
1704           readArray[readPipes++] = fh;
1705         }
1706       }
1707       else
1708       {
1709         GNUNET_CONTAINER_slist_add (handles_read,
1710                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1711                                     fh, sizeof (struct GNUNET_DISK_FileHandle));
1712       }
1713     }
1714   }
1715   if (wfds && write_handles)
1716   {
1717     LOG (GNUNET_ERROR_TYPE_DEBUG,
1718          "Adding the write ready event to the array as %d\n", nhandles);
1719     handle_array[nhandles++] = hEventPipeWrite;
1720     writePipePos = nhandles;
1721   }
1722   if (efds && ex_handles)
1723   {
1724     struct GNUNET_CONTAINER_SList_Iterator i;
1725
1726     for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1727          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1728          GNUNET_CONTAINER_slist_next (&i))
1729     {
1730       struct GNUNET_DISK_FileHandle *fh;
1731       DWORD dwBytes;
1732
1733       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1734                                                                          NULL);
1735       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1736       {
1737         if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1738         {
1739           GNUNET_CONTAINER_slist_add (handles_except,
1740                                       GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1741                                       fh,
1742                                       sizeof (struct GNUNET_DISK_FileHandle));
1743         }
1744       }
1745     }
1746   }
1747
1748   sp.status = 0;
1749
1750   if (nfds > 0)
1751   {
1752     LOG (GNUNET_ERROR_TYPE_DEBUG,
1753          "Adding the socket event to the array as %d\n",
1754          nhandles);
1755     handle_array[nhandles++] = select_finished_event;
1756     if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1757       sp.tv = NULL;
1758     else
1759     {
1760       select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
1761       select_timeout.tv_usec =(timeout.rel_value_us -
1762           (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value_us));
1763       sp.tv = &select_timeout;
1764     }
1765     FD_SET (select_wakeup_socket, &aread);
1766     sp.r = &aread;
1767     sp.w = &awrite;
1768     sp.e = &aexcept;
1769     /* Failed connections cause sockets to be set in errorfds on W32,
1770      * but on POSIX it should set them in writefds.
1771      * First copy all awrite sockets to aexcept, later we'll
1772      * check aexcept and set its contents in awrite as well
1773      * Sockets are also set in errorfds when OOB data is available,
1774      * but we don't use OOB data.
1775      */
1776     for (i = 0; i < awrite.fd_count; i++)
1777       FD_SET (awrite.fd_array[i], &aexcept);
1778     ResetEvent (select_finished_event);
1779     SetEvent (select_standby_event);
1780   }
1781
1782   handle_array[nhandles] = NULL;
1783   LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n", 
1784        nfds, nhandles, (unsigned long long) ms_total);
1785   if (nhandles)
1786   {
1787     returncode =
1788         WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1789     LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1790          returncode);
1791   }
1792   else if (nfds > 0)
1793   {
1794     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1795     returncode = WAIT_TIMEOUT;
1796   }
1797   else
1798   {
1799     /* Shouldn't come this far. If it does - investigate. */
1800     GNUNET_assert (0);
1801   }
1802
1803   if (nfds > 0)
1804   {
1805     /* Don't wake up select-thread when delay is 0, it should return immediately
1806      * and wake up by itself.
1807      */
1808     if (ms_total != 0)
1809       i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1810     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1811     LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1812     if (ms_total != 0)
1813     {
1814       do
1815       {
1816         i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1817       } while (i == 1);
1818     }
1819     /* Check aexcept, add its contents to awrite */
1820     for (i = 0; i < aexcept.fd_count; i++)
1821       FD_SET (aexcept.fd_array[i], &awrite);
1822   }
1823
1824   returnedpos = returncode - WAIT_OBJECT_0;
1825   LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1826
1827   if (nhandles && (returnedpos < nhandles))
1828   {
1829     DWORD waitstatus;
1830
1831     if (sp.status > 0)
1832       retcode += sp.status;
1833
1834     if ((writePipePos != -1) && (returnedpos < writePipePos))
1835     {
1836       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1837       retcode += write_handles;
1838       LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1839     }
1840     LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1841     /* We have some pipes ready for read. */
1842     if (returnedpos < readPipes)
1843     {
1844       for (i = 0; i < readPipes; i++)
1845       {
1846         DWORD error;
1847         BOOL bret;
1848
1849         SetLastError (0);
1850         waitstatus = 0;
1851         bret =
1852             PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1853         error = GetLastError ();
1854         LOG (GNUNET_ERROR_TYPE_DEBUG,
1855              "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1856              i, readArray[i]->h, bret, waitstatus, error);
1857         if (bret == 0)
1858         {
1859           /* TODO: either add more errors to this condition, or eliminate it
1860            * entirely (failed to peek -> pipe is in serious trouble, should
1861            * be selected as readable).
1862            */
1863           if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1864             continue;
1865         }
1866         else if (waitstatus <= 0)
1867           continue;
1868         GNUNET_CONTAINER_slist_add (handles_read,
1869                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1870                                     readArray[i],
1871                                     sizeof (struct GNUNET_DISK_FileHandle));
1872         retcode++;
1873         LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1874              readArray[i], readArray[i]->h);
1875       }
1876     }
1877   }
1878   if (!nhandles || (returnedpos >= nhandles))
1879     LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1880   if (rfds)
1881   {
1882     struct GNUNET_CONTAINER_SList_Iterator t;
1883
1884     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1885          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1886          GNUNET_CONTAINER_slist_next (&t))
1887     {
1888       struct GNUNET_DISK_FileHandle *fh;
1889
1890       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1891                                                                          NULL);
1892       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1893       {
1894         CancelIo (fh->h);
1895       }
1896     }
1897     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1898     GNUNET_NETWORK_fdset_zero (rfds);
1899     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1900       GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1901     GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1902   }
1903   if (wfds)
1904   {
1905     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1906     GNUNET_NETWORK_fdset_zero (wfds);
1907     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1908       GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1909     GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1910   }
1911   if (efds)
1912   {
1913     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1914     GNUNET_NETWORK_fdset_zero (efds);
1915     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1916       GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1917     GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1918   }
1919   GNUNET_CONTAINER_slist_destroy (handles_read);
1920   GNUNET_CONTAINER_slist_destroy (handles_write);
1921   GNUNET_CONTAINER_slist_destroy (handles_except);
1922 #if DEBUG_NETWORK
1923   if (rfds)
1924   {
1925     struct GNUNET_CONTAINER_SList_Iterator t;
1926
1927     LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1928     for (i = 0; i < rfds->sds.fd_count; i++)
1929     {
1930       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1931     }
1932     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1933          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1934          GNUNET_CONTAINER_slist_next (&t))
1935     {
1936       struct GNUNET_DISK_FileHandle *fh;
1937
1938       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1939                                                                          NULL);
1940       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1941     }
1942   }
1943   if (wfds)
1944   {
1945     LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1946     for (i = 0; i < wfds->sds.fd_count; i++)
1947     {
1948       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1949     }
1950   }
1951   if (efds)
1952   {
1953     LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1954     for (i = 0; i < efds->sds.fd_count; i++)
1955     {
1956       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1957     }
1958   }
1959   LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1960 #endif
1961   if (nhandles && (returnedpos < nhandles))
1962     return retcode;
1963   else
1964 #endif
1965     return 0;
1966 }
1967
1968 /* end of network.c */