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