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