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