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