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