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