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