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