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