- verboser log, faster start
[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 (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   int i;
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
1384     alen = sizeof (s_in);
1385     s_in.sin_family = AF_INET;
1386     s_in.sin_port = 0;
1387     s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1388     s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1389     s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1390     s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1391     res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1392
1393     res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1394
1395     res = listen (select_listening_socket, SOMAXCONN);
1396
1397     res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1398
1399     select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1400
1401     closesocket (select_listening_socket);
1402
1403     sp.wakeup = select_finished_event;
1404     sp.standby = select_standby_event;
1405     sp.wakeup_socket = select_wakeup_socket;
1406
1407     select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1408   }
1409
1410
1411   handles_read = GNUNET_CONTAINER_slist_create ();
1412   handles_write = GNUNET_CONTAINER_slist_create ();
1413   handles_except = GNUNET_CONTAINER_slist_create ();
1414   FD_ZERO (&aread);
1415   FD_ZERO (&awrite);
1416   FD_ZERO (&aexcept);
1417 #if DEBUG_NETWORK
1418   FD_ZERO (&bread);
1419   FD_ZERO (&bwrite);
1420   FD_ZERO (&bexcept);
1421 #endif
1422   if (rfds)
1423   {
1424     FD_COPY (&rfds->sds, &aread);
1425 #if DEBUG_NETWORK
1426     FD_COPY (&rfds->sds, &bread);
1427 #endif
1428   }
1429   if (wfds)
1430   {
1431     FD_COPY (&wfds->sds, &awrite);
1432 #if DEBUG_NETWORK
1433     FD_COPY (&wfds->sds, &bwrite);
1434 #endif
1435   }
1436   if (efds)
1437   {
1438     FD_COPY (&efds->sds, &aexcept);
1439 #if DEBUG_NETWORK
1440     FD_COPY (&efds->sds, &bexcept);
1441 #endif
1442   }
1443
1444   /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1445      By profiling we detected that to be true in 90% of the cases.
1446   */
1447
1448   /* Do the select now */
1449   select_timeout.tv_sec = 0;
1450   select_timeout.tv_usec = 0;
1451
1452   /* Copy all the writes to the except, so we can detect connect() errors */
1453   for (i = 0; i < awrite.fd_count; i++)
1454     FD_SET (awrite.fd_array[i], &aexcept);
1455   if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1456     selectret = select (1, (rfds != NULL) ? &aread : NULL,
1457         (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1458   else
1459     selectret = 0;
1460   if (selectret == -1)
1461   {
1462     /* Throw an error early on, while we still have the context. */
1463     LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1464         rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1465     GNUNET_abort ();
1466   }
1467
1468   /* Check aexcept, add its contents to awrite
1469      This is technically wrong (aexcept might have its own descriptors), we should
1470      have checked that descriptors were in awrite originally before re-adding them from
1471      aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1472   for (i = 0; i < aexcept.fd_count; i++)
1473     FD_SET (aexcept.fd_array[i], &awrite);
1474
1475   /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1476   /* Sadly, it means code duplication :( */
1477   if ((selectret > 0) || (ms_total == 0))
1478   {
1479     /* Read Pipes */
1480     if (rfds && read_handles)
1481     {
1482       struct GNUNET_CONTAINER_SList_Iterator i;
1483
1484       for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1485           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1486           GNUNET_CONTAINER_slist_next (&i))
1487       {
1488         struct GNUNET_DISK_FileHandle *fh;
1489
1490         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1491         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1492         {
1493           DWORD error;
1494           BOOL bret;
1495
1496           SetLastError (0);
1497           DWORD waitstatus = 0;
1498           bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1499           error = GetLastError ();
1500           LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1501               i, fh->h, bret, waitstatus, error);
1502           if (bret == 0)
1503           {
1504             /* TODO: either add more errors to this condition, or eliminate it
1505              * entirely (failed to peek -> pipe is in serious trouble, should
1506              * be selected as readable).
1507              */
1508             if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1509               continue;
1510           }
1511           else if (waitstatus <= 0)
1512             continue;
1513           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1514               fh, sizeof (struct GNUNET_DISK_FileHandle));
1515           retcode++;
1516           LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1517               fh, fh->h);
1518         }
1519         else
1520         {
1521           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1522               fh, sizeof (struct GNUNET_DISK_FileHandle));
1523           retcode++;
1524         }
1525       }
1526     }
1527     if (wfds && write_handles)
1528     {
1529       LOG (GNUNET_ERROR_TYPE_DEBUG,
1530           "Adding the write ready event to the array as %d\n", nhandles);
1531       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1532       retcode += write_handles;
1533     }
1534     if (efds && ex_handles)
1535     {
1536       struct GNUNET_CONTAINER_SList_Iterator i;
1537
1538       for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1539           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1540           GNUNET_CONTAINER_slist_next (&i))
1541       {
1542         struct GNUNET_DISK_FileHandle *fh;
1543         DWORD dwBytes;
1544
1545         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1546         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1547         {
1548           if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1549             continue;
1550           GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1551               fh, sizeof (struct GNUNET_DISK_FileHandle));
1552           retcode++;
1553         }
1554       }
1555     }
1556
1557     /* Add our select() result.*/
1558     if (selectret >= 0)
1559       retcode += selectret;
1560
1561     if (rfds)
1562     {
1563       GNUNET_NETWORK_fdset_zero (rfds);
1564       if (selectret != -1)
1565         GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1566       GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1567     }
1568     if (wfds)
1569     {
1570       GNUNET_NETWORK_fdset_zero (wfds);
1571       if (selectret != -1)
1572         GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1573       GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1574     }
1575     if (efds)
1576     {
1577       GNUNET_NETWORK_fdset_zero (efds);
1578       if (selectret != -1)
1579         GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1580       GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1581     }
1582     GNUNET_CONTAINER_slist_destroy (handles_read);
1583     GNUNET_CONTAINER_slist_destroy (handles_write);
1584     GNUNET_CONTAINER_slist_destroy (handles_except);
1585
1586     if (selectret == -1)
1587       return -1;
1588     return retcode;
1589   }
1590
1591   /* If we got this far, use slower implementation that is able to do a waiting select
1592      on both sockets and pipes simultaneously */
1593
1594   /* Events for pipes */
1595   if (!hEventReadReady)
1596     hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1597   if (!hEventPipeWrite)
1598     hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1599   readPipes = 0;
1600   writePipePos = -1;
1601
1602   retcode = 0;
1603
1604   FD_ZERO (&aread);
1605   FD_ZERO (&awrite);
1606   FD_ZERO (&aexcept);
1607 #if DEBUG_NETWORK
1608   FD_ZERO (&bread);
1609   FD_ZERO (&bwrite);
1610   FD_ZERO (&bexcept);
1611 #endif
1612   if (rfds)
1613   {
1614     FD_COPY (&rfds->sds, &aread);
1615 #if DEBUG_NETWORK
1616     FD_COPY (&rfds->sds, &bread);
1617 #endif
1618   }
1619   if (wfds)
1620   {
1621     FD_COPY (&wfds->sds, &awrite);
1622 #if DEBUG_NETWORK
1623     FD_COPY (&wfds->sds, &bwrite);
1624 #endif
1625   }
1626   if (efds)
1627   {
1628     FD_COPY (&efds->sds, &aexcept);
1629 #if DEBUG_NETWORK
1630     FD_COPY (&efds->sds, &bexcept);
1631 #endif
1632   }
1633   /* We will first Add the PIPES to the events */
1634   /* Read Pipes */
1635   if (rfds && read_handles)
1636   {
1637     struct GNUNET_CONTAINER_SList_Iterator i;
1638
1639     for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1640          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1641          GNUNET_CONTAINER_slist_next (&i))
1642     {
1643       struct GNUNET_DISK_FileHandle *fh;
1644
1645       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1646                                                                          NULL);
1647       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1648       {
1649         /* Read zero bytes to check the status of the pipe */
1650         LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1651              fh->h);
1652         if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1653         {
1654           DWORD error_code = GetLastError ();
1655
1656           if (error_code == ERROR_IO_PENDING)
1657           {
1658             LOG (GNUNET_ERROR_TYPE_DEBUG,
1659                  "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1660                  fh->h, nhandles);
1661             handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1662             readArray[readPipes++] = fh;
1663           }
1664           else
1665           {
1666             LOG (GNUNET_ERROR_TYPE_DEBUG,
1667                  "Read failed, adding the read ready event to the array as %d\n", nhandles);
1668             handle_array[nhandles++] = hEventReadReady;
1669             readArray[readPipes++] = fh;
1670           }
1671         }
1672         else
1673         {
1674           LOG (GNUNET_ERROR_TYPE_DEBUG,
1675                "Adding the read ready event to the array as %d\n", nhandles);
1676           handle_array[nhandles++] = hEventReadReady;
1677           readArray[readPipes++] = fh;
1678         }
1679       }
1680       else
1681       {
1682         GNUNET_CONTAINER_slist_add (handles_read,
1683                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1684                                     fh, sizeof (struct GNUNET_DISK_FileHandle));
1685       }
1686     }
1687   }
1688   if (wfds && write_handles)
1689   {
1690     LOG (GNUNET_ERROR_TYPE_DEBUG,
1691          "Adding the write ready event to the array as %d\n", nhandles);
1692     handle_array[nhandles++] = hEventPipeWrite;
1693     writePipePos = nhandles;
1694   }
1695   if (efds && ex_handles)
1696   {
1697     struct GNUNET_CONTAINER_SList_Iterator i;
1698
1699     for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1700          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1701          GNUNET_CONTAINER_slist_next (&i))
1702     {
1703       struct GNUNET_DISK_FileHandle *fh;
1704       DWORD dwBytes;
1705
1706       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1707                                                                          NULL);
1708       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1709       {
1710         if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1711         {
1712           GNUNET_CONTAINER_slist_add (handles_except,
1713                                       GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1714                                       fh,
1715                                       sizeof (struct GNUNET_DISK_FileHandle));
1716         }
1717       }
1718     }
1719   }
1720
1721   sp.status = 0;
1722
1723   if (nfds > 0)
1724   {
1725     LOG (GNUNET_ERROR_TYPE_DEBUG,
1726          "Adding the socket event to the array as %d\n", nhandles);
1727     handle_array[nhandles++] = select_finished_event;
1728     if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1729       sp.tv = NULL;
1730     else
1731     {
1732       select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1733       select_timeout.tv_usec = 1000 * (timeout.rel_value -
1734           (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1735       sp.tv = &select_timeout;
1736     }
1737     FD_SET (select_wakeup_socket, &aread);
1738     sp.r = &aread;
1739     sp.w = &awrite;
1740     sp.e = &aexcept;
1741     /* Failed connections cause sockets to be set in errorfds on W32,
1742      * but on POSIX it should set them in writefds.
1743      * First copy all awrite sockets to aexcept, later we'll
1744      * check aexcept and set its contents in awrite as well
1745      * Sockets are also set in errorfds when OOB data is available,
1746      * but we don't use OOB data.
1747      */
1748     for (i = 0; i < awrite.fd_count; i++)
1749       FD_SET (awrite.fd_array[i], &aexcept);
1750     ResetEvent (select_finished_event);
1751     SetEvent (select_standby_event);
1752   }
1753
1754   handle_array[nhandles] = NULL;
1755   LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n", 
1756        nfds, nhandles, (unsigned long long) ms_total);
1757   if (nhandles)
1758   {
1759     returncode =
1760         WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1761     LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1762          returncode);
1763   }
1764   else if (nfds > 0)
1765   {
1766     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1767     returncode = WAIT_TIMEOUT;
1768   }
1769   else
1770   {
1771     /* Shouldn't come this far. If it does - investigate. */
1772     GNUNET_assert (0);
1773   }
1774
1775   if (nfds > 0)
1776   {
1777     /* Don't wake up select-thread when delay is 0, it should return immediately
1778      * and wake up by itself.
1779      */
1780     if (ms_total != 0)
1781       i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1782     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1783     LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1784     if (ms_total != 0)
1785     {
1786       do
1787       {
1788         i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1789       } while (i == 1);
1790     }
1791     /* Check aexcept, add its contents to awrite */
1792     for (i = 0; i < aexcept.fd_count; i++)
1793       FD_SET (aexcept.fd_array[i], &awrite);
1794   }
1795
1796   returnedpos = returncode - WAIT_OBJECT_0;
1797   LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1798
1799   if (nhandles && (returnedpos < nhandles))
1800   {
1801     DWORD waitstatus;
1802
1803     if (sp.status > 0)
1804       retcode += sp.status;
1805
1806     if ((writePipePos != -1) && (returnedpos < writePipePos))
1807     {
1808       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1809       retcode += write_handles;
1810       LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1811     }
1812     LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1813     /* We have some pipes ready for read. */
1814     if (returnedpos < readPipes)
1815     {
1816       for (i = 0; i < readPipes; i++)
1817       {
1818         DWORD error;
1819         BOOL bret;
1820
1821         SetLastError (0);
1822         waitstatus = 0;
1823         bret =
1824             PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1825         error = GetLastError ();
1826         LOG (GNUNET_ERROR_TYPE_DEBUG,
1827              "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1828              i, readArray[i]->h, bret, waitstatus, error);
1829         if (bret == 0)
1830         {
1831           /* TODO: either add more errors to this condition, or eliminate it
1832            * entirely (failed to peek -> pipe is in serious trouble, should
1833            * be selected as readable).
1834            */
1835           if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1836             continue;
1837         }
1838         else if (waitstatus <= 0)
1839           continue;
1840         GNUNET_CONTAINER_slist_add (handles_read,
1841                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1842                                     readArray[i],
1843                                     sizeof (struct GNUNET_DISK_FileHandle));
1844         retcode++;
1845         LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1846              readArray[i], readArray[i]->h);
1847       }
1848     }
1849   }
1850   if (!nhandles || (returnedpos >= nhandles))
1851     LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1852   if (rfds)
1853   {
1854     struct GNUNET_CONTAINER_SList_Iterator t;
1855
1856     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1857          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1858          GNUNET_CONTAINER_slist_next (&t))
1859     {
1860       struct GNUNET_DISK_FileHandle *fh;
1861
1862       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1863                                                                          NULL);
1864       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1865       {
1866         CancelIo (fh->h);
1867       }
1868     }
1869     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1870     GNUNET_NETWORK_fdset_zero (rfds);
1871     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1872       GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1873     GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1874   }
1875   if (wfds)
1876   {
1877     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1878     GNUNET_NETWORK_fdset_zero (wfds);
1879     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1880       GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1881     GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1882   }
1883   if (efds)
1884   {
1885     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1886     GNUNET_NETWORK_fdset_zero (efds);
1887     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1888       GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1889     GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1890   }
1891   GNUNET_CONTAINER_slist_destroy (handles_read);
1892   GNUNET_CONTAINER_slist_destroy (handles_write);
1893   GNUNET_CONTAINER_slist_destroy (handles_except);
1894 #if DEBUG_NETWORK
1895   if (rfds)
1896   {
1897     struct GNUNET_CONTAINER_SList_Iterator t;
1898
1899     LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1900     for (i = 0; i < rfds->sds.fd_count; i++)
1901     {
1902       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1903     }
1904     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1905          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1906          GNUNET_CONTAINER_slist_next (&t))
1907     {
1908       struct GNUNET_DISK_FileHandle *fh;
1909
1910       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1911                                                                          NULL);
1912       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1913     }
1914   }
1915   if (wfds)
1916   {
1917     LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1918     for (i = 0; i < wfds->sds.fd_count; i++)
1919     {
1920       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1921     }
1922   }
1923   if (efds)
1924   {
1925     LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1926     for (i = 0; i < efds->sds.fd_count; i++)
1927     {
1928       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1929     }
1930   }
1931   LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1932 #endif
1933   if (nhandles && (returnedpos < nhandles))
1934     return retcode;
1935   else
1936 #endif
1937     return 0;
1938 }
1939
1940 /* end of network.c */