- disable unix
[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       return GNUNET_YES;
1028     }
1029     GNUNET_CONTAINER_slist_next (&it);
1030   }
1031 #endif
1032   return GNUNET_NO;
1033 }
1034
1035
1036 /**
1037  * Creates an fd set
1038  * @return a new fd set
1039  */
1040 struct GNUNET_NETWORK_FDSet *
1041 GNUNET_NETWORK_fdset_create ()
1042 {
1043   struct GNUNET_NETWORK_FDSet *fds;
1044
1045   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1046 #ifdef MINGW
1047   fds->handles = GNUNET_CONTAINER_slist_create ();
1048 #endif
1049   GNUNET_NETWORK_fdset_zero (fds);
1050   return fds;
1051 }
1052
1053
1054 /**
1055  * Releases the associated memory of an fd set
1056  * @param fds fd set
1057  */
1058 void
1059 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1060 {
1061 #ifdef MINGW
1062   GNUNET_CONTAINER_slist_destroy (fds->handles);
1063 #endif
1064   GNUNET_free (fds);
1065 }
1066
1067 /**
1068  * Check if sockets meet certain conditions
1069  * @param rfds set of sockets to be checked for readability
1070  * @param wfds set of sockets to be checked for writability
1071  * @param efds set of sockets to be checked for exceptions
1072  * @param timeout relative value when to return
1073  * @return number of selected sockets, GNUNET_SYSERR on error
1074  */
1075 int
1076 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1077                               struct GNUNET_NETWORK_FDSet *wfds,
1078                               struct GNUNET_NETWORK_FDSet *efds,
1079                               const struct GNUNET_TIME_Relative timeout)
1080 {
1081   int nfds = 0;
1082
1083 #ifdef MINGW
1084   int handles = 0;
1085   int ex_handles = 0;
1086   int read_handles = 0;
1087   int write_handles = 0;
1088
1089   int i = 0;
1090   int retcode = 0;
1091   DWORD ms_total = 0;
1092
1093   int nsock = 0, nhandles = 0, nSockEvents = 0;
1094
1095   static HANDLE hEventRead = 0;
1096   static HANDLE hEventWrite = 0;
1097   static HANDLE hEventException = 0;
1098   static HANDLE hEventPipeWrite = 0;
1099   static HANDLE hEventReadReady = 0;
1100
1101   int readPipes = 0;
1102   int writePipePos = 0;
1103
1104   HANDLE handle_array[FD_SETSIZE + 2];
1105   int returncode = -1;
1106   DWORD newretcode = 0;
1107   int returnedpos = 0;
1108
1109   struct GNUNET_CONTAINER_SList *handles_read, *handles_write, *handles_except;
1110
1111   fd_set aread, awrite, aexcept;
1112
1113 #if DEBUG_NETWORK
1114   fd_set bread, bwrite, bexcept;
1115 #endif
1116
1117   /* TODO: Make this growable */
1118   struct GNUNET_DISK_FileHandle *readArray[50];
1119 #else
1120   struct timeval tv;
1121 #endif
1122   if (NULL != rfds)
1123   {
1124     nfds = rfds->nsds;
1125 #ifdef MINGW
1126     handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1127 #if DEBUG_NETWORK
1128     {
1129       struct GNUNET_CONTAINER_SList_Iterator t;
1130
1131       for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1132            GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1133            GNUNET_CONTAINER_slist_next (&t))
1134       {
1135         struct GNUNET_DISK_FileHandle *fh;
1136
1137         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1138                                                                            NULL);
1139         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1140              fh);
1141       }
1142     }
1143 #endif
1144 #endif
1145   }
1146   if (NULL != wfds)
1147   {
1148     nfds = GNUNET_MAX (nfds, wfds->nsds);
1149 #ifdef MINGW
1150     handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1151 #endif
1152   }
1153   if (NULL != efds)
1154   {
1155     nfds = GNUNET_MAX (nfds, efds->nsds);
1156 #ifdef MINGW
1157     handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1158 #endif
1159   }
1160
1161   if ((nfds == 0) &&
1162       (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1163 #ifdef MINGW
1164       && handles == 0
1165 #endif
1166       )
1167   {
1168     LOG (GNUNET_ERROR_TYPE_ERROR,
1169          _
1170          ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1171          "select");
1172     GNUNET_break (0);
1173   }
1174 #ifndef MINGW
1175   tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1176   tv.tv_usec =
1177       1000 * (timeout.rel_value -
1178               (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1179   return select (nfds, (rfds != NULL) ? &rfds->sds : NULL,
1180                  (wfds != NULL) ? &wfds->sds : NULL,
1181                  (efds != NULL) ? &efds->sds : NULL,
1182                  (timeout.rel_value ==
1183                   GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ? NULL : &tv);
1184
1185 #else
1186 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1187   /* calculate how long we need to wait in milliseconds */
1188   if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1189     ms_total = INFINITE;
1190   else
1191     ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1192   /* select() may be used as a portable way to sleep */
1193   if (!(rfds || wfds || efds))
1194   {
1195     Sleep (ms_total);
1196     return 0;
1197   }
1198
1199   /* Events for sockets */
1200   if (!hEventRead)
1201     hEventRead = CreateEvent (NULL, TRUE, FALSE, NULL);
1202   else
1203     ResetEvent (hEventRead);
1204   if (!hEventReadReady)
1205     hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1206   if (!hEventWrite)
1207     hEventWrite = CreateEvent (NULL, TRUE, FALSE, NULL);
1208   else
1209     ResetEvent (hEventWrite);
1210   if (!hEventException)
1211     hEventException = CreateEvent (NULL, TRUE, FALSE, NULL);
1212   else
1213     ResetEvent (hEventException);
1214
1215   /* Event for pipes */
1216   if (!hEventPipeWrite)
1217     hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1218   readPipes = 0;
1219   writePipePos = -1;
1220
1221   handles_read = GNUNET_CONTAINER_slist_create ();
1222   handles_write = GNUNET_CONTAINER_slist_create ();
1223   handles_except = GNUNET_CONTAINER_slist_create ();
1224   FD_ZERO (&aread);
1225   FD_ZERO (&awrite);
1226   FD_ZERO (&aexcept);
1227 #if DEBUG_NETWORK
1228   FD_ZERO (&bread);
1229   FD_ZERO (&bwrite);
1230   FD_ZERO (&bexcept);
1231 #endif
1232   if (rfds)
1233   {
1234     FD_COPY (&rfds->sds, &aread);
1235 #if DEBUG_NETWORK
1236     FD_COPY (&rfds->sds, &bread);
1237 #endif
1238   }
1239   if (wfds)
1240   {
1241     FD_COPY (&wfds->sds, &awrite);
1242 #if DEBUG_NETWORK
1243     FD_COPY (&wfds->sds, &bwrite);
1244 #endif
1245   }
1246   if (efds)
1247   {
1248     FD_COPY (&efds->sds, &aexcept);
1249 #if DEBUG_NETWORK
1250     FD_COPY (&efds->sds, &bexcept);
1251 #endif
1252   }
1253   /* We will first Add the PIPES to the events */
1254   /* Read Pipes */
1255   if (rfds && read_handles)
1256   {
1257     struct GNUNET_CONTAINER_SList_Iterator i;
1258
1259     for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1260          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1261          GNUNET_CONTAINER_slist_next (&i))
1262     {
1263       struct GNUNET_DISK_FileHandle *fh;
1264
1265       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1266                                                                          NULL);
1267       if (fh->type == GNUNET_PIPE)
1268       {
1269         /* Read zero bytes to check the status of the pipe */
1270         LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1271              fh->h);
1272         if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1273         {
1274           DWORD error_code = GetLastError ();
1275
1276           if (error_code == ERROR_IO_PENDING)
1277           {
1278             LOG (GNUNET_ERROR_TYPE_DEBUG,
1279                  "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1280                  fh->h, nhandles);
1281             handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1282             readArray[readPipes++] = fh;
1283           }
1284           else
1285           {
1286             LOG (GNUNET_ERROR_TYPE_DEBUG,
1287                  "Read failed, adding the read ready event to the array as %d\n", nhandles);
1288             handle_array[nhandles++] = hEventReadReady;
1289             readArray[readPipes++] = fh;
1290           }
1291         }
1292         else
1293         {
1294           LOG (GNUNET_ERROR_TYPE_DEBUG,
1295                "Adding the read ready event to the array as %d\n", nhandles);
1296           handle_array[nhandles++] = hEventReadReady;
1297           readArray[readPipes++] = fh;
1298         }
1299       }
1300       else
1301       {
1302         GNUNET_CONTAINER_slist_add (handles_read,
1303                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1304                                     fh, sizeof (struct GNUNET_DISK_FileHandle));
1305       }
1306     }
1307   }
1308   if (wfds && write_handles)
1309   {
1310     LOG (GNUNET_ERROR_TYPE_DEBUG,
1311          "Adding the write ready event to the array as %d\n", nhandles);
1312     handle_array[nhandles++] = hEventPipeWrite;
1313     writePipePos = nhandles;
1314   }
1315   if (efds && ex_handles)
1316   {
1317     struct GNUNET_CONTAINER_SList_Iterator i;
1318
1319     for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1320          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1321          GNUNET_CONTAINER_slist_next (&i))
1322     {
1323       struct GNUNET_DISK_FileHandle *fh;
1324       DWORD dwBytes;
1325
1326       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1327                                                                          NULL);
1328       if (fh->type == GNUNET_PIPE)
1329       {
1330         if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1331         {
1332           GNUNET_CONTAINER_slist_add (handles_except,
1333                                       GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1334                                       fh,
1335                                       sizeof (struct GNUNET_DISK_FileHandle));
1336           newretcode++;
1337         }
1338       }
1339     }
1340   }
1341   if (nfds > 0)
1342   {
1343     if (rfds)
1344     {
1345       LOG (GNUNET_ERROR_TYPE_DEBUG,
1346            "Adding the socket read event to the array as %d\n", nhandles);
1347       handle_array[nhandles++] = hEventRead;
1348       nSockEvents++;
1349       for (i = 0; i < rfds->sds.fd_count; i++)
1350       {
1351         WSAEventSelect (rfds->sds.fd_array[i], hEventRead,
1352                         FD_ACCEPT | FD_READ | FD_CLOSE);
1353         nsock++;
1354       }
1355     }
1356     if (wfds)
1357     {
1358       int wakeup = 0;
1359
1360       LOG (GNUNET_ERROR_TYPE_DEBUG,
1361            "Adding the socket write event to the array as %d\n", nhandles);
1362       handle_array[nhandles++] = hEventWrite;
1363       nSockEvents++;
1364       for (i = 0; i < wfds->sds.fd_count; i++)
1365       {
1366         DWORD error;
1367         int status;
1368
1369         status = send (wfds->sds.fd_array[i], NULL, 0, 0);
1370         error = GetLastError ();
1371         LOG (GNUNET_ERROR_TYPE_DEBUG,
1372              "pre-send to the socket %d returned %d (%u)\n", i, status, error);
1373         if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN))
1374           wakeup = 1;
1375         WSAEventSelect (wfds->sds.fd_array[i], hEventWrite,
1376                         FD_WRITE | FD_CONNECT | FD_CLOSE);
1377         nsock++;
1378       }
1379       if (wakeup)
1380         SetEvent (hEventWrite);
1381     }
1382     if (efds)
1383     {
1384       LOG (GNUNET_ERROR_TYPE_DEBUG,
1385            "Adding the socket error event to the array as %d\n", nhandles);
1386       handle_array[nhandles++] = hEventException;
1387       nSockEvents++;
1388       for (i = 0; i < efds->sds.fd_count; i++)
1389       {
1390         WSAEventSelect (efds->sds.fd_array[i], hEventException,
1391                         FD_OOB | FD_CLOSE);
1392         nsock++;
1393       }
1394     }
1395   }
1396
1397   handle_array[nhandles] = NULL;
1398   LOG (GNUNET_ERROR_TYPE_DEBUG, 
1399        "Number nfds: %d, handles: %d, return code: %u will wait: %d ms\n", 
1400        nfds, nhandles, newretcode, ms_total);
1401   if (nhandles)
1402     returncode =
1403         WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1404   LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1405        returncode);
1406
1407   returnedpos = returncode - WAIT_OBJECT_0;
1408   LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1409
1410   /* FIXME: THIS LINE IS WRONG !! We should add to handles only handles that fired the events, not all ! */
1411   /*
1412    * if(rfds)
1413    * GNUNET_CONTAINER_slist_append (handles_read, rfds->handles);
1414    */
1415   if (nhandles && (returnedpos < nhandles))
1416   {
1417     DWORD waitstatus;
1418
1419     /* Do the select */
1420     if (nfds)
1421     {
1422       struct timeval tvslice;
1423
1424       tvslice.tv_sec = 0;
1425       tvslice.tv_usec = 10;
1426       retcode = select (nfds, &aread, &awrite, &aexcept, &tvslice);
1427       if (retcode == -1)
1428         retcode = 0;
1429       LOG (GNUNET_ERROR_TYPE_DEBUG, "Select retcode : %d\n", retcode);
1430     }
1431     /* FIXME: <= writePipePos? Really? */
1432     if ((writePipePos != -1) && (returnedpos <= writePipePos))
1433     {
1434       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1435       retcode += write_handles;
1436       LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1437     }
1438     LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1439     /* We have some pipes ready for read. */
1440     /* FIXME: it is supposed to work !! Only choose the Pipes who fired the event, but it is not working */
1441
1442     if (returnedpos < readPipes)
1443     {
1444       /*
1445        * for (i = 0; i < readPipes; i++)
1446        * {
1447        * waitstatus = WaitForSingleObject (handle_array[i], 0);
1448        * LOG (GNUNET_ERROR_TYPE_DEBUG, "Read pipe %d wait status is : %d\n", i, waitstatus);
1449        * if (waitstatus != WAIT_OBJECT_0)
1450        * continue;
1451        * GNUNET_CONTAINER_slist_add (handles_read,
1452        * GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1453        * readArray[i], sizeof (struct GNUNET_DISK_FileHandle));
1454        * retcode++;
1455        * LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe\n");
1456        * }
1457        */
1458       for (i = 0; i < readPipes; i++)
1459       {
1460         DWORD error;
1461         BOOL bret;
1462
1463         SetLastError (0);
1464         waitstatus = 0;
1465         bret =
1466             PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1467         error = GetLastError ();
1468         LOG (GNUNET_ERROR_TYPE_DEBUG,
1469              "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1470              i, readArray[i]->h, bret, waitstatus, error);
1471         if (bret == 0)
1472         {
1473           if (error != ERROR_BROKEN_PIPE)
1474             continue;
1475         }
1476         else if (waitstatus <= 0)
1477           continue;
1478         GNUNET_CONTAINER_slist_add (handles_read,
1479                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1480                                     readArray[i],
1481                                     sizeof (struct GNUNET_DISK_FileHandle));
1482         retcode++;
1483         LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1484              readArray[i], readArray[i]->h);
1485       }
1486     }
1487     waitstatus = WaitForSingleObject (hEventWrite, 0);
1488     LOG (GNUNET_ERROR_TYPE_DEBUG, "Wait for the write event returned %d\n",
1489          waitstatus);
1490     if (waitstatus == WAIT_OBJECT_0)
1491     {
1492       for (i = 0; i < wfds->sds.fd_count; i++)
1493       {
1494         DWORD error;
1495         int status;
1496         int so_error = 0;
1497         int sizeof_so_error = sizeof (so_error);
1498         int gso_result =
1499             getsockopt (wfds->sds.fd_array[i], SOL_SOCKET, SO_ERROR,
1500                         (char *) &so_error, &sizeof_so_error);
1501
1502         status = send (wfds->sds.fd_array[i], NULL, 0, 0);
1503         error = GetLastError ();
1504         LOG (GNUNET_ERROR_TYPE_DEBUG,
1505              "send to the socket %d returned %d (%u)\n", i, status, error);
1506         if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN) ||
1507             (status == -1 && gso_result == 0 && error == WSAENOTCONN &&
1508              so_error == WSAECONNREFUSED))
1509         {
1510           FD_SET (wfds->sds.fd_array[i], &awrite);
1511           retcode += 1;
1512         }
1513       }
1514     }
1515   }
1516   if (!nhandles || (returnedpos >= nhandles))
1517     LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1518   if (rfds)
1519   {
1520     struct GNUNET_CONTAINER_SList_Iterator t;
1521
1522     for (i = 0; i < rfds->sds.fd_count; i++)
1523     {
1524       WSAEventSelect (rfds->sds.fd_array[i], hEventRead, 0);
1525       nsock++;
1526     }
1527     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1528          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1529          GNUNET_CONTAINER_slist_next (&t))
1530     {
1531       struct GNUNET_DISK_FileHandle *fh;
1532
1533       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1534                                                                          NULL);
1535       if (fh->type == GNUNET_PIPE)
1536       {
1537         CancelIo (fh->h);
1538       }
1539     }
1540     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds\n");
1541     GNUNET_NETWORK_fdset_zero (rfds);
1542     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1543       GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1544     GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1545   }
1546   if (wfds)
1547   {
1548     for (i = 0; i < wfds->sds.fd_count; i++)
1549     {
1550       WSAEventSelect (wfds->sds.fd_array[i], hEventWrite, 0);
1551       nsock++;
1552     }
1553     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds\n");
1554     GNUNET_NETWORK_fdset_zero (wfds);
1555     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1556       GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1557     GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1558   }
1559   if (efds)
1560   {
1561     for (i = 0; i < efds->sds.fd_count; i++)
1562     {
1563       WSAEventSelect (efds->sds.fd_array[i], hEventException, 0);
1564       nsock++;
1565     }
1566     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds\n");
1567     GNUNET_NETWORK_fdset_zero (efds);
1568     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1569       GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1570     GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1571   }
1572   GNUNET_CONTAINER_slist_destroy (handles_read);
1573   GNUNET_CONTAINER_slist_destroy (handles_write);
1574   GNUNET_CONTAINER_slist_destroy (handles_except);
1575 #if DEBUG_NETWORK
1576   if (rfds)
1577   {
1578     struct GNUNET_CONTAINER_SList_Iterator t;
1579
1580     for (i = 0; i < bread.fd_count; i++)
1581     {
1582       if (bread.fd_array[i] != 0)
1583         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in rfds\n",
1584              bread.fd_array[i],
1585              (SAFE_FD_ISSET (bread.fd_array[i], rfds)) ? "SET" : "NOT SET");
1586     }
1587     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1588          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1589          GNUNET_CONTAINER_slist_next (&t))
1590     {
1591       struct GNUNET_DISK_FileHandle *fh;
1592
1593       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1594                                                                          NULL);
1595       LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is SET in rfds\n", fh->h);
1596     }
1597   }
1598   if (wfds)
1599   {
1600     for (i = 0; i < bwrite.fd_count; i++)
1601     {
1602       if (bwrite.fd_array[i] != 0)
1603         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in wfds\n",
1604              bwrite.fd_array[i],
1605              (SAFE_FD_ISSET (bwrite.fd_array[i], rfds)) ? "SET" : "NOT SET");
1606     }
1607   }
1608   if (efds)
1609   {
1610     for (i = 0; i < bexcept.fd_count; i++)
1611     {
1612       if (bexcept.fd_array[i] != 0)
1613         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in efds\n",
1614              bexcept.fd_array[i],
1615              (SAFE_FD_ISSET (bexcept.fd_array[i], rfds)) ? "SET" : "NOT SET");
1616     }
1617   }
1618   LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1619 #endif
1620   if (nhandles && (returnedpos < nhandles))
1621     return retcode;
1622   else
1623 #endif
1624     return 0;
1625 }
1626
1627 /* end of network.c */