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