mantis 1735
[oweals/gnunet.git] / src / util / network.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 2, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file util/network.c
23  * @brief basic, low-level networking interface
24  * @author Nils Durner
25  */
26
27 #include "platform.h"
28 #include "gnunet_disk_lib.h"
29 #include "disk.h"
30 #include "gnunet_container_lib.h"
31
32 #define DEBUG_NETWORK GNUNET_NO
33
34 #define DEBUG_W32_CYCLES GNUNET_NO
35
36 #ifndef INVALID_SOCKET
37 #define INVALID_SOCKET -1
38 #endif
39
40
41 struct GNUNET_NETWORK_Handle
42 {
43 #ifndef MINGW
44   int fd;
45
46 #else
47   SOCKET fd;
48 #endif
49
50   /**
51    * Address family / domain.
52    */
53   int af;
54
55   /**
56    * Number of bytes in addr.
57    */
58   socklen_t addrlen;
59
60   /**
61    * Address we were bound to, or NULL.
62    */
63   struct sockaddr *addr;
64
65 };
66
67
68 struct GNUNET_NETWORK_FDSet
69 {
70
71   /**
72    * Maximum number of any socket socket descriptor in the set (plus one)
73    */
74   int nsds;
75
76   /**
77    * Bitset with the descriptors.
78    */
79   fd_set sds;
80
81 #ifdef WINDOWS
82   /**
83    * Linked list of handles
84    */
85   struct GNUNET_CONTAINER_SList *handles;
86 #endif
87
88 };
89
90 #ifndef FD_COPY
91 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
92 #endif
93
94
95 /**
96  * Set if a socket should use blocking or non-blocking IO.
97  * @param fd socket
98  * @param doBlock blocking mode
99  * @return GNUNET_OK on success, GNUNET_SYSERR on error
100  */
101 static int
102 socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
103 {
104
105 #if MINGW
106   u_long mode;
107   mode = !doBlock;
108   if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
109
110     {
111       SetErrnoFromWinsockError (WSAGetLastError ());
112       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
113       return GNUNET_SYSERR;
114     }
115   return GNUNET_OK;
116
117 #else
118   /* not MINGW */
119   int flags = fcntl (fd->fd, F_GETFL);
120   if (flags == -1)
121
122     {
123       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
124       return GNUNET_SYSERR;
125     }
126   if (doBlock)
127     flags &= ~O_NONBLOCK;
128
129   else
130     flags |= O_NONBLOCK;
131   if (0 != fcntl (fd->fd, F_SETFL, flags))
132
133     {
134       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
135       return GNUNET_SYSERR;
136     }
137   return GNUNET_OK;
138 #endif
139 }
140
141
142 #ifndef MINGW
143 /**
144  * Make a socket non-inheritable to child processes
145  *
146  * @param h the socket to make non-inheritable
147  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
148  * @warning Not implemented on Windows
149  */
150 static int
151 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
152 {
153   int i;
154
155   i = fcntl (h->fd, F_GETFD);  
156   if (i < 0)
157     return GNUNET_SYSERR;
158   if (i == (i | FD_CLOEXEC))
159     return GNUNET_OK;
160   i |= FD_CLOEXEC;
161   if (fcntl (h->fd, F_SETFD, i) < 0)
162     return GNUNET_SYSERR;
163   return GNUNET_OK;
164 }
165 #endif
166
167
168 #ifdef DARWIN
169 /**
170  * The MSG_NOSIGNAL equivalent on Mac OS X
171  *
172  * @param h the socket to make non-delaying
173  */
174 static void
175 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
176 {
177   int abs_value = 1;
178   if (0 !=
179       setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, &abs_value, sizeof (abs_value)))
180     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
181 }
182 #endif
183
184
185 /**
186  * Disable delays when sending data via the socket.
187  * (GNUnet makes sure that messages are as big as
188  * possible already).
189  *
190  * @param h the socket to make non-delaying
191  */
192 static void
193 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
194 {
195 #ifndef WINDOWS  
196   int value = 1;
197   if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
198     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
199 #else
200   const char * abs_value = "1";
201   if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, abs_value, sizeof (abs_value)))
202     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
203 #endif  
204 }
205
206
207 /**
208  * accept a new connection on a socket
209  *
210  * @param desc bound socket
211  * @param address address of the connecting peer, may be NULL
212  * @param address_len length of address
213  * @return client socket
214  */
215 struct GNUNET_NETWORK_Handle *
216 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
217                               struct sockaddr *address,
218                               socklen_t * address_len)
219 {
220   struct GNUNET_NETWORK_Handle *ret;
221
222   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
223   ret->fd = accept (desc->fd, address, address_len);
224   if (address != NULL)
225     ret->af = address->sa_family;
226   else
227     ret->af = desc->af;
228   if (ret->fd == INVALID_SOCKET)
229     {
230 #ifdef MINGW
231       SetErrnoFromWinsockError (WSAGetLastError ());
232 #endif
233       GNUNET_free (ret);
234       return NULL;
235     }
236 #ifndef MINGW
237   if (ret->fd >= FD_SETSIZE)
238     {
239       GNUNET_break (0 == close (ret->fd));
240       GNUNET_free (ret);
241       errno = EMFILE;
242       return NULL;
243     }
244 #endif
245   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
246
247     {
248
249       /* we might want to treat this one as fatal... */
250       GNUNET_break (0);
251       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret));
252       return NULL;
253     }
254
255 #ifndef MINGW
256   if (GNUNET_OK != socket_set_inheritable (ret))
257     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
258                          "socket_set_inheritable");
259 #endif
260 #ifdef DARWIN
261   socket_set_nosigpipe (ret);
262 #endif
263 #ifdef AF_UNIX
264   if (ret->af != AF_UNIX)
265 #endif
266     socket_set_nodelay (ret);
267   return ret;
268 }
269
270
271 /**
272  * Bind to a connected socket
273  * @param desc socket
274  * @param address address to be bound
275  * @param address_len length of address
276  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
277  */
278 int
279 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
280                             const struct sockaddr *address,
281                             socklen_t address_len)
282 {
283   int ret;
284   
285 #ifdef IPV6_V6ONLY 
286 #ifdef IPPROTO_IPV6
287   const int on = 1;
288   if (desc->af == AF_INET6)
289     if (0 != setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
290       GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
291 #if 0
292   /* is this needed or desired? or done elsewhere? */
293   if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
294     GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
295 #endif
296 #endif
297 #endif
298 #ifndef LINUX
299 #ifndef MINGW
300   if (address->sa_family == AF_UNIX)
301     {
302       const struct sockaddr_un *un = (const struct sockaddr_un*) address;
303       (void) unlink (un->sun_path);
304     }
305 #endif
306 #endif
307   ret = bind (desc->fd, address, address_len);
308 #ifdef MINGW
309   if (SOCKET_ERROR == ret)
310     SetErrnoFromWinsockError (WSAGetLastError ());
311 #endif
312   if (ret != 0)
313           return GNUNET_SYSERR;
314 #ifndef MINGW
315 #ifndef LINUX
316   desc->addr = GNUNET_malloc (address_len);
317   memcpy (desc->addr, address, address_len);
318   desc->addrlen = address_len;
319 #endif
320 #endif
321   return GNUNET_OK;
322 }
323
324
325 /**
326  * Close a socket
327  * @param desc socket
328  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
329  */
330 int
331 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
332 {
333   int ret;
334
335 #ifdef MINGW
336   ret = closesocket (desc->fd);
337   SetErrnoFromWinsockError (WSAGetLastError ());
338 #else
339   ret = close (desc->fd);
340 #endif
341 #ifndef LINUX
342 #ifndef MINGW
343   if ( (desc->af == AF_UNIX) && (NULL != desc->addr) )
344     {
345       const struct sockaddr_un *un = (const struct sockaddr_un*) desc->addr;
346       if (0 != unlink (un->sun_path))
347           GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
348                                   "unlink",
349                                   un->sun_path);
350     }
351 #endif
352 #endif
353    GNUNET_free_non_null (desc->addr);
354   GNUNET_free (desc);
355   return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
356 }
357
358
359 /**
360  * Box a native socket (and check that it is a socket).
361  *
362  * @param fd socket to box
363  * @return NULL on error (including not supported on target platform)
364  */
365 struct GNUNET_NETWORK_Handle *
366 GNUNET_NETWORK_socket_box_native (int fd)
367 {
368 #if MINGW
369   return NULL;
370 #else
371   struct GNUNET_NETWORK_Handle *ret;
372
373   if (fcntl (fd, F_GETFD) < 0)
374     return NULL; /* invalid FD */
375   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle)); 
376   ret->fd = fd;
377   ret->af = AF_UNSPEC;
378   return ret;
379 #endif
380 }
381
382
383 /**
384  * Connect a socket
385  * @param desc socket
386  * @param address peer address
387  * @param address_len length of address
388  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
389  */
390 int
391 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
392                                const struct sockaddr *address,
393                                socklen_t address_len)
394 {
395   int ret;
396   ret = connect (desc->fd, address, address_len);
397
398 #ifdef MINGW
399   if (SOCKET_ERROR == ret)
400     {
401       SetErrnoFromWinsockError (WSAGetLastError ());
402       if (errno == EWOULDBLOCK)
403         errno = EINPROGRESS;
404     }
405 #endif
406   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
407 }
408
409
410 /**
411  * Get socket options
412  *
413  * @param desc socket
414  * @param level protocol level of the option
415  * @param optname identifier of the option
416  * @param optval options
417  * @param optlen length of optval
418  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
419  */
420 int
421 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
422                                   int level, int optname, void *optval,
423                                   socklen_t * optlen)
424 {
425   int ret;
426   ret = getsockopt (desc->fd, level, optname, optval, optlen);
427
428 #ifdef MINGW
429   if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
430     *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
431
432   else if (SOCKET_ERROR == ret)
433     SetErrnoFromWinsockError (WSAGetLastError ());
434
435 #endif
436   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
437 }
438
439
440 /**
441  * Listen on a socket
442  * @param desc socket
443  * @param backlog length of the listen queue
444  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
445  */
446 int
447 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
448                               int backlog)
449 {
450   int ret;
451   ret = listen (desc->fd, backlog);
452
453 #ifdef MINGW
454   if (SOCKET_ERROR == ret)
455     SetErrnoFromWinsockError (WSAGetLastError ());
456
457 #endif
458   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
459 }
460
461
462 /**
463  * How much data is available to be read on this descriptor?
464  *
465  * Returns GNUNET_NO if no data is available, or on error!
466  * @param desc socket
467  */
468 ssize_t
469 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle
470                                        *desc)
471 {
472   int error;
473
474   /* How much is there to be read? */
475 #ifndef WINDOWS
476   int pending;
477   error = ioctl (desc->fd, FIONREAD, &pending);
478   if (error == 0)
479 #else
480   u_long pending;
481   error = ioctlsocket (desc->fd, FIONREAD, &pending);
482   if (error != SOCKET_ERROR)
483 #endif
484     return pending;
485   else
486     return GNUNET_NO;
487 }
488
489
490 /**
491  * Read data from a connected socket (always non-blocking).
492  * @param desc socket
493  * @param buffer buffer
494  * @param length length of buffer
495  * @param src_addr either the source to recv from, or all zeroes
496  *        to be filled in by recvfrom
497  * @param addrlen length of the addr
498  */
499 ssize_t
500 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
501                                 void *buffer, size_t length,
502                                 struct sockaddr * src_addr,
503                                 socklen_t * addrlen)
504 {
505   int ret;
506   int flags;
507   flags = 0;
508
509 #ifdef MSG_DONTWAIT
510   flags |= MSG_DONTWAIT;
511
512 #endif
513   ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
514 #ifdef MINGW
515   if (SOCKET_ERROR == ret)
516     SetErrnoFromWinsockError (WSAGetLastError ());
517 #endif 
518   return ret;
519 }
520
521
522 /**
523  * Read data from a connected socket (always non-blocking).
524  * @param desc socket
525  * @param buffer buffer
526  * @param length length of buffer
527  */
528 ssize_t
529 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
530                             void *buffer, size_t length)
531 {
532   int ret;
533   int flags;
534   flags = 0;
535
536 #ifdef MSG_DONTWAIT
537   flags |= MSG_DONTWAIT;
538 #endif
539   ret = recv (desc->fd, buffer, length, flags);
540 #ifdef MINGW
541   if (SOCKET_ERROR == ret)
542     SetErrnoFromWinsockError (WSAGetLastError ());
543 #endif
544   return ret;
545 }
546
547
548 /**
549  * Send data (always non-blocking).
550  *
551  * @param desc socket
552  * @param buffer data to send
553  * @param length size of the buffer
554  * @return number of bytes sent, GNUNET_SYSERR on error
555  */
556 ssize_t
557 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
558                             const void *buffer, size_t length)
559 {
560   int ret;
561   int flags;
562   flags = 0;
563
564 #ifdef MSG_DONTWAIT
565   flags |= MSG_DONTWAIT;
566
567 #endif
568 #ifdef MSG_NOSIGNAL
569   flags |= MSG_NOSIGNAL;
570
571 #endif
572   ret = send (desc->fd, buffer, length, flags);
573
574 #ifdef MINGW
575   if (SOCKET_ERROR == ret)
576     SetErrnoFromWinsockError (WSAGetLastError ());
577
578 #endif
579   return ret;
580 }
581
582
583 /**
584  * Send data to a particular destination (always non-blocking).
585  * This function only works for UDP sockets.
586  *
587  * @param desc socket
588  * @param message data to send
589  * @param length size of the data
590  * @param dest_addr destination address
591  * @param dest_len length of address
592  * @return number of bytes sent, GNUNET_SYSERR on error
593  */
594 ssize_t
595 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
596                               const void *message, size_t length,
597                               const struct sockaddr * dest_addr,
598                               socklen_t dest_len)
599 {
600   int ret;
601   int flags;
602   flags = 0;
603
604 #ifdef MSG_DONTWAIT
605   flags |= MSG_DONTWAIT;
606 #endif
607 #ifdef MSG_NOSIGNAL
608   flags |= MSG_NOSIGNAL;
609 #endif
610   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
611 #ifdef MINGW
612   if (SOCKET_ERROR == ret)
613     SetErrnoFromWinsockError (WSAGetLastError ());
614 #endif
615   return ret;
616 }
617
618
619 /**
620  * Set socket option
621  * @param fd socket
622  * @param level protocol level of the option
623  * @param option_name option identifier
624  * @param option_value value to set
625  * @param option_len size of option_value
626  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
627  */
628 int
629 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd,
630                                   int level, int option_name,
631                                   const void *option_value,
632                                   socklen_t option_len)
633 {
634   int ret;
635
636   ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
637 #ifdef MINGW
638   if (SOCKET_ERROR == ret)
639     SetErrnoFromWinsockError (WSAGetLastError ());
640 #endif
641   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
642 }
643
644
645 /**
646  * Create a new socket.  Configure it for non-blocking IO and
647  * mark it as non-inheritable to child processes (set the
648  * close-on-exec flag).
649  *
650  * @param domain domain of the socket
651  * @param type socket type
652  * @param protocol network protocol
653  * @return new socket, NULL on error
654  */
655 struct GNUNET_NETWORK_Handle *
656 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
657 {
658   struct GNUNET_NETWORK_Handle *ret;
659
660   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
661   ret->af = domain;
662   ret->fd = socket (domain, type, protocol);
663   if (INVALID_SOCKET == ret->fd)
664     {
665 #ifdef MINGW
666       SetErrnoFromWinsockError (WSAGetLastError ());
667 #endif
668       GNUNET_free (ret);
669       return NULL;
670     }
671
672 #ifndef MINGW
673   if (ret->fd >= FD_SETSIZE)
674     {
675       GNUNET_break (0 == close (ret->fd));
676       GNUNET_free (ret);
677       errno = EMFILE;
678       return NULL;
679     }
680
681 #endif
682   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
683     {
684       /* we might want to treat this one as fatal... */
685       GNUNET_break (0);
686       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret));
687       return NULL;
688     }
689
690 #ifndef MINGW
691   if (GNUNET_OK != socket_set_inheritable (ret))
692     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
693                          "socket_set_inheritable");
694 #endif
695 #ifdef DARWIN
696   socket_set_nosigpipe (ret);
697 #endif
698   if ( (type == SOCK_STREAM) 
699 #ifdef AF_UNIX
700        && (domain != AF_UNIX) 
701 #endif
702        )
703     socket_set_nodelay (ret);
704   return ret;
705 }
706
707
708 /**
709  * Shut down socket operations
710  * @param desc socket
711  * @param how type of shutdown
712  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
713  */
714 int
715 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
716 {
717   int ret;
718
719   ret = shutdown (desc->fd, how);
720 #ifdef MINGW
721   if (ret != 0)
722     SetErrnoFromWinsockError (WSAGetLastError ());
723 #endif
724   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
725 }
726
727
728 /**
729  * Disable the "CORK" feature for communication with the given socket,
730  * forcing the OS to immediately flush the buffer on transmission
731  * instead of potentially buffering multiple messages.  Essentially
732  * reduces the OS send buffers to zero.
733  *
734  * @param desc socket
735  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
736  */
737 int
738 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
739 {
740   int value = 0;
741   int ret = 0;
742
743   if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
744     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
745   if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
746     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
747
748   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
749 }
750
751
752 /**
753  * Reset FD set
754  * @param fds fd set
755  */
756 void
757 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
758 {
759   FD_ZERO (&fds->sds);
760   fds->nsds = 0;
761 #ifdef MINGW
762   GNUNET_CONTAINER_slist_clear (fds->handles);
763 #endif
764 }
765
766 /**
767  * Add a socket to the FD set
768  * @param fds fd set
769  * @param desc socket to add
770  */
771 void
772 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
773                           const struct GNUNET_NETWORK_Handle *desc)
774 {
775   FD_SET (desc->fd, &fds->sds);
776   if (desc->fd + 1 > fds->nsds)
777     fds->nsds = desc->fd + 1;
778 }
779
780
781 /**
782  * Check whether a socket is part of the fd set
783  * @param fds fd set
784  * @param desc socket
785  * @return 0 if the FD is not set
786  */
787 int
788 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
789                             const struct GNUNET_NETWORK_Handle *desc)
790 {
791   return FD_ISSET (desc->fd, &fds->sds);
792 }
793
794
795 /**
796  * Add one fd set to another
797  * @param dst the fd set to add to
798  * @param src the fd set to add from
799  */
800 void
801 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
802                           const struct GNUNET_NETWORK_FDSet *src)
803 {
804   int nfds;
805   for (nfds = src->nsds; nfds > 0; nfds--)
806     if (FD_ISSET (nfds, &src->sds))
807
808       {
809         FD_SET (nfds, &dst->sds);
810         if (nfds + 1 > dst->nsds)
811           dst->nsds = nfds + 1;
812       }
813 #ifdef MINGW
814   GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
815 #endif
816 }
817
818
819 /**
820  * Copy one fd set to another
821  *
822  * @param to destination
823  * @param from source
824  */
825 void
826 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
827                            const struct GNUNET_NETWORK_FDSet *from)
828 {
829   FD_COPY (&from->sds, &to->sds);
830   to->nsds = from->nsds;
831
832 #ifdef MINGW
833   GNUNET_CONTAINER_slist_clear (to->handles);
834   GNUNET_CONTAINER_slist_append (to->handles, from->handles);
835 #endif
836 }
837
838
839 /**
840  * Return file descriptor for this network handle
841  *
842  * @param desc wrapper to process
843  * @return POSIX file descriptor
844  */
845 int
846 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
847 {
848   return desc->fd;
849 }
850
851
852 /**
853  * Copy a native fd set
854  *
855  * @param to destination
856  * @param from native source set
857  * @param nfds the biggest socket number in from + 1
858  */
859 void
860 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
861                                   const fd_set * from, int nfds)
862 {
863   FD_COPY (from, &to->sds);
864   to->nsds = nfds;
865 }
866
867
868 /**
869  * Set a native fd in a set
870  *
871  * @param to destination
872  * @param nfd native FD to set
873  */
874 void GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to,
875                                       int nfd)
876 {
877   GNUNET_assert((nfd >= 0) && (nfd <= FD_SETSIZE));
878   FD_SET (nfd, &to->sds);
879   to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
880 }
881
882
883 /**
884  * Test native fd in a set
885  *
886  * @param to set to test, NULL for empty set
887  * @param nfd native FD to test, or -1 for none
888  * @return GNUNET_YES if FD is set in the set
889  */
890 int 
891 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
892                                   int nfd)
893 {
894   if ( (nfd == -1) || (to == NULL) )
895     return GNUNET_NO;
896   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
897 }
898
899
900 /**
901  * Add a file handle to the fd set
902  * @param fds fd set
903  * @param h the file handle to add
904  */
905 void
906 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
907                                  const struct GNUNET_DISK_FileHandle *h)
908 {
909 #ifdef MINGW
910   GNUNET_CONTAINER_slist_add (fds->handles,
911                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
912                               h, sizeof (struct GNUNET_DISK_FileHandle));
913
914 #else
915   int fd;
916   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
917   FD_SET (fd, &fds->sds);
918   if (fd + 1 > fds->nsds)
919     fds->nsds = fd + 1;
920
921 #endif
922 }
923
924
925 /**
926  * Check if a file handle is part of an fd set
927  * @param fds fd set
928  * @param h file handle
929  * @return GNUNET_YES if the file handle is part of the set
930  */
931 int
932 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
933                                    const struct GNUNET_DISK_FileHandle *h)
934 {
935
936 #ifdef MINGW
937   return GNUNET_CONTAINER_slist_contains (fds->handles, h,
938                                           sizeof (struct GNUNET_DISK_FileHandle));
939 #else
940   return FD_ISSET (h->fd, &fds->sds);
941 #endif
942 }
943
944
945 /**
946  * Checks if two fd sets overlap
947  * @param fds1 first fd set
948  * @param fds2 second fd set
949  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
950  */
951 int
952 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
953                               const struct GNUNET_NETWORK_FDSet *fds2)
954 {
955 #ifndef MINGW
956   int nfds;
957
958   nfds = fds1->nsds;
959   if (nfds > fds2->nsds)
960     nfds = fds2->nsds;
961   while (nfds > 0)
962     {
963       nfds--;
964       if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
965         return GNUNET_YES;
966     }
967 #else
968   struct GNUNET_CONTAINER_SList_Iterator *it;
969   struct GNUNET_DISK_FileHandle *h;
970   int i;
971   int j;
972
973   /*This code is somewhat hacky, we are not supposed to know what's
974     inside of fd_set; also the O(n^2) is really bad... */
975
976   for (i = 0; i < fds1->sds.fd_count; i++)
977   {
978     for (j = 0; j < fds2->sds.fd_count; j++)
979     {
980       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
981         return GNUNET_YES;
982     }
983   }
984   it = GNUNET_CONTAINER_slist_begin (fds1->handles);
985   while (GNUNET_CONTAINER_slist_end (it) != GNUNET_YES)
986     {
987       h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (it, NULL);
988       if (GNUNET_CONTAINER_slist_contains
989           (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
990         {
991           GNUNET_CONTAINER_slist_iter_destroy (it);
992           return GNUNET_YES;
993         }
994       GNUNET_CONTAINER_slist_next (it);
995     }
996   GNUNET_CONTAINER_slist_iter_destroy (it);
997 #endif
998   return GNUNET_NO;
999 }
1000
1001
1002 /**
1003  * Creates an fd set
1004  * @return a new fd set
1005  */
1006 struct GNUNET_NETWORK_FDSet *
1007 GNUNET_NETWORK_fdset_create ()
1008 {
1009   struct GNUNET_NETWORK_FDSet *fds;
1010   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1011 #ifdef MINGW
1012   fds->handles = GNUNET_CONTAINER_slist_create ();
1013 #endif
1014   GNUNET_NETWORK_fdset_zero (fds);
1015   return fds;
1016 }
1017
1018
1019 /**
1020  * Releases the associated memory of an fd set
1021  * @param fds fd set
1022  */
1023 void
1024 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1025 {
1026 #ifdef MINGW
1027   GNUNET_CONTAINER_slist_destroy (fds->handles);
1028 #endif
1029   GNUNET_free (fds);
1030 }
1031
1032 /**
1033  * Check if sockets meet certain conditions
1034  * @param rfds set of sockets to be checked for readability
1035  * @param wfds set of sockets to be checked for writability
1036  * @param efds set of sockets to be checked for exceptions
1037  * @param timeout relative value when to return
1038  * @return number of selected sockets, GNUNET_SYSERR on error
1039  */
1040 int
1041 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1042                               struct GNUNET_NETWORK_FDSet *wfds,
1043                               struct GNUNET_NETWORK_FDSet *efds,
1044                               const struct GNUNET_TIME_Relative timeout)
1045 {
1046   int nfds;
1047 #ifdef MINGW
1048   int handles;
1049 #endif
1050   nfds = 0;
1051 #ifdef MINGW
1052   handles = 0;
1053 #endif
1054   if (NULL != rfds)
1055     {
1056       nfds = rfds->nsds;
1057 #ifdef MINGW
1058       handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1059 #endif
1060     }
1061   if (NULL != wfds)
1062     {
1063       nfds = GNUNET_MAX (nfds, wfds->nsds);
1064 #ifdef MINGW
1065       handles += GNUNET_CONTAINER_slist_count (wfds->handles);
1066 #endif
1067     }
1068   if (NULL != efds)
1069     {
1070       nfds = GNUNET_MAX (nfds, efds->nsds);
1071 #ifdef MINGW
1072       handles += GNUNET_CONTAINER_slist_count (efds->handles);
1073 #endif
1074     }
1075
1076   struct timeval tv;
1077   tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1078   tv.tv_usec =
1079     1000 * (timeout.rel_value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1080   if ((nfds == 0) && (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1081 #ifdef MINGW
1082       && handles == 0
1083 #endif
1084     )
1085     {
1086       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1087                   _
1088                   ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1089                   "select");
1090       GNUNET_break (0);
1091     }
1092 #ifndef MINGW
1093   return select (nfds,
1094                  (rfds != NULL) ? &rfds->sds : NULL,
1095                  (wfds != NULL) ? &wfds->sds : NULL,
1096                  (efds != NULL) ? &efds->sds : NULL,
1097                  (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1098                  ? NULL : &tv);
1099
1100 #else
1101   DWORD limit;
1102   fd_set sock_read, sock_write, sock_except;
1103   fd_set aread, awrite, aexcept;
1104   struct GNUNET_CONTAINER_SList *handles_read, *handles_write,
1105     *handles_except;
1106
1107   int i;
1108   struct timeval tvslice;
1109   int retcode;
1110   DWORD ms_total;
1111   /* Number of milliseconds per cycle. Adapted on the fly */
1112   static unsigned int cycle_delay = 20;
1113
1114 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1115
1116   /* calculate how long we need to wait in milliseconds */
1117   if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1118     ms_total = INFINITE;
1119
1120   else
1121     ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1122
1123   /* select() may be used as a portable way to sleep */
1124   if (!(rfds || wfds || efds))
1125
1126     {
1127       Sleep (ms_total);
1128       return 0;
1129     }
1130
1131   handles_read = GNUNET_CONTAINER_slist_create ();
1132   handles_write = GNUNET_CONTAINER_slist_create ();
1133   handles_except = GNUNET_CONTAINER_slist_create ();
1134
1135   if (rfds)
1136     sock_read = rfds->sds;
1137   else
1138     FD_ZERO (&sock_read);
1139   if (wfds)
1140     sock_write = wfds->sds;
1141   else
1142     FD_ZERO (&sock_write);
1143   if (efds)
1144     sock_except = efds->sds;
1145   else
1146     FD_ZERO (&sock_except);
1147
1148   /* multiplex between winsock select() and waiting on the handles */
1149   FD_ZERO (&aread);
1150   FD_ZERO (&awrite);
1151   FD_ZERO (&aexcept);
1152
1153 #if DEBUG_W32_CYCLES
1154   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1155               "Starting a cycle, delay is %dms\n", cycle_delay);
1156 #endif
1157
1158   limit = GetTickCount () + ms_total;
1159
1160   do
1161     {
1162       retcode = 0;
1163       if (nfds > 0)
1164
1165         {
1166
1167           /* overwrite the zero'd sets here; the select call
1168            * will clear those that are not active */
1169           FD_COPY (&sock_read, &aread);
1170           FD_COPY (&sock_write, &awrite);
1171           FD_COPY (&sock_except, &aexcept);
1172           tvslice.tv_sec = 0;
1173           tvslice.tv_usec = cycle_delay;
1174           if ((retcode =
1175                select (nfds + 1, &aread, &awrite, &aexcept,
1176                        &tvslice)) == SOCKET_ERROR)
1177
1178             {
1179               SetErrnoFromWinsockError (WSAGetLastError ());
1180               if (errno == ENOTSOCK)
1181                 errno = EBADF;
1182
1183 #if DEBUG_NETWORK
1184               GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
1185
1186 #endif
1187               goto select_loop_end;
1188             }
1189         }
1190
1191       /* Poll read pipes */
1192       if (rfds)
1193
1194         {
1195           struct GNUNET_CONTAINER_SList_Iterator *i;
1196           for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1197                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1198                GNUNET_CONTAINER_slist_next (i))
1199
1200             {
1201               struct GNUNET_DISK_FileHandle *fh;
1202               DWORD dwBytes;
1203               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1204               if (fh->type == GNUNET_PIPE)
1205                 {
1206                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1207                     {
1208                       DWORD error_code = GetLastError ();
1209                       switch (error_code)
1210                       {
1211                       case ERROR_BROKEN_PIPE:
1212                         GNUNET_CONTAINER_slist_add (handles_read,
1213                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1214                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1215                         retcode++;
1216                         break;
1217                       default:
1218                         retcode = -1;
1219                         SetErrnoFromWinError (error_code);
1220
1221     #if DEBUG_NETWORK
1222                         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1223                                              "PeekNamedPipe");
1224
1225     #endif
1226                         goto select_loop_end;
1227                       }
1228                     }
1229                   else if (dwBytes)
1230
1231                     {
1232                       GNUNET_CONTAINER_slist_add (handles_read,
1233                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1234                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1235                       retcode++;
1236                     }
1237                 }
1238               else
1239                 {
1240                   /* Should we wait for more bytes to read here (in case of previous EOF)? */
1241                   GNUNET_CONTAINER_slist_add (handles_read,
1242                                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1243                                               fh, sizeof (struct GNUNET_DISK_FileHandle));
1244                 }
1245             }
1246           GNUNET_CONTAINER_slist_iter_destroy (i);
1247         }
1248
1249       /* Poll for faulty pipes */
1250       if (efds)
1251
1252         {
1253           struct GNUNET_CONTAINER_SList_Iterator *i;
1254           for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1255                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1256                GNUNET_CONTAINER_slist_next (i))
1257
1258             {
1259               struct GNUNET_DISK_FileHandle *fh;
1260               DWORD dwBytes;
1261
1262               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1263               if (fh->type == GNUNET_PIPE)
1264                 {
1265                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1266
1267                     {
1268                       GNUNET_CONTAINER_slist_add (handles_except,
1269                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1270                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1271                       retcode++;
1272                     }
1273                 }
1274             }
1275           GNUNET_CONTAINER_slist_iter_destroy (i);
1276         }
1277
1278       if (wfds)
1279         {
1280           GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1281           retcode += GNUNET_CONTAINER_slist_count (wfds->handles);
1282         }
1283
1284       /* Check for closed sockets */
1285       for (i = 0; i < nfds; i++)
1286
1287         {
1288           if (SAFE_FD_ISSET (i, &sock_read))
1289
1290             {
1291               struct sockaddr addr;
1292               int len;
1293               if (getpeername (i, &addr, &len) == SOCKET_ERROR)
1294
1295                 {
1296                   int err, len;
1297                   len = sizeof (err);
1298                   if (getsockopt
1299                       (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
1300                       && err == WSAENOTCONN)
1301
1302                     {
1303                       if (!SAFE_FD_ISSET (i, &aread))
1304
1305                         {
1306                           FD_SET (i, &aread);
1307                           retcode++;
1308                         }
1309                     }
1310                 }
1311             }
1312         }
1313     select_loop_end:
1314       if (retcode == 0)
1315       {
1316         /* Missed an I/O - double the cycle time */
1317         cycle_delay = cycle_delay * 2 > 250 ? 250 : cycle_delay * 1.4;
1318 #if DEBUG_W32_CYCLES
1319         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1320                     "The cycle missed, increased the delay to %dms\n", cycle_delay);
1321 #endif
1322       }
1323       else
1324       {
1325         /* Successfully selected something - decrease the cycle time */
1326         cycle_delay -= cycle_delay > 2 ? 2 : 0;
1327 #if DEBUG_W32_CYCLES
1328         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1329                     "The cycle hit, decreased the delay to %dms\n", cycle_delay);
1330 #endif
1331       }
1332       if (retcode == 0 && nfds == 0)
1333         Sleep (GNUNET_MIN (cycle_delay * 1000, limit - GetTickCount ()));
1334     }
1335   while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
1336
1337   if (retcode != -1)
1338     {
1339       if (rfds)
1340         {
1341           GNUNET_NETWORK_fdset_zero (rfds);
1342           GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1343           GNUNET_CONTAINER_slist_clear (rfds->handles);
1344           GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1345         }
1346       if (wfds)
1347         {
1348           GNUNET_NETWORK_fdset_zero (wfds);
1349           GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1350           GNUNET_CONTAINER_slist_clear (wfds->handles);
1351           GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1352         }
1353       if (efds)
1354         {
1355           GNUNET_NETWORK_fdset_zero (efds);
1356           GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1357           GNUNET_CONTAINER_slist_clear (efds->handles);
1358           GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1359         }
1360     }
1361
1362   GNUNET_CONTAINER_slist_destroy (handles_read);
1363   GNUNET_CONTAINER_slist_destroy (handles_write);
1364   GNUNET_CONTAINER_slist_destroy (handles_except);
1365
1366   return retcode;
1367 #endif
1368 }
1369
1370
1371 /* end of network.c */