972f93849958f8ea448887a62527dd00a3b0799d
[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  * Return sockaddr for this network handle
870  *
871  * @param desc wrapper to process
872  * @return sockaddr
873  */
874 struct sockaddr*
875 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
876 {
877   return desc->addr;
878 }
879
880 /**
881  * Return sockaddr length for this network handle
882  *
883  * @param desc wrapper to process
884  * @return socklen_t for sockaddr
885  */
886 socklen_t
887 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
888 {
889   return desc->addrlen;
890 }
891 /**
892  * Copy a native fd set
893  *
894  * @param to destination
895  * @param from native source set
896  * @param nfds the biggest socket number in from + 1
897  */
898 void
899 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
900                                   const fd_set * from, int nfds)
901 {
902   FD_COPY (from, &to->sds);
903   to->nsds = nfds;
904 }
905
906
907 /**
908  * Set a native fd in a set
909  *
910  * @param to destination
911  * @param nfd native FD to set
912  */
913 void
914 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
915 {
916   GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
917   FD_SET (nfd, &to->sds);
918   to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
919 }
920
921
922 /**
923  * Test native fd in a set
924  *
925  * @param to set to test, NULL for empty set
926  * @param nfd native FD to test, or -1 for none
927  * @return GNUNET_YES if FD is set in the set
928  */
929 int
930 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
931                                   int nfd)
932 {
933   if ((nfd == -1) || (to == NULL))
934     return GNUNET_NO;
935   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
936 }
937
938
939 /**
940  * Add a file handle to the fd set
941  * @param fds fd set
942  * @param h the file handle to add
943  */
944 void
945 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
946                                  const struct GNUNET_DISK_FileHandle *h)
947 {
948 #ifdef MINGW
949   GNUNET_CONTAINER_slist_add (fds->handles,
950                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
951                               sizeof (struct GNUNET_DISK_FileHandle));
952
953 #else
954   int fd;
955
956   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
957   FD_SET (fd, &fds->sds);
958   if (fd + 1 > fds->nsds)
959     fds->nsds = fd + 1;
960
961 #endif
962 }
963
964
965 /**
966  * Check if a file handle is part of an fd set
967  * @param fds fd set
968  * @param h file handle
969  * @return GNUNET_YES if the file handle is part of the set
970  */
971 int
972 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
973                                    const struct GNUNET_DISK_FileHandle *h)
974 {
975
976 #ifdef MINGW
977   return GNUNET_CONTAINER_slist_contains (fds->handles, h,
978                                           sizeof (struct
979                                                   GNUNET_DISK_FileHandle));
980 #else
981   return FD_ISSET (h->fd, &fds->sds);
982 #endif
983 }
984
985
986 /**
987  * Checks if two fd sets overlap
988  * @param fds1 first fd set
989  * @param fds2 second fd set
990  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
991  */
992 int
993 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
994                               const struct GNUNET_NETWORK_FDSet *fds2)
995 {
996 #ifndef MINGW
997   int nfds;
998
999   nfds = fds1->nsds;
1000   if (nfds > fds2->nsds)
1001     nfds = fds2->nsds;
1002   while (nfds > 0)
1003   {
1004     nfds--;
1005     if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1006       return GNUNET_YES;
1007   }
1008 #else
1009   struct GNUNET_CONTAINER_SList_Iterator it;
1010   struct GNUNET_DISK_FileHandle *h;
1011   int i;
1012   int j;
1013
1014   /*This code is somewhat hacky, we are not supposed to know what's
1015    * inside of fd_set; also the O(n^2) is really bad... */
1016
1017   for (i = 0; i < fds1->sds.fd_count; i++)
1018   {
1019     for (j = 0; j < fds2->sds.fd_count; j++)
1020     {
1021       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1022         return GNUNET_YES;
1023     }
1024   }
1025   it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1026   while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1027   {
1028 #if DEBUG_NETWORK
1029     struct GNUNET_CONTAINER_SList_Iterator t;
1030 #endif
1031     h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1032                                                                       NULL);
1033 #if DEBUG_NETWORK
1034     LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1035          h->h);
1036     for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1037          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1038          GNUNET_CONTAINER_slist_next (&t))
1039     {
1040       struct GNUNET_DISK_FileHandle *fh;
1041
1042       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1043                                                                          NULL);
1044       LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1045     }
1046 #endif
1047     if (GNUNET_CONTAINER_slist_contains
1048         (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1049     {
1050       return GNUNET_YES;
1051     }
1052     GNUNET_CONTAINER_slist_next (&it);
1053   }
1054 #endif
1055   return GNUNET_NO;
1056 }
1057
1058
1059 /**
1060  * Creates an fd set
1061  * @return a new fd set
1062  */
1063 struct GNUNET_NETWORK_FDSet *
1064 GNUNET_NETWORK_fdset_create ()
1065 {
1066   struct GNUNET_NETWORK_FDSet *fds;
1067
1068   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1069 #ifdef MINGW
1070   fds->handles = GNUNET_CONTAINER_slist_create ();
1071 #endif
1072   GNUNET_NETWORK_fdset_zero (fds);
1073   return fds;
1074 }
1075
1076
1077 /**
1078  * Releases the associated memory of an fd set
1079  * @param fds fd set
1080  */
1081 void
1082 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1083 {
1084 #ifdef MINGW
1085   GNUNET_CONTAINER_slist_destroy (fds->handles);
1086 #endif
1087   GNUNET_free (fds);
1088 }
1089
1090 /**
1091  * Check if sockets meet certain conditions
1092  * @param rfds set of sockets to be checked for readability
1093  * @param wfds set of sockets to be checked for writability
1094  * @param efds set of sockets to be checked for exceptions
1095  * @param timeout relative value when to return
1096  * @return number of selected sockets, GNUNET_SYSERR on error
1097  */
1098 int
1099 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1100                               struct GNUNET_NETWORK_FDSet *wfds,
1101                               struct GNUNET_NETWORK_FDSet *efds,
1102                               const struct GNUNET_TIME_Relative timeout)
1103 {
1104   int nfds = 0;
1105 #ifdef MINGW
1106   int handles = 0;
1107   int ex_handles = 0;
1108   int read_handles = 0;
1109   int write_handles = 0;
1110
1111   int i = 0;
1112   int retcode = 0;
1113   DWORD ms_total = 0;
1114
1115   int nsock = 0;
1116   int nhandles = 0;
1117   int nSockEvents = 0;
1118
1119   static HANDLE hEventRead = 0;
1120   static HANDLE hEventWrite = 0;
1121   static HANDLE hEventException = 0;
1122   static HANDLE hEventPipeWrite = 0;
1123   static HANDLE hEventReadReady = 0;
1124
1125   int readPipes = 0;
1126   int writePipePos = 0;
1127
1128   HANDLE handle_array[FD_SETSIZE + 2];
1129   int returncode = -1;
1130   DWORD newretcode = 0;
1131   int returnedpos = 0;
1132
1133   struct GNUNET_CONTAINER_SList *handles_read;
1134   struct GNUNET_CONTAINER_SList *handles_write;
1135   struct GNUNET_CONTAINER_SList *handles_except;
1136
1137   fd_set aread;
1138   fd_set awrite;
1139   fd_set aexcept;
1140
1141 #if DEBUG_NETWORK
1142   fd_set bread;
1143   fd_set bwrite;
1144   fd_set bexcept;
1145 #endif
1146
1147   /* TODO: Make this growable */
1148   struct GNUNET_DISK_FileHandle *readArray[50];
1149 #else
1150   struct timeval tv;
1151 #endif
1152   if (NULL != rfds)
1153   {
1154     nfds = rfds->nsds;
1155 #ifdef MINGW
1156     handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1157 #if DEBUG_NETWORK
1158     {
1159       struct GNUNET_CONTAINER_SList_Iterator t;
1160
1161       for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1162            GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1163            GNUNET_CONTAINER_slist_next (&t))
1164       {
1165         struct GNUNET_DISK_FileHandle *fh;
1166
1167         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1168                                                                            NULL);
1169         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1170              fh);
1171       }
1172     }
1173 #endif
1174 #endif
1175   }
1176   if (NULL != wfds)
1177   {
1178     nfds = GNUNET_MAX (nfds, wfds->nsds);
1179 #ifdef MINGW
1180     handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1181 #endif
1182   }
1183   if (NULL != efds)
1184   {
1185     nfds = GNUNET_MAX (nfds, efds->nsds);
1186 #ifdef MINGW
1187     handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1188 #endif
1189   }
1190
1191   if ((nfds == 0) &&
1192       (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1193 #ifdef MINGW
1194       && handles == 0
1195 #endif
1196       )
1197   {
1198     LOG (GNUNET_ERROR_TYPE_ERROR,
1199          _
1200          ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1201          "select");
1202     GNUNET_break (0);
1203   }
1204 #ifndef MINGW
1205   tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1206   tv.tv_usec =
1207       1000 * (timeout.rel_value -
1208               (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1209   return select (nfds, (rfds != NULL) ? &rfds->sds : NULL,
1210                  (wfds != NULL) ? &wfds->sds : NULL,
1211                  (efds != NULL) ? &efds->sds : NULL,
1212                  (timeout.rel_value ==
1213                   GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ? NULL : &tv);
1214
1215 #else
1216 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1217   /* calculate how long we need to wait in milliseconds */
1218   if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1219     ms_total = INFINITE;
1220   else
1221     ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1222   /* select() may be used as a portable way to sleep */
1223   if (!(rfds || wfds || efds))
1224   {
1225     Sleep (ms_total);
1226     return 0;
1227   }
1228
1229   /* Events for sockets */
1230   if (!hEventRead)
1231     hEventRead = CreateEvent (NULL, TRUE, FALSE, NULL);
1232   else
1233     ResetEvent (hEventRead);
1234   if (!hEventReadReady)
1235     hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1236   if (!hEventWrite)
1237     hEventWrite = CreateEvent (NULL, TRUE, FALSE, NULL);
1238   else
1239     ResetEvent (hEventWrite);
1240   if (!hEventException)
1241     hEventException = CreateEvent (NULL, TRUE, FALSE, NULL);
1242   else
1243     ResetEvent (hEventException);
1244
1245   /* Event for pipes */
1246   if (!hEventPipeWrite)
1247     hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1248   readPipes = 0;
1249   writePipePos = -1;
1250
1251   handles_read = GNUNET_CONTAINER_slist_create ();
1252   handles_write = GNUNET_CONTAINER_slist_create ();
1253   handles_except = GNUNET_CONTAINER_slist_create ();
1254   FD_ZERO (&aread);
1255   FD_ZERO (&awrite);
1256   FD_ZERO (&aexcept);
1257 #if DEBUG_NETWORK
1258   FD_ZERO (&bread);
1259   FD_ZERO (&bwrite);
1260   FD_ZERO (&bexcept);
1261 #endif
1262   if (rfds)
1263   {
1264     FD_COPY (&rfds->sds, &aread);
1265 #if DEBUG_NETWORK
1266     FD_COPY (&rfds->sds, &bread);
1267 #endif
1268   }
1269   if (wfds)
1270   {
1271     FD_COPY (&wfds->sds, &awrite);
1272 #if DEBUG_NETWORK
1273     FD_COPY (&wfds->sds, &bwrite);
1274 #endif
1275   }
1276   if (efds)
1277   {
1278     FD_COPY (&efds->sds, &aexcept);
1279 #if DEBUG_NETWORK
1280     FD_COPY (&efds->sds, &bexcept);
1281 #endif
1282   }
1283   /* We will first Add the PIPES to the events */
1284   /* Read Pipes */
1285   if (rfds && read_handles)
1286   {
1287     struct GNUNET_CONTAINER_SList_Iterator i;
1288
1289     for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1290          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1291          GNUNET_CONTAINER_slist_next (&i))
1292     {
1293       struct GNUNET_DISK_FileHandle *fh;
1294
1295       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1296                                                                          NULL);
1297       if (fh->type == GNUNET_PIPE)
1298       {
1299         /* Read zero bytes to check the status of the pipe */
1300         LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1301              fh->h);
1302         if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1303         {
1304           DWORD error_code = GetLastError ();
1305
1306           if (error_code == ERROR_IO_PENDING)
1307           {
1308             LOG (GNUNET_ERROR_TYPE_DEBUG,
1309                  "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1310                  fh->h, nhandles);
1311             handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1312             readArray[readPipes++] = fh;
1313           }
1314           else
1315           {
1316             LOG (GNUNET_ERROR_TYPE_DEBUG,
1317                  "Read failed, adding the read ready event to the array as %d\n", nhandles);
1318             handle_array[nhandles++] = hEventReadReady;
1319             readArray[readPipes++] = fh;
1320           }
1321         }
1322         else
1323         {
1324           LOG (GNUNET_ERROR_TYPE_DEBUG,
1325                "Adding the read ready event to the array as %d\n", nhandles);
1326           handle_array[nhandles++] = hEventReadReady;
1327           readArray[readPipes++] = fh;
1328         }
1329       }
1330       else
1331       {
1332         GNUNET_CONTAINER_slist_add (handles_read,
1333                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1334                                     fh, sizeof (struct GNUNET_DISK_FileHandle));
1335       }
1336     }
1337   }
1338   if (wfds && write_handles)
1339   {
1340     LOG (GNUNET_ERROR_TYPE_DEBUG,
1341          "Adding the write ready event to the array as %d\n", nhandles);
1342     handle_array[nhandles++] = hEventPipeWrite;
1343     writePipePos = nhandles;
1344   }
1345   if (efds && ex_handles)
1346   {
1347     struct GNUNET_CONTAINER_SList_Iterator i;
1348
1349     for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1350          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1351          GNUNET_CONTAINER_slist_next (&i))
1352     {
1353       struct GNUNET_DISK_FileHandle *fh;
1354       DWORD dwBytes;
1355
1356       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1357                                                                          NULL);
1358       if (fh->type == GNUNET_PIPE)
1359       {
1360         if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1361         {
1362           GNUNET_CONTAINER_slist_add (handles_except,
1363                                       GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1364                                       fh,
1365                                       sizeof (struct GNUNET_DISK_FileHandle));
1366           newretcode++;
1367         }
1368       }
1369     }
1370   }
1371   if (nfds > 0)
1372   {
1373     if (rfds)
1374     {
1375       LOG (GNUNET_ERROR_TYPE_DEBUG,
1376            "Adding the socket read event to the array as %d\n", nhandles);
1377       handle_array[nhandles++] = hEventRead;
1378       nSockEvents++;
1379       for (i = 0; i < rfds->sds.fd_count; i++)
1380       {
1381         WSAEventSelect (rfds->sds.fd_array[i], hEventRead,
1382                         FD_ACCEPT | FD_READ | FD_CLOSE);
1383         nsock++;
1384       }
1385     }
1386     if (wfds)
1387     {
1388       int wakeup = 0;
1389
1390       LOG (GNUNET_ERROR_TYPE_DEBUG,
1391            "Adding the socket write event to the array as %d\n", nhandles);
1392       handle_array[nhandles++] = hEventWrite;
1393       nSockEvents++;
1394       for (i = 0; i < wfds->sds.fd_count; i++)
1395       {
1396         DWORD error;
1397         int status;
1398
1399         status = send (wfds->sds.fd_array[i], NULL, 0, 0);
1400         error = GetLastError ();
1401         LOG (GNUNET_ERROR_TYPE_DEBUG,
1402              "pre-send to the socket %d returned %d (%u)\n", i, status, error);
1403         if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN))
1404           wakeup = 1;
1405         WSAEventSelect (wfds->sds.fd_array[i], hEventWrite,
1406                         FD_WRITE | FD_CONNECT | FD_CLOSE);
1407         nsock++;
1408       }
1409       if (wakeup)
1410         SetEvent (hEventWrite);
1411     }
1412     if (efds)
1413     {
1414       LOG (GNUNET_ERROR_TYPE_DEBUG,
1415            "Adding the socket error event to the array as %d\n", nhandles);
1416       handle_array[nhandles++] = hEventException;
1417       nSockEvents++;
1418       for (i = 0; i < efds->sds.fd_count; i++)
1419       {
1420         WSAEventSelect (efds->sds.fd_array[i], hEventException,
1421                         FD_OOB | FD_CLOSE);
1422         nsock++;
1423       }
1424     }
1425   }
1426
1427   handle_array[nhandles] = NULL;
1428   LOG (GNUNET_ERROR_TYPE_DEBUG, 
1429        "Number nfds: %d, handles: %d, return code: %u will wait: %d ms\n", 
1430        nfds, nhandles, newretcode, ms_total);
1431   if (nhandles)
1432     returncode =
1433         WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1434   LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1435        returncode);
1436
1437   returnedpos = returncode - WAIT_OBJECT_0;
1438   LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1439
1440   /* FIXME: THIS LINE IS WRONG !! We should add to handles only handles that fired the events, not all ! */
1441   /*
1442    * if(rfds)
1443    * GNUNET_CONTAINER_slist_append (handles_read, rfds->handles);
1444    */
1445   if (nhandles && (returnedpos < nhandles))
1446   {
1447     DWORD waitstatus;
1448
1449     /* Do the select */
1450     if (nfds)
1451     {
1452       struct timeval tvslice;
1453
1454       tvslice.tv_sec = 0;
1455       tvslice.tv_usec = 0;
1456       retcode = select (nfds, &aread, &awrite, &aexcept, &tvslice);
1457       if (retcode == -1)
1458         retcode = 0;
1459       LOG (GNUNET_ERROR_TYPE_DEBUG, "Select retcode : %d\n", retcode);
1460     }
1461     /* FIXME: <= writePipePos? Really? */
1462     if ((writePipePos != -1) && (returnedpos <= writePipePos))
1463     {
1464       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1465       retcode += write_handles;
1466       LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1467     }
1468     LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1469     /* We have some pipes ready for read. */
1470     /* FIXME: it is supposed to work !! Only choose the Pipes who fired the event, but it is not working */
1471
1472     if (returnedpos < readPipes)
1473     {
1474       /*
1475        * for (i = 0; i < readPipes; i++)
1476        * {
1477        * waitstatus = WaitForSingleObject (handle_array[i], 0);
1478        * LOG (GNUNET_ERROR_TYPE_DEBUG, "Read pipe %d wait status is : %d\n", i, waitstatus);
1479        * if (waitstatus != WAIT_OBJECT_0)
1480        * continue;
1481        * GNUNET_CONTAINER_slist_add (handles_read,
1482        * GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1483        * readArray[i], sizeof (struct GNUNET_DISK_FileHandle));
1484        * retcode++;
1485        * LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe\n");
1486        * }
1487        */
1488       for (i = 0; i < readPipes; i++)
1489       {
1490         DWORD error;
1491         BOOL bret;
1492
1493         SetLastError (0);
1494         waitstatus = 0;
1495         bret =
1496             PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1497         error = GetLastError ();
1498         LOG (GNUNET_ERROR_TYPE_DEBUG,
1499              "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1500              i, readArray[i]->h, bret, waitstatus, error);
1501         if (bret == 0)
1502         {
1503           if (error != ERROR_BROKEN_PIPE)
1504             continue;
1505         }
1506         else if (waitstatus <= 0)
1507           continue;
1508         GNUNET_CONTAINER_slist_add (handles_read,
1509                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1510                                     readArray[i],
1511                                     sizeof (struct GNUNET_DISK_FileHandle));
1512         retcode++;
1513         LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1514              readArray[i], readArray[i]->h);
1515       }
1516     }
1517     waitstatus = WaitForSingleObject (hEventWrite, 0);
1518     LOG (GNUNET_ERROR_TYPE_DEBUG, "Wait for the write event returned %d\n",
1519          waitstatus);
1520     if (waitstatus == WAIT_OBJECT_0)
1521     {
1522       for (i = 0; i < wfds->sds.fd_count; i++)
1523       {
1524         DWORD error;
1525         int status;
1526         int so_error = 0;
1527         int sizeof_so_error = sizeof (so_error);
1528         int gso_result =
1529             getsockopt (wfds->sds.fd_array[i], SOL_SOCKET, SO_ERROR,
1530                         (char *) &so_error, &sizeof_so_error);
1531
1532         status = send (wfds->sds.fd_array[i], NULL, 0, 0);
1533         error = GetLastError ();
1534         LOG (GNUNET_ERROR_TYPE_DEBUG,
1535              "send to the socket %d returned %d (%u)\n", i, status, error);
1536         if (status == 0 || (error != WSAEWOULDBLOCK && error != WSAENOTCONN) ||
1537             (status == -1 && gso_result == 0 && error == WSAENOTCONN &&
1538              so_error == WSAECONNREFUSED))
1539         {
1540           FD_SET (wfds->sds.fd_array[i], &awrite);
1541           retcode += 1;
1542         }
1543       }
1544     }
1545   }
1546   if (!nhandles || (returnedpos >= nhandles))
1547     LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1548   if (rfds)
1549   {
1550     struct GNUNET_CONTAINER_SList_Iterator t;
1551
1552     for (i = 0; i < rfds->sds.fd_count; i++)
1553     {
1554       WSAEventSelect (rfds->sds.fd_array[i], hEventRead, 0);
1555       nsock++;
1556     }
1557     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1558          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1559          GNUNET_CONTAINER_slist_next (&t))
1560     {
1561       struct GNUNET_DISK_FileHandle *fh;
1562
1563       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1564                                                                          NULL);
1565       if (fh->type == GNUNET_PIPE)
1566       {
1567         CancelIo (fh->h);
1568       }
1569     }
1570     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds\n");
1571     GNUNET_NETWORK_fdset_zero (rfds);
1572     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1573       GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1574     GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1575   }
1576   if (wfds)
1577   {
1578     for (i = 0; i < wfds->sds.fd_count; i++)
1579     {
1580       WSAEventSelect (wfds->sds.fd_array[i], hEventWrite, 0);
1581       nsock++;
1582     }
1583     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds\n");
1584     GNUNET_NETWORK_fdset_zero (wfds);
1585     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1586       GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1587     GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1588   }
1589   if (efds)
1590   {
1591     for (i = 0; i < efds->sds.fd_count; i++)
1592     {
1593       WSAEventSelect (efds->sds.fd_array[i], hEventException, 0);
1594       nsock++;
1595     }
1596     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds\n");
1597     GNUNET_NETWORK_fdset_zero (efds);
1598     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1599       GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1600     GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1601   }
1602   GNUNET_CONTAINER_slist_destroy (handles_read);
1603   GNUNET_CONTAINER_slist_destroy (handles_write);
1604   GNUNET_CONTAINER_slist_destroy (handles_except);
1605 #if DEBUG_NETWORK
1606   if (rfds)
1607   {
1608     struct GNUNET_CONTAINER_SList_Iterator t;
1609
1610     for (i = 0; i < bread.fd_count; i++)
1611     {
1612       if (bread.fd_array[i] != 0)
1613         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in rfds\n",
1614              bread.fd_array[i],
1615              (SAFE_FD_ISSET (bread.fd_array[i], rfds)) ? "SET" : "NOT SET");
1616     }
1617     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1618          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1619          GNUNET_CONTAINER_slist_next (&t))
1620     {
1621       struct GNUNET_DISK_FileHandle *fh;
1622
1623       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1624                                                                          NULL);
1625       LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is SET in rfds\n", fh->h);
1626     }
1627   }
1628   if (wfds)
1629   {
1630     for (i = 0; i < bwrite.fd_count; i++)
1631     {
1632       if (bwrite.fd_array[i] != 0)
1633         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in wfds\n",
1634              bwrite.fd_array[i],
1635              (SAFE_FD_ISSET (bwrite.fd_array[i], rfds)) ? "SET" : "NOT SET");
1636     }
1637   }
1638   if (efds)
1639   {
1640     for (i = 0; i < bexcept.fd_count; i++)
1641     {
1642       if (bexcept.fd_array[i] != 0)
1643         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x is %s in efds\n",
1644              bexcept.fd_array[i],
1645              (SAFE_FD_ISSET (bexcept.fd_array[i], rfds)) ? "SET" : "NOT SET");
1646     }
1647   }
1648   LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1649 #endif
1650   if (nhandles && (returnedpos < nhandles))
1651     return retcode;
1652   else
1653 #endif
1654     return 0;
1655 }
1656
1657 /* end of network.c */