fixes
[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 (plus one)
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 #ifdef MINGW
840   HANDLE hw;
841   GNUNET_DISK_internal_file_handle_ (h, &hw, sizeof (HANDLE));
842   GNUNET_CONTAINER_slist_add (fds->handles,
843                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
844                               &hw, sizeof (HANDLE));
845
846 #else
847   int fd;
848   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
849   FD_SET (fd, &fds->sds);
850   if (fd + 1 > fds->nsds)
851     fds->nsds = fd + 1;
852
853 #endif
854 }
855
856
857 /**
858  * Check if a file handle is part of an fd set
859  * @param fds fd set
860  * @param h file handle
861  * @return GNUNET_YES if the file handle is part of the set
862  */
863 int
864 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
865                                    const struct GNUNET_DISK_FileHandle *h)
866 {
867
868 #ifdef MINGW
869   return GNUNET_CONTAINER_slist_contains (fds->handles, &h->h,
870                                           sizeof (HANDLE));
871 #else
872   return FD_ISSET (h->fd, &fds->sds);
873 #endif
874 }
875
876
877 /**
878  * Checks if two fd sets overlap
879  * @param fds1 first fd set
880  * @param fds2 second fd set
881  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
882  */
883 int
884 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
885                               const struct GNUNET_NETWORK_FDSet *fds2)
886 {
887   int nfds;
888   nfds = fds1->nsds;
889   if (nfds < fds2->nsds)
890     nfds = fds2->nsds;
891   for (; nfds >= 0; nfds--)
892     if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
893       return GNUNET_YES;
894 #ifdef MINGW
895   {
896     struct GNUNET_CONTAINER_SList_Iterator *it;
897
898     for (it = GNUNET_CONTAINER_slist_begin (fds1->handles);
899          GNUNET_CONTAINER_slist_end (it) != GNUNET_YES;
900          GNUNET_CONTAINER_slist_next (it))
901       {
902         HANDLE *h;
903
904         h = (HANDLE *) GNUNET_CONTAINER_slist_get ((const struct GNUNET_CONTAINER_SList_Iterator *)it, NULL);
905         if (GNUNET_CONTAINER_slist_contains
906             (fds2->handles, h, sizeof (HANDLE)))
907           {
908             GNUNET_CONTAINER_slist_iter_destroy (it);
909             return GNUNET_YES;
910           }
911       }
912     GNUNET_CONTAINER_slist_iter_destroy (it);
913   }
914 #endif
915   return GNUNET_NO;
916 }
917
918
919 /**
920  * Creates an fd set
921  * @return a new fd set
922  */
923 struct GNUNET_NETWORK_FDSet *
924 GNUNET_NETWORK_fdset_create ()
925 {
926   struct GNUNET_NETWORK_FDSet *fds;
927   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
928 #ifdef MINGW
929   fds->handles = GNUNET_CONTAINER_slist_create ();
930 #endif
931   GNUNET_NETWORK_fdset_zero (fds);
932   return fds;
933 }
934
935
936 /**
937  * Releases the associated memory of an fd set
938  * @param fds fd set
939  */
940 void
941 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
942 {
943 #ifdef MINGW
944   GNUNET_CONTAINER_slist_destroy (fds->handles);
945 #endif
946   GNUNET_free (fds);
947 }
948
949 /**
950  * Check if sockets meet certain conditions
951  * @param rfds set of sockets to be checked for readability
952  * @param wfds set of sockets to be checked for writability
953  * @param efds set of sockets to be checked for exceptions
954  * @param timeout relative value when to return
955  * @return number of selected sockets, GNUNET_SYSERR on error
956  */
957 int
958 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
959                               struct GNUNET_NETWORK_FDSet *wfds,
960                               struct GNUNET_NETWORK_FDSet *efds,
961                               const struct GNUNET_TIME_Relative timeout)
962 {
963   int nfds;
964 #ifdef MINGW
965   int handles;
966 #endif
967   nfds = 0;
968 #ifdef MINGW
969   handles = 0;
970 #endif
971   if (NULL != rfds)
972     {
973       nfds = rfds->nsds;
974 #ifdef MINGW
975       handles = GNUNET_CONTAINER_slist_count (rfds->handles);
976 #endif
977     }
978   if (NULL != wfds)
979     {
980       nfds = GNUNET_MAX (nfds, wfds->nsds);
981 #ifdef MINGW
982       handles += GNUNET_CONTAINER_slist_count (wfds->handles);
983 #endif
984     }
985   if (NULL != efds)
986     {
987       nfds = GNUNET_MAX (nfds, efds->nsds);
988 #ifdef MINGW
989       handles += GNUNET_CONTAINER_slist_count (efds->handles);
990 #endif
991     }
992
993   struct timeval tv;
994   tv.tv_sec = timeout.value / GNUNET_TIME_UNIT_SECONDS.value;
995   tv.tv_usec =
996     1000 * (timeout.value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.value));
997   if ((nfds == 0) && (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
998 #ifdef MINGW
999       && handles == 0
1000 #endif
1001     )
1002     {
1003       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1004                   _
1005                   ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1006                   "select");
1007       GNUNET_break (0);
1008     }
1009 #ifndef MINGW
1010   return select (nfds,
1011                  (rfds != NULL) ? &rfds->sds : NULL,
1012                  (wfds != NULL) ? &wfds->sds : NULL,
1013                  (efds != NULL) ? &efds->sds : NULL,
1014                  (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
1015                  ? NULL : &tv);
1016
1017 #else
1018   DWORD limit;
1019   fd_set sock_read, sock_write, sock_except;
1020   fd_set aread, awrite, aexcept;
1021   struct GNUNET_CONTAINER_SList *handles_read, *handles_write,
1022     *handles_except;
1023
1024   int i;
1025   struct timeval tvslice;
1026   int retcode;
1027   DWORD ms_total;
1028
1029 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1030
1031   /* calculate how long we need to wait in milliseconds */
1032   if (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
1033     ms_total = INFINITE;
1034
1035   else
1036     ms_total = timeout.value / GNUNET_TIME_UNIT_MILLISECONDS.value;
1037
1038   /* select() may be used as a portable way to sleep */
1039   if (!(rfds || wfds || efds))
1040
1041     {
1042       Sleep (ms_total);
1043       return 0;
1044     }
1045
1046   handles_read = GNUNET_CONTAINER_slist_create ();
1047   handles_write = GNUNET_CONTAINER_slist_create ();
1048   handles_except = GNUNET_CONTAINER_slist_create ();
1049
1050   if (rfds)
1051     sock_read = rfds->sds;
1052   else
1053     FD_ZERO (&sock_read);
1054   if (wfds)
1055     sock_write = wfds->sds;
1056   else
1057     FD_ZERO (&sock_write);
1058   if (efds)
1059     sock_except = efds->sds;
1060   else
1061     FD_ZERO (&sock_except);
1062
1063   /* multiplex between winsock select() and waiting on the handles */
1064   FD_ZERO (&aread);
1065   FD_ZERO (&awrite);
1066   FD_ZERO (&aexcept);
1067   limit = GetTickCount () + ms_total;
1068
1069   do
1070     {
1071       retcode = 0;
1072       if (nfds > 0)
1073
1074         {
1075
1076           /* overwrite the zero'd sets here; the select call
1077            * will clear those that are not active */
1078           FD_COPY (&sock_read, &aread);
1079           FD_COPY (&sock_write, &awrite);
1080           FD_COPY (&sock_except, &aexcept);
1081           tvslice.tv_sec = 0;
1082           tvslice.tv_usec = 100000;
1083           if ((retcode =
1084                select (nfds + 1, &aread, &awrite, &aexcept,
1085                        &tvslice)) == SOCKET_ERROR)
1086
1087             {
1088               SetErrnoFromWinsockError (WSAGetLastError ());
1089               if (errno == ENOTSOCK)
1090                 errno = EBADF;
1091
1092 #if DEBUG_NETWORK
1093               GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
1094
1095 #endif
1096               goto select_loop_end;
1097             }
1098         }
1099
1100       /* Poll read pipes */
1101       if (rfds)
1102
1103         {
1104           struct GNUNET_CONTAINER_SList_Iterator *i;
1105           for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1106                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1107                GNUNET_CONTAINER_slist_next (i))
1108
1109             {
1110               HANDLE h;
1111               DWORD dwBytes;
1112               h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL);
1113               if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL))
1114                 {
1115                   retcode = -1;
1116                   SetErrnoFromWinError (GetLastError ());
1117
1118 #if DEBUG_NETWORK
1119                   GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1120                                        "PeekNamedPipe");
1121
1122 #endif
1123                   goto select_loop_end;
1124                 }
1125               else if (dwBytes)
1126
1127                 {
1128                   GNUNET_CONTAINER_slist_add (handles_read,
1129                                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1130                                               &h, sizeof (HANDLE));
1131                   retcode++;
1132                 }
1133             }
1134           GNUNET_CONTAINER_slist_iter_destroy (i);
1135         }
1136
1137       /* Poll for faulty pipes */
1138       if (efds)
1139
1140         {
1141           struct GNUNET_CONTAINER_SList_Iterator *i;
1142           for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1143                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1144                GNUNET_CONTAINER_slist_next (i))
1145
1146             {
1147               HANDLE h;
1148               DWORD dwBytes;
1149               h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL);
1150               if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL))
1151
1152                 {
1153                   GNUNET_CONTAINER_slist_add (handles_except,
1154                                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1155                                               &h, sizeof (HANDLE));
1156                   retcode++;
1157                 }
1158             }
1159           GNUNET_CONTAINER_slist_iter_destroy (i);
1160         }
1161
1162       if (wfds)
1163         {
1164           GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1165           retcode += GNUNET_CONTAINER_slist_count (wfds->handles);
1166         }
1167
1168       /* Check for closed sockets */
1169       for (i = 0; i < nfds; i++)
1170
1171         {
1172           if (SAFE_FD_ISSET (i, &sock_read))
1173
1174             {
1175               struct sockaddr addr;
1176               int len;
1177               if (getpeername (i, &addr, &len) == SOCKET_ERROR)
1178
1179                 {
1180                   int err, len;
1181                   len = sizeof (err);
1182                   if (getsockopt
1183                       (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
1184                       && err == WSAENOTCONN)
1185
1186                     {
1187                       if (!SAFE_FD_ISSET (i, &aread))
1188
1189                         {
1190                           FD_SET (i, &aread);
1191                           retcode++;
1192                         }
1193                     }
1194                 }
1195             }
1196         }
1197     select_loop_end:
1198       if (retcode == 0 && nfds == 0)
1199         Sleep (GNUNET_MIN (100, limit - GetTickCount ()));
1200     }
1201   while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
1202
1203   if (retcode != -1)
1204     {
1205       if (rfds)
1206         {
1207           GNUNET_NETWORK_fdset_zero (rfds);
1208           GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1209           GNUNET_CONTAINER_slist_clear (rfds->handles);
1210           GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1211         }
1212       if (wfds)
1213         {
1214           GNUNET_NETWORK_fdset_zero (wfds);
1215           GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1216           GNUNET_CONTAINER_slist_clear (wfds->handles);
1217           GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1218         }
1219       if (efds)
1220         {
1221           GNUNET_NETWORK_fdset_zero (efds);
1222           GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1223           GNUNET_CONTAINER_slist_clear (efds->handles);
1224           GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1225         }
1226     }
1227
1228   GNUNET_CONTAINER_slist_destroy (handles_read);
1229   GNUNET_CONTAINER_slist_destroy (handles_write);
1230   GNUNET_CONTAINER_slist_destroy (handles_except);
1231
1232   return retcode;
1233 #endif
1234 }
1235
1236
1237 /* end of network.c */