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