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