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