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