fixing error message -- 1635
[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 abs_value = 1;
165   if (0 !=
166       setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, &abs_value, sizeof (abs_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 * abs_value = "1";
188   if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, abs_value, sizeof (abs_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->fd = accept (desc->fd, address, address_len);
211   ret->af = address->sa_family;
212   if (ret->fd == INVALID_SOCKET)
213     {
214 #ifdef MINGW
215       SetErrnoFromWinsockError (WSAGetLastError ());
216 #endif
217       GNUNET_free (ret);
218       return NULL;
219     }
220 #ifndef MINGW
221   if (ret->fd >= FD_SETSIZE)
222     {
223       GNUNET_break (0 == close (ret->fd));
224       GNUNET_free (ret);
225       errno = EMFILE;
226       return NULL;
227     }
228 #endif
229   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
230
231     {
232
233       /* we might want to treat this one as fatal... */
234       GNUNET_break (0);
235       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret));
236       return NULL;
237     }
238
239 #ifndef MINGW
240   if (GNUNET_OK != socket_set_inheritable (ret))
241     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
242                          "socket_set_inheritable");
243 #endif
244 #ifdef DARWIN
245   socket_set_nosigpipe (ret);
246 #endif
247 #ifdef AF_UNIX
248   if (address->sa_family != AF_UNIX)
249 #endif
250     socket_set_nodelay (ret);
251   return ret;
252 }
253
254
255 /**
256  * Bind to a connected socket
257  * @param desc socket
258  * @param address address to be bound
259  * @param address_len length of address
260  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
261  */
262 int
263 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
264                             const struct sockaddr *address,
265                             socklen_t address_len)
266 {
267   int ret;
268   
269 #ifdef IPV6_V6ONLY 
270 #ifdef IPPROTO_IPV6
271   const int on = 1;
272   if (desc->af == AF_INET6)
273     if (0 != setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
274       GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
275 #if 0
276   /* is this needed or desired? or done elsewhere? */
277   if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
278     GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
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   GNUNET_CONTAINER_slist_add (fds->handles,
841                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
842                               h, sizeof (struct GNUNET_DISK_FileHandle));
843
844 #else
845   int fd;
846   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
847   FD_SET (fd, &fds->sds);
848   if (fd + 1 > fds->nsds)
849     fds->nsds = fd + 1;
850
851 #endif
852 }
853
854
855 /**
856  * Check if a file handle is part of an fd set
857  * @param fds fd set
858  * @param h file handle
859  * @return GNUNET_YES if the file handle is part of the set
860  */
861 int
862 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
863                                    const struct GNUNET_DISK_FileHandle *h)
864 {
865
866 #ifdef MINGW
867   return GNUNET_CONTAINER_slist_contains (fds->handles, h,
868                                           sizeof (struct GNUNET_DISK_FileHandle));
869 #else
870   return FD_ISSET (h->fd, &fds->sds);
871 #endif
872 }
873
874
875 /**
876  * Checks if two fd sets overlap
877  * @param fds1 first fd set
878  * @param fds2 second fd set
879  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
880  */
881 int
882 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
883                               const struct GNUNET_NETWORK_FDSet *fds2)
884 {
885 #ifndef MINGW
886   int nfds;
887
888   nfds = fds1->nsds;
889   if (nfds > fds2->nsds)
890     nfds = fds2->nsds;
891   while (nfds > 0)
892     {
893       nfds--;
894       if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
895         return GNUNET_YES;
896     }
897 #else
898   struct GNUNET_CONTAINER_SList_Iterator *it;
899   struct GNUNET_DISK_FileHandle *h;
900   int i;
901   int j;
902
903   /*This code is somewhat hacky, we are not supposed to know what's
904     inside of fd_set; also the O(n^2) is really bad... */
905
906   for (i = 0; i < fds1->sds.fd_count; i++)
907   {
908     for (j = 0; j < fds2->sds.fd_count; j++)
909     {
910       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
911         return GNUNET_YES;
912     }
913   }
914   it = GNUNET_CONTAINER_slist_begin (fds1->handles);
915   while (GNUNET_CONTAINER_slist_end (it) != GNUNET_YES)
916     {
917       h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (it, NULL);
918       if (GNUNET_CONTAINER_slist_contains
919           (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
920         {
921           GNUNET_CONTAINER_slist_iter_destroy (it);
922           return GNUNET_YES;
923         }
924       GNUNET_CONTAINER_slist_next (it);
925     }
926   GNUNET_CONTAINER_slist_iter_destroy (it);
927 #endif
928   return GNUNET_NO;
929 }
930
931
932 /**
933  * Creates an fd set
934  * @return a new fd set
935  */
936 struct GNUNET_NETWORK_FDSet *
937 GNUNET_NETWORK_fdset_create ()
938 {
939   struct GNUNET_NETWORK_FDSet *fds;
940   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
941 #ifdef MINGW
942   fds->handles = GNUNET_CONTAINER_slist_create ();
943 #endif
944   GNUNET_NETWORK_fdset_zero (fds);
945   return fds;
946 }
947
948
949 /**
950  * Releases the associated memory of an fd set
951  * @param fds fd set
952  */
953 void
954 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
955 {
956 #ifdef MINGW
957   GNUNET_CONTAINER_slist_destroy (fds->handles);
958 #endif
959   GNUNET_free (fds);
960 }
961
962 /**
963  * Check if sockets meet certain conditions
964  * @param rfds set of sockets to be checked for readability
965  * @param wfds set of sockets to be checked for writability
966  * @param efds set of sockets to be checked for exceptions
967  * @param timeout relative value when to return
968  * @return number of selected sockets, GNUNET_SYSERR on error
969  */
970 int
971 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
972                               struct GNUNET_NETWORK_FDSet *wfds,
973                               struct GNUNET_NETWORK_FDSet *efds,
974                               const struct GNUNET_TIME_Relative timeout)
975 {
976   int nfds;
977 #ifdef MINGW
978   int handles;
979 #endif
980   nfds = 0;
981 #ifdef MINGW
982   handles = 0;
983 #endif
984   if (NULL != rfds)
985     {
986       nfds = rfds->nsds;
987 #ifdef MINGW
988       handles = GNUNET_CONTAINER_slist_count (rfds->handles);
989 #endif
990     }
991   if (NULL != wfds)
992     {
993       nfds = GNUNET_MAX (nfds, wfds->nsds);
994 #ifdef MINGW
995       handles += GNUNET_CONTAINER_slist_count (wfds->handles);
996 #endif
997     }
998   if (NULL != efds)
999     {
1000       nfds = GNUNET_MAX (nfds, efds->nsds);
1001 #ifdef MINGW
1002       handles += GNUNET_CONTAINER_slist_count (efds->handles);
1003 #endif
1004     }
1005
1006   struct timeval tv;
1007   tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1008   tv.tv_usec =
1009     1000 * (timeout.rel_value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1010   if ((nfds == 0) && (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1011 #ifdef MINGW
1012       && handles == 0
1013 #endif
1014     )
1015     {
1016       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1017                   _
1018                   ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1019                   "select");
1020       GNUNET_break (0);
1021     }
1022 #ifndef MINGW
1023   return select (nfds,
1024                  (rfds != NULL) ? &rfds->sds : NULL,
1025                  (wfds != NULL) ? &wfds->sds : NULL,
1026                  (efds != NULL) ? &efds->sds : NULL,
1027                  (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1028                  ? NULL : &tv);
1029
1030 #else
1031   DWORD limit;
1032   fd_set sock_read, sock_write, sock_except;
1033   fd_set aread, awrite, aexcept;
1034   struct GNUNET_CONTAINER_SList *handles_read, *handles_write,
1035     *handles_except;
1036
1037   int i;
1038   struct timeval tvslice;
1039   int retcode;
1040   DWORD ms_total;
1041
1042 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1043
1044   /* calculate how long we need to wait in milliseconds */
1045   if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1046     ms_total = INFINITE;
1047
1048   else
1049     ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1050
1051   /* select() may be used as a portable way to sleep */
1052   if (!(rfds || wfds || efds))
1053
1054     {
1055       Sleep (ms_total);
1056       return 0;
1057     }
1058
1059   handles_read = GNUNET_CONTAINER_slist_create ();
1060   handles_write = GNUNET_CONTAINER_slist_create ();
1061   handles_except = GNUNET_CONTAINER_slist_create ();
1062
1063   if (rfds)
1064     sock_read = rfds->sds;
1065   else
1066     FD_ZERO (&sock_read);
1067   if (wfds)
1068     sock_write = wfds->sds;
1069   else
1070     FD_ZERO (&sock_write);
1071   if (efds)
1072     sock_except = efds->sds;
1073   else
1074     FD_ZERO (&sock_except);
1075
1076   /* multiplex between winsock select() and waiting on the handles */
1077   FD_ZERO (&aread);
1078   FD_ZERO (&awrite);
1079   FD_ZERO (&aexcept);
1080   limit = GetTickCount () + ms_total;
1081
1082   do
1083     {
1084       retcode = 0;
1085       if (nfds > 0)
1086
1087         {
1088
1089           /* overwrite the zero'd sets here; the select call
1090            * will clear those that are not active */
1091           FD_COPY (&sock_read, &aread);
1092           FD_COPY (&sock_write, &awrite);
1093           FD_COPY (&sock_except, &aexcept);
1094           tvslice.tv_sec = 0;
1095           tvslice.tv_usec = 100000;
1096           if ((retcode =
1097                select (nfds + 1, &aread, &awrite, &aexcept,
1098                        &tvslice)) == SOCKET_ERROR)
1099
1100             {
1101               SetErrnoFromWinsockError (WSAGetLastError ());
1102               if (errno == ENOTSOCK)
1103                 errno = EBADF;
1104
1105 #if DEBUG_NETWORK
1106               GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
1107
1108 #endif
1109               goto select_loop_end;
1110             }
1111         }
1112
1113       /* Poll read pipes */
1114       if (rfds)
1115
1116         {
1117           struct GNUNET_CONTAINER_SList_Iterator *i;
1118           for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1119                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1120                GNUNET_CONTAINER_slist_next (i))
1121
1122             {
1123               struct GNUNET_DISK_FileHandle *fh;
1124               DWORD dwBytes;
1125               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1126               if (fh->type == GNUNET_PIPE)
1127                 {
1128                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1129                     {
1130                       DWORD error_code = GetLastError ();
1131                       switch (error_code)
1132                       {
1133                       case ERROR_BROKEN_PIPE:
1134                         GNUNET_CONTAINER_slist_add (handles_read,
1135                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1136                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1137                         retcode++;
1138                         break;
1139                       default:
1140                         retcode = -1;
1141                         SetErrnoFromWinError (error_code);
1142
1143     #if DEBUG_NETWORK
1144                         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1145                                              "PeekNamedPipe");
1146
1147     #endif
1148                         goto select_loop_end;
1149                       }
1150                     }
1151                   else if (dwBytes)
1152
1153                     {
1154                       GNUNET_CONTAINER_slist_add (handles_read,
1155                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1156                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1157                       retcode++;
1158                     }
1159                 }
1160               else
1161                 {
1162                   /* Should we wait for more bytes to read here (in case of previous EOF)? */
1163                   GNUNET_CONTAINER_slist_add (handles_read,
1164                                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1165                                               fh, sizeof (struct GNUNET_DISK_FileHandle));
1166                 }
1167             }
1168           GNUNET_CONTAINER_slist_iter_destroy (i);
1169         }
1170
1171       /* Poll for faulty pipes */
1172       if (efds)
1173
1174         {
1175           struct GNUNET_CONTAINER_SList_Iterator *i;
1176           for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1177                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1178                GNUNET_CONTAINER_slist_next (i))
1179
1180             {
1181               struct GNUNET_DISK_FileHandle *fh;
1182               DWORD dwBytes;
1183
1184               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1185               if (fh->type == GNUNET_PIPE)
1186                 {
1187                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1188
1189                     {
1190                       GNUNET_CONTAINER_slist_add (handles_except,
1191                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1192                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1193                       retcode++;
1194                     }
1195                 }
1196             }
1197           GNUNET_CONTAINER_slist_iter_destroy (i);
1198         }
1199
1200       if (wfds)
1201         {
1202           GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1203           retcode += GNUNET_CONTAINER_slist_count (wfds->handles);
1204         }
1205
1206       /* Check for closed sockets */
1207       for (i = 0; i < nfds; i++)
1208
1209         {
1210           if (SAFE_FD_ISSET (i, &sock_read))
1211
1212             {
1213               struct sockaddr addr;
1214               int len;
1215               if (getpeername (i, &addr, &len) == SOCKET_ERROR)
1216
1217                 {
1218                   int err, len;
1219                   len = sizeof (err);
1220                   if (getsockopt
1221                       (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
1222                       && err == WSAENOTCONN)
1223
1224                     {
1225                       if (!SAFE_FD_ISSET (i, &aread))
1226
1227                         {
1228                           FD_SET (i, &aread);
1229                           retcode++;
1230                         }
1231                     }
1232                 }
1233             }
1234         }
1235     select_loop_end:
1236       if (retcode == 0 && nfds == 0)
1237         Sleep (GNUNET_MIN (100, limit - GetTickCount ()));
1238     }
1239   while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
1240
1241   if (retcode != -1)
1242     {
1243       if (rfds)
1244         {
1245           GNUNET_NETWORK_fdset_zero (rfds);
1246           GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1247           GNUNET_CONTAINER_slist_clear (rfds->handles);
1248           GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1249         }
1250       if (wfds)
1251         {
1252           GNUNET_NETWORK_fdset_zero (wfds);
1253           GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1254           GNUNET_CONTAINER_slist_clear (wfds->handles);
1255           GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1256         }
1257       if (efds)
1258         {
1259           GNUNET_NETWORK_fdset_zero (efds);
1260           GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1261           GNUNET_CONTAINER_slist_clear (efds->handles);
1262           GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1263         }
1264     }
1265
1266   GNUNET_CONTAINER_slist_destroy (handles_read);
1267   GNUNET_CONTAINER_slist_destroy (handles_write);
1268   GNUNET_CONTAINER_slist_destroy (handles_except);
1269
1270   return retcode;
1271 #endif
1272 }
1273
1274
1275 /* end of network.c */