-fixing #2439
[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\r
1134 {\r
1135   fd_set *r;\r
1136   fd_set *w;\r
1137   fd_set *e;\r
1138   struct timeval *tv;\r
1139   HANDLE wakeup;\r
1140   HANDLE standby;\r
1141   SOCKET wakeup_socket;\r
1142   int status;\r
1143 };\r
1144
1145 static DWORD WINAPI\r
1146 _selector (LPVOID p)\r
1147 {\r
1148   struct _select_params *sp = p;\r
1149   int i;\r
1150   while (1)\r
1151   {\r
1152     WaitForSingleObject (sp->standby, INFINITE);\r
1153     ResetEvent (sp->standby);\r
1154     sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);\r
1155     if (FD_ISSET (sp->wakeup_socket, sp->r))\r
1156     {\r
1157       FD_CLR (sp->wakeup_socket, sp->r);\r
1158       sp->status -= 1;\r
1159     }\r
1160     SetEvent (sp->wakeup);\r
1161   }\r
1162   return 0;\r
1163 }\r
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;\r
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;\r
1201   static SOCKET select_send_socket = -1;\r
1202   static struct timeval select_timeout;
1203 \r
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     ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1300   /* select() may be used as a portable way to sleep */
1301   if (!(rfds || wfds || efds))
1302   {
1303     Sleep (ms_total);
1304     return 0;
1305   }
1306
1307   if (select_thread == NULL)
1308   {
1309     SOCKET select_listening_socket = -1;\r
1310     struct sockaddr_in s_in;\r
1311     int alen;\r
1312     int res;\r
1313     unsigned long p;\r
1314
1315     select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);\r
1316     select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);\r
1317
1318     select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);\r
1319 \r
1320     select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);\r
1321 \r
1322     p = 1;\r
1323     res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);\r
1324 \r
1325     alen = sizeof (s_in);\r
1326     s_in.sin_family = AF_INET;\r
1327     s_in.sin_port = 0;\r
1328     s_in.sin_addr.S_un.S_un_b.s_b1 = 127;\r
1329     s_in.sin_addr.S_un.S_un_b.s_b2 = 0;\r
1330     s_in.sin_addr.S_un.S_un_b.s_b3 = 0;\r
1331     s_in.sin_addr.S_un.S_un_b.s_b4 = 1;\r
1332     res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));\r
1333 \r
1334     res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);\r
1335 \r
1336     res = listen (select_listening_socket, SOMAXCONN);\r
1337 \r
1338     res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));\r
1339 \r
1340     select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);\r
1341 \r
1342     closesocket (select_listening_socket);\r
1343 \r
1344     sp.wakeup = select_finished_event;\r
1345     sp.standby = select_standby_event;\r
1346     sp.wakeup_socket = select_wakeup_socket;
1347 \r
1348     select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);\r
1349   }
1350
1351   /* Events for pipes */
1352   if (!hEventReadReady)
1353     hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1354   if (!hEventPipeWrite)
1355     hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1356   readPipes = 0;
1357   writePipePos = -1;
1358
1359   handles_read = GNUNET_CONTAINER_slist_create ();
1360   handles_write = GNUNET_CONTAINER_slist_create ();
1361   handles_except = GNUNET_CONTAINER_slist_create ();
1362   FD_ZERO (&aread);
1363   FD_ZERO (&awrite);
1364   FD_ZERO (&aexcept);
1365 #if DEBUG_NETWORK
1366   FD_ZERO (&bread);
1367   FD_ZERO (&bwrite);
1368   FD_ZERO (&bexcept);
1369 #endif
1370   if (rfds)
1371   {
1372     FD_COPY (&rfds->sds, &aread);
1373 #if DEBUG_NETWORK
1374     FD_COPY (&rfds->sds, &bread);
1375 #endif
1376   }
1377   if (wfds)
1378   {
1379     FD_COPY (&wfds->sds, &awrite);
1380 #if DEBUG_NETWORK
1381     FD_COPY (&wfds->sds, &bwrite);
1382 #endif
1383   }
1384   if (efds)
1385   {
1386     FD_COPY (&efds->sds, &aexcept);
1387 #if DEBUG_NETWORK
1388     FD_COPY (&efds->sds, &bexcept);
1389 #endif
1390   }
1391   /* We will first Add the PIPES to the events */
1392   /* Read Pipes */
1393   if (rfds && read_handles)
1394   {
1395     struct GNUNET_CONTAINER_SList_Iterator i;
1396
1397     for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1398          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1399          GNUNET_CONTAINER_slist_next (&i))
1400     {
1401       struct GNUNET_DISK_FileHandle *fh;
1402
1403       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1404                                                                          NULL);
1405       if (fh->type == GNUNET_PIPE)
1406       {
1407         /* Read zero bytes to check the status of the pipe */
1408         LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1409              fh->h);
1410         if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1411         {
1412           DWORD error_code = GetLastError ();
1413
1414           if (error_code == ERROR_IO_PENDING)
1415           {
1416             LOG (GNUNET_ERROR_TYPE_DEBUG,
1417                  "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1418                  fh->h, nhandles);
1419             handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1420             readArray[readPipes++] = fh;
1421           }
1422           else
1423           {
1424             LOG (GNUNET_ERROR_TYPE_DEBUG,
1425                  "Read failed, adding the read ready event to the array as %d\n", nhandles);
1426             handle_array[nhandles++] = hEventReadReady;
1427             readArray[readPipes++] = fh;
1428           }
1429         }
1430         else
1431         {
1432           LOG (GNUNET_ERROR_TYPE_DEBUG,
1433                "Adding the read ready event to the array as %d\n", nhandles);
1434           handle_array[nhandles++] = hEventReadReady;
1435           readArray[readPipes++] = fh;
1436         }
1437       }
1438       else
1439       {
1440         GNUNET_CONTAINER_slist_add (handles_read,
1441                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1442                                     fh, sizeof (struct GNUNET_DISK_FileHandle));
1443       }
1444     }
1445   }
1446   if (wfds && write_handles)
1447   {
1448     LOG (GNUNET_ERROR_TYPE_DEBUG,
1449          "Adding the write ready event to the array as %d\n", nhandles);
1450     handle_array[nhandles++] = hEventPipeWrite;
1451     writePipePos = nhandles;
1452   }
1453   if (efds && ex_handles)
1454   {
1455     struct GNUNET_CONTAINER_SList_Iterator i;
1456
1457     for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1458          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1459          GNUNET_CONTAINER_slist_next (&i))
1460     {
1461       struct GNUNET_DISK_FileHandle *fh;
1462       DWORD dwBytes;
1463
1464       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1465                                                                          NULL);
1466       if (fh->type == GNUNET_PIPE)
1467       {
1468         if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1469         {
1470           GNUNET_CONTAINER_slist_add (handles_except,
1471                                       GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1472                                       fh,
1473                                       sizeof (struct GNUNET_DISK_FileHandle));
1474         }
1475       }
1476     }
1477   }
1478
1479   sp.status = 0;
1480
1481   if (nfds > 0)
1482   {
1483     LOG (GNUNET_ERROR_TYPE_DEBUG,
1484          "Adding the socket event to the array as %d\n", nhandles);
1485     handle_array[nhandles++] = select_finished_event;
1486     if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1487       sp.tv = NULL;
1488     else
1489     {
1490       select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1491       select_timeout.tv_usec = 1000 * (timeout.rel_value -
1492           (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1493       sp.tv = &select_timeout;
1494     }
1495     FD_SET (select_wakeup_socket, &aread);
1496     sp.r = &aread;
1497     sp.w = &awrite;
1498     sp.e = &aexcept;
1499     /* Failed connections cause sockets to be set in errorfds on W32,
1500      * but on POSIX it should set them in writefds.
1501      * First copy all awrite sockets to aexcept, later we'll
1502      * check aexcept and set its contents in awrite as well
1503      * Sockets are also set in errorfds when OOB data is available,
1504      * but we don't use OOB data.
1505      */
1506     for (i = 0; i < awrite.fd_count; i++)
1507     {
1508       if (awrite.fd_array[i] != 0 && awrite.fd_array[i] != -1)
1509         FD_SET (awrite.fd_array[i], &aexcept);
1510     }
1511     ResetEvent (select_finished_event);
1512     SetEvent (select_standby_event);
1513   }
1514
1515   handle_array[nhandles] = NULL;
1516   LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %d ms\n", 
1517        nfds, nhandles, ms_total);
1518   if (nhandles)
1519     returncode =
1520         WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1521   LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1522        returncode);
1523
1524   if (nfds > 0)
1525   {
1526     /* Don't wake up select-thread when delay is 0, it should return immediately
1527      * and wake up by itself.
1528      */
1529     if (ms_total != 0)
1530       i = send (select_send_socket, (const char *) &returnedpos, 1, 0);\r
1531     i = (int) WaitForSingleObject (select_finished_event, INFINITE);\r
1532     LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1533     if (ms_total != 0)
1534     {
1535       do
1536       {
1537         i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);\r
1538       } while (i == 1);
1539     }
1540     /* Check aexcept, add its contents to awrite */
1541     for (i = 0; i < aexcept.fd_count; i++)
1542     {
1543       if (aexcept.fd_array[i] != 0 && aexcept.fd_array[i] != -1)
1544         FD_SET (aexcept.fd_array[i], &awrite);
1545     }
1546   }
1547
1548   returnedpos = returncode - WAIT_OBJECT_0;
1549   LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1550
1551   if (nhandles && (returnedpos < nhandles))
1552   {
1553     DWORD waitstatus;
1554
1555     if (sp.status > 0)
1556       retcode += sp.status;
1557
1558     if ((writePipePos != -1) && (returnedpos < writePipePos))
1559     {
1560       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1561       retcode += write_handles;
1562       LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1563     }
1564     LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1565     /* We have some pipes ready for read. */
1566     if (returnedpos < readPipes)
1567     {
1568       for (i = 0; i < readPipes; i++)
1569       {
1570         DWORD error;
1571         BOOL bret;
1572
1573         SetLastError (0);
1574         waitstatus = 0;
1575         bret =
1576             PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1577         error = GetLastError ();
1578         LOG (GNUNET_ERROR_TYPE_DEBUG,
1579              "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1580              i, readArray[i]->h, bret, waitstatus, error);
1581         if (bret == 0)
1582         {
1583           if (error != ERROR_BROKEN_PIPE)
1584             continue;
1585         }
1586         else if (waitstatus <= 0)
1587           continue;
1588         GNUNET_CONTAINER_slist_add (handles_read,
1589                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1590                                     readArray[i],
1591                                     sizeof (struct GNUNET_DISK_FileHandle));
1592         retcode++;
1593         LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1594              readArray[i], readArray[i]->h);
1595       }
1596     }
1597   }
1598   if (!nhandles || (returnedpos >= nhandles))
1599     LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1600   if (rfds)
1601   {
1602     struct GNUNET_CONTAINER_SList_Iterator t;
1603
1604     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1605          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1606          GNUNET_CONTAINER_slist_next (&t))
1607     {
1608       struct GNUNET_DISK_FileHandle *fh;
1609
1610       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1611                                                                          NULL);
1612       if (fh->type == GNUNET_PIPE)
1613       {
1614         CancelIo (fh->h);
1615       }
1616     }
1617     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1618     GNUNET_NETWORK_fdset_zero (rfds);
1619     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1620       GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1621     GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1622   }
1623   if (wfds)
1624   {
1625     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1626     GNUNET_NETWORK_fdset_zero (wfds);
1627     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1628       GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1629     GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1630   }
1631   if (efds)
1632   {
1633     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1634     GNUNET_NETWORK_fdset_zero (efds);
1635     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1636       GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1637     GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1638   }
1639   GNUNET_CONTAINER_slist_destroy (handles_read);
1640   GNUNET_CONTAINER_slist_destroy (handles_write);
1641   GNUNET_CONTAINER_slist_destroy (handles_except);
1642 #if DEBUG_NETWORK
1643   if (rfds)
1644   {
1645     struct GNUNET_CONTAINER_SList_Iterator t;
1646
1647     LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1648     for (i = 0; i < rfds->sds.fd_count; i++)
1649     {
1650       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1651     }
1652     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1653          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1654          GNUNET_CONTAINER_slist_next (&t))
1655     {
1656       struct GNUNET_DISK_FileHandle *fh;
1657
1658       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1659                                                                          NULL);
1660       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1661     }
1662   }
1663   if (wfds)
1664   {
1665     LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1666     for (i = 0; i < wfds->sds.fd_count; i++)
1667     {
1668       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1669     }
1670   }
1671   if (efds)
1672   {
1673     LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1674     for (i = 0; i < efds->sds.fd_count; i++)
1675     {
1676       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1677     }
1678   }
1679   LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1680 #endif
1681   if (nhandles && (returnedpos < nhandles))
1682     return retcode;
1683   else
1684 #endif
1685     return 0;
1686 }
1687
1688 /* end of network.c */