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