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