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