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