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