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