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