oops
[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 /**
456  * Read data from a connected socket (always non-blocking).
457  * @param desc socket
458  * @param buffer buffer
459  * @param length length of buffer
460  * @param src_addr either the source to recv from, or all zeroes
461  *        to be filled in by recvfrom
462  * @param addrlen length of the addr
463  */
464 ssize_t
465 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
466                                 void *buffer, size_t length,
467                                 struct sockaddr * src_addr,
468                                 socklen_t * addrlen)
469 {
470   int ret;
471   int flags;
472   flags = 0;
473
474 #ifdef MSG_DONTWAIT
475   flags |= MSG_DONTWAIT;
476
477 #endif
478   ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
479 #ifdef MINGW
480   if (SOCKET_ERROR == ret)
481     SetErrnoFromWinsockError (WSAGetLastError ());
482 #endif 
483   return ret;
484 }
485
486
487 /**
488  * Read data from a connected socket (always non-blocking).
489  * @param desc socket
490  * @param buffer buffer
491  * @param length length of buffer
492  */
493 ssize_t
494 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
495                             void *buffer, size_t length)
496 {
497   int ret;
498   int flags;
499   flags = 0;
500
501 #ifdef MSG_DONTWAIT
502   flags |= MSG_DONTWAIT;
503 #endif
504   ret = recv (desc->fd, buffer, length, flags);
505 #ifdef MINGW
506   if (SOCKET_ERROR == ret)
507     SetErrnoFromWinsockError (WSAGetLastError ());
508 #endif
509   return ret;
510 }
511
512
513 /**
514  * Send data (always non-blocking).
515  *
516  * @param desc socket
517  * @param buffer data to send
518  * @param length size of the buffer
519  * @return number of bytes sent, GNUNET_SYSERR on error
520  */
521 ssize_t
522 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
523                             const void *buffer, size_t length)
524 {
525   int ret;
526   int flags;
527   flags = 0;
528
529 #ifdef MSG_DONTWAIT
530   flags |= MSG_DONTWAIT;
531
532 #endif /*  */
533 #ifdef MSG_NOSIGNAL
534   flags |= MSG_NOSIGNAL;
535
536 #endif /*  */
537   ret = send (desc->fd, buffer, length, flags);
538
539 #ifdef MINGW
540   if (SOCKET_ERROR == ret)
541     SetErrnoFromWinsockError (WSAGetLastError ());
542
543 #endif /*  */
544   return ret;
545 }
546
547
548 /**
549  * Send data to a particular destination (always non-blocking).
550  * This function only works for UDP sockets.
551  *
552  * @param desc socket
553  * @param message data to send
554  * @param length size of the data
555  * @param dest_addr destination address
556  * @param dest_len length of address
557  * @return number of bytes sent, GNUNET_SYSERR on error
558  */
559 ssize_t
560 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
561                               const void *message, size_t length,
562                               const struct sockaddr * dest_addr,
563                               socklen_t dest_len)
564 {
565   int ret;
566   int flags;
567   flags = 0;
568
569 #ifdef MSG_DONTWAIT
570   flags |= MSG_DONTWAIT;
571 #endif
572 #ifdef MSG_NOSIGNAL
573   flags |= MSG_NOSIGNAL;
574 #endif
575   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
576 #ifdef MINGW
577   if (SOCKET_ERROR == ret)
578     SetErrnoFromWinsockError (WSAGetLastError ());
579 #endif
580   return ret;
581 }
582
583
584 /**
585  * Set socket option
586  * @param fd socket
587  * @param level protocol level of the option
588  * @param option_name option identifier
589  * @param option_value value to set
590  * @param option_len size of option_value
591  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
592  */
593 int
594 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd,
595                                   int level, int option_name,
596                                   const void *option_value,
597                                   socklen_t option_len)
598 {
599   int ret;
600
601   ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
602 #ifdef MINGW
603   if (SOCKET_ERROR == ret)
604     SetErrnoFromWinsockError (WSAGetLastError ());
605 #endif
606   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
607 }
608
609
610 /**
611  * Create a new socket.  Configure it for non-blocking IO and
612  * mark it as non-inheritable to child processes (set the
613  * close-on-exec flag).
614  *
615  * @param domain domain of the socket
616  * @param type socket type
617  * @param protocol network protocol
618  * @return new socket, NULL on error
619  */
620 struct GNUNET_NETWORK_Handle *
621 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
622 {
623   struct GNUNET_NETWORK_Handle *ret;
624   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
625   ret->af = domain;
626   ret->fd = socket (domain, type, protocol);
627   if (INVALID_SOCKET == ret->fd)
628     {
629 #ifdef MINGW
630       SetErrnoFromWinsockError (WSAGetLastError ());
631 #endif
632       GNUNET_free (ret);
633       return NULL;
634     }
635
636 #ifndef MINGW
637   if (ret->fd >= FD_SETSIZE)
638     {
639       GNUNET_break (0 == close (ret->fd));
640       GNUNET_free (ret);
641       errno = EMFILE;
642       return NULL;
643     }
644
645 #endif
646   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
647     {
648       /* we might want to treat this one as fatal... */
649       GNUNET_break (0);
650       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret));
651       return NULL;
652     }
653
654 #ifndef MINGW
655   if (GNUNET_OK != socket_set_inheritable (ret))
656     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
657                          "socket_set_inheritable");
658 #endif
659 #ifdef DARWIN
660   socket_set_nosigpipe (ret);
661 #endif
662   if ( (type == SOCK_STREAM) 
663 #ifdef AF_UNIX
664        && (domain != AF_UNIX) 
665 #endif
666        )
667     socket_set_nodelay (ret);
668   return ret;
669 }
670
671
672 /**
673  * Shut down socket operations
674  * @param desc socket
675  * @param how type of shutdown
676  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
677  */
678 int
679 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
680 {
681   int ret;
682
683   ret = shutdown (desc->fd, how);
684 #ifdef MINGW
685   if (ret != 0)
686     SetErrnoFromWinsockError (WSAGetLastError ());
687 #endif
688   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
689 }
690
691
692 /**
693  * Reset FD set
694  * @param fds fd set
695  */
696 void
697 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
698 {
699   FD_ZERO (&fds->sds);
700   fds->nsds = 0;
701 #ifdef MINGW
702   GNUNET_CONTAINER_slist_clear (fds->handles);
703 #endif
704 }
705
706 /**
707  * Add a socket to the FD set
708  * @param fds fd set
709  * @param desc socket to add
710  */
711 void
712 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
713                           const struct GNUNET_NETWORK_Handle *desc)
714 {
715   FD_SET (desc->fd, &fds->sds);
716   if (desc->fd + 1 > fds->nsds)
717     fds->nsds = desc->fd + 1;
718 }
719
720
721 /**
722  * Check whether a socket is part of the fd set
723  * @param fds fd set
724  * @param desc socket
725  * @return 0 if the FD is not set
726  */
727 int
728 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
729                             const struct GNUNET_NETWORK_Handle *desc)
730 {
731   return FD_ISSET (desc->fd, &fds->sds);
732 }
733
734
735 /**
736  * Add one fd set to another
737  * @param dst the fd set to add to
738  * @param src the fd set to add from
739  */
740 void
741 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
742                           const struct GNUNET_NETWORK_FDSet *src)
743 {
744   int nfds;
745   for (nfds = src->nsds; nfds > 0; nfds--)
746     if (FD_ISSET (nfds, &src->sds))
747
748       {
749         FD_SET (nfds, &dst->sds);
750         if (nfds + 1 > dst->nsds)
751           dst->nsds = nfds + 1;
752       }
753 #ifdef MINGW
754   GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
755 #endif
756 }
757
758
759 /**
760  * Copy one fd set to another
761  *
762  * @param to destination
763  * @param from source
764  */
765 void
766 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
767                            const struct GNUNET_NETWORK_FDSet *from)
768 {
769   FD_COPY (&from->sds, &to->sds);
770   to->nsds = from->nsds;
771
772 #ifdef MINGW
773   GNUNET_CONTAINER_slist_clear (to->handles);
774   GNUNET_CONTAINER_slist_append (to->handles, from->handles);
775 #endif
776 }
777
778
779 /**
780  * Return file descriptor for this network handle
781  *
782  * @param desc wrapper to process
783  * @return POSIX file descriptor
784  */
785 int
786 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
787 {
788   return desc->fd;
789 }
790
791
792 /**
793  * Copy a native fd set
794  *
795  * @param to destination
796  * @param from native source set
797  * @param nfds the biggest socket number in from + 1
798  */
799 void
800 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
801                                   const fd_set * from, int nfds)
802 {
803   FD_COPY (from, &to->sds);
804   to->nsds = nfds;
805 }
806
807
808 /**
809  * Set a native fd in a set
810  *
811  * @param to destination
812  * @param nfd native FD to set
813  */
814 void GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to,
815                                       int nfd)
816 {
817   GNUNET_assert(nfd >= 0);
818   FD_SET (nfd, &to->sds);
819   to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
820 }
821
822
823 /**
824  * Test native fd in a set
825  *
826  * @param to set to test, NULL for empty set
827  * @param nfd native FD to test, or -1 for none
828  * @return GNUNET_YES if FD is set in the set
829  */
830 int 
831 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
832                                   int nfd)
833 {
834   if ( (nfd == -1) || (to == NULL) )
835     return GNUNET_NO;
836   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
837 }
838
839
840 /**
841  * Add a file handle to the fd set
842  * @param fds fd set
843  * @param h the file handle to add
844  */
845 void
846 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
847                                  const struct GNUNET_DISK_FileHandle *h)
848 {
849 #ifdef MINGW
850   GNUNET_CONTAINER_slist_add (fds->handles,
851                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
852                               h, sizeof (struct GNUNET_DISK_FileHandle));
853
854 #else
855   int fd;
856   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
857   FD_SET (fd, &fds->sds);
858   if (fd + 1 > fds->nsds)
859     fds->nsds = fd + 1;
860
861 #endif
862 }
863
864
865 /**
866  * Check if a file handle is part of an fd set
867  * @param fds fd set
868  * @param h file handle
869  * @return GNUNET_YES if the file handle is part of the set
870  */
871 int
872 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
873                                    const struct GNUNET_DISK_FileHandle *h)
874 {
875
876 #ifdef MINGW
877   return GNUNET_CONTAINER_slist_contains (fds->handles, h,
878                                           sizeof (struct GNUNET_DISK_FileHandle));
879 #else
880   return FD_ISSET (h->fd, &fds->sds);
881 #endif
882 }
883
884
885 /**
886  * Checks if two fd sets overlap
887  * @param fds1 first fd set
888  * @param fds2 second fd set
889  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
890  */
891 int
892 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
893                               const struct GNUNET_NETWORK_FDSet *fds2)
894 {
895 #ifndef MINGW
896   int nfds;
897
898   nfds = fds1->nsds;
899   if (nfds > fds2->nsds)
900     nfds = fds2->nsds;
901   while (nfds > 0)
902     {
903       nfds--;
904       if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
905         return GNUNET_YES;
906     }
907 #else
908   struct GNUNET_CONTAINER_SList_Iterator *it;
909   struct GNUNET_DISK_FileHandle *h;
910   int i;
911   int j;
912
913   /*This code is somewhat hacky, we are not supposed to know what's
914     inside of fd_set; also the O(n^2) is really bad... */
915
916   for (i = 0; i < fds1->sds.fd_count; i++)
917   {
918     for (j = 0; j < fds2->sds.fd_count; j++)
919     {
920       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
921         return GNUNET_YES;
922     }
923   }
924   it = GNUNET_CONTAINER_slist_begin (fds1->handles);
925   while (GNUNET_CONTAINER_slist_end (it) != GNUNET_YES)
926     {
927       h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (it, NULL);
928       if (GNUNET_CONTAINER_slist_contains
929           (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
930         {
931           GNUNET_CONTAINER_slist_iter_destroy (it);
932           return GNUNET_YES;
933         }
934       GNUNET_CONTAINER_slist_next (it);
935     }
936   GNUNET_CONTAINER_slist_iter_destroy (it);
937 #endif
938   return GNUNET_NO;
939 }
940
941
942 /**
943  * Creates an fd set
944  * @return a new fd set
945  */
946 struct GNUNET_NETWORK_FDSet *
947 GNUNET_NETWORK_fdset_create ()
948 {
949   struct GNUNET_NETWORK_FDSet *fds;
950   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
951 #ifdef MINGW
952   fds->handles = GNUNET_CONTAINER_slist_create ();
953 #endif
954   GNUNET_NETWORK_fdset_zero (fds);
955   return fds;
956 }
957
958
959 /**
960  * Releases the associated memory of an fd set
961  * @param fds fd set
962  */
963 void
964 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
965 {
966 #ifdef MINGW
967   GNUNET_CONTAINER_slist_destroy (fds->handles);
968 #endif
969   GNUNET_free (fds);
970 }
971
972 /**
973  * Check if sockets meet certain conditions
974  * @param rfds set of sockets to be checked for readability
975  * @param wfds set of sockets to be checked for writability
976  * @param efds set of sockets to be checked for exceptions
977  * @param timeout relative value when to return
978  * @return number of selected sockets, GNUNET_SYSERR on error
979  */
980 int
981 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
982                               struct GNUNET_NETWORK_FDSet *wfds,
983                               struct GNUNET_NETWORK_FDSet *efds,
984                               const struct GNUNET_TIME_Relative timeout)
985 {
986   int nfds;
987 #ifdef MINGW
988   int handles;
989 #endif
990   nfds = 0;
991 #ifdef MINGW
992   handles = 0;
993 #endif
994   if (NULL != rfds)
995     {
996       nfds = rfds->nsds;
997 #ifdef MINGW
998       handles = GNUNET_CONTAINER_slist_count (rfds->handles);
999 #endif
1000     }
1001   if (NULL != wfds)
1002     {
1003       nfds = GNUNET_MAX (nfds, wfds->nsds);
1004 #ifdef MINGW
1005       handles += GNUNET_CONTAINER_slist_count (wfds->handles);
1006 #endif
1007     }
1008   if (NULL != efds)
1009     {
1010       nfds = GNUNET_MAX (nfds, efds->nsds);
1011 #ifdef MINGW
1012       handles += GNUNET_CONTAINER_slist_count (efds->handles);
1013 #endif
1014     }
1015
1016   struct timeval tv;
1017   tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1018   tv.tv_usec =
1019     1000 * (timeout.rel_value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1020   if ((nfds == 0) && (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1021 #ifdef MINGW
1022       && handles == 0
1023 #endif
1024     )
1025     {
1026       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1027                   _
1028                   ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1029                   "select");
1030       GNUNET_break (0);
1031     }
1032 #ifndef MINGW
1033   return select (nfds,
1034                  (rfds != NULL) ? &rfds->sds : NULL,
1035                  (wfds != NULL) ? &wfds->sds : NULL,
1036                  (efds != NULL) ? &efds->sds : NULL,
1037                  (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1038                  ? NULL : &tv);
1039
1040 #else
1041   DWORD limit;
1042   fd_set sock_read, sock_write, sock_except;
1043   fd_set aread, awrite, aexcept;
1044   struct GNUNET_CONTAINER_SList *handles_read, *handles_write,
1045     *handles_except;
1046
1047   int i;
1048   struct timeval tvslice;
1049   int retcode;
1050   DWORD ms_total;
1051
1052 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1053
1054   /* calculate how long we need to wait in milliseconds */
1055   if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1056     ms_total = INFINITE;
1057
1058   else
1059     ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1060
1061   /* select() may be used as a portable way to sleep */
1062   if (!(rfds || wfds || efds))
1063
1064     {
1065       Sleep (ms_total);
1066       return 0;
1067     }
1068
1069   handles_read = GNUNET_CONTAINER_slist_create ();
1070   handles_write = GNUNET_CONTAINER_slist_create ();
1071   handles_except = GNUNET_CONTAINER_slist_create ();
1072
1073   if (rfds)
1074     sock_read = rfds->sds;
1075   else
1076     FD_ZERO (&sock_read);
1077   if (wfds)
1078     sock_write = wfds->sds;
1079   else
1080     FD_ZERO (&sock_write);
1081   if (efds)
1082     sock_except = efds->sds;
1083   else
1084     FD_ZERO (&sock_except);
1085
1086   /* multiplex between winsock select() and waiting on the handles */
1087   FD_ZERO (&aread);
1088   FD_ZERO (&awrite);
1089   FD_ZERO (&aexcept);
1090   limit = GetTickCount () + ms_total;
1091
1092   do
1093     {
1094       retcode = 0;
1095       if (nfds > 0)
1096
1097         {
1098
1099           /* overwrite the zero'd sets here; the select call
1100            * will clear those that are not active */
1101           FD_COPY (&sock_read, &aread);
1102           FD_COPY (&sock_write, &awrite);
1103           FD_COPY (&sock_except, &aexcept);
1104           tvslice.tv_sec = 0;
1105           tvslice.tv_usec = 100000;
1106           if ((retcode =
1107                select (nfds + 1, &aread, &awrite, &aexcept,
1108                        &tvslice)) == SOCKET_ERROR)
1109
1110             {
1111               SetErrnoFromWinsockError (WSAGetLastError ());
1112               if (errno == ENOTSOCK)
1113                 errno = EBADF;
1114
1115 #if DEBUG_NETWORK
1116               GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
1117
1118 #endif
1119               goto select_loop_end;
1120             }
1121         }
1122
1123       /* Poll read pipes */
1124       if (rfds)
1125
1126         {
1127           struct GNUNET_CONTAINER_SList_Iterator *i;
1128           for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1129                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1130                GNUNET_CONTAINER_slist_next (i))
1131
1132             {
1133               struct GNUNET_DISK_FileHandle *fh;
1134               DWORD dwBytes;
1135               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1136               if (fh->type == GNUNET_PIPE)
1137                 {
1138                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1139                     {
1140                       DWORD error_code = GetLastError ();
1141                       switch (error_code)
1142                       {
1143                       case ERROR_BROKEN_PIPE:
1144                         GNUNET_CONTAINER_slist_add (handles_read,
1145                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1146                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1147                         retcode++;
1148                         break;
1149                       default:
1150                         retcode = -1;
1151                         SetErrnoFromWinError (error_code);
1152
1153     #if DEBUG_NETWORK
1154                         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1155                                              "PeekNamedPipe");
1156
1157     #endif
1158                         goto select_loop_end;
1159                       }
1160                     }
1161                   else if (dwBytes)
1162
1163                     {
1164                       GNUNET_CONTAINER_slist_add (handles_read,
1165                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1166                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1167                       retcode++;
1168                     }
1169                 }
1170               else
1171                 {
1172                   /* Should we wait for more bytes to read here (in case of previous EOF)? */
1173                   GNUNET_CONTAINER_slist_add (handles_read,
1174                                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1175                                               fh, sizeof (struct GNUNET_DISK_FileHandle));
1176                 }
1177             }
1178           GNUNET_CONTAINER_slist_iter_destroy (i);
1179         }
1180
1181       /* Poll for faulty pipes */
1182       if (efds)
1183
1184         {
1185           struct GNUNET_CONTAINER_SList_Iterator *i;
1186           for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1187                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1188                GNUNET_CONTAINER_slist_next (i))
1189
1190             {
1191               struct GNUNET_DISK_FileHandle *fh;
1192               DWORD dwBytes;
1193
1194               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1195               if (fh->type == GNUNET_PIPE)
1196                 {
1197                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1198
1199                     {
1200                       GNUNET_CONTAINER_slist_add (handles_except,
1201                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1202                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1203                       retcode++;
1204                     }
1205                 }
1206             }
1207           GNUNET_CONTAINER_slist_iter_destroy (i);
1208         }
1209
1210       if (wfds)
1211         {
1212           GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1213           retcode += GNUNET_CONTAINER_slist_count (wfds->handles);
1214         }
1215
1216       /* Check for closed sockets */
1217       for (i = 0; i < nfds; i++)
1218
1219         {
1220           if (SAFE_FD_ISSET (i, &sock_read))
1221
1222             {
1223               struct sockaddr addr;
1224               int len;
1225               if (getpeername (i, &addr, &len) == SOCKET_ERROR)
1226
1227                 {
1228                   int err, len;
1229                   len = sizeof (err);
1230                   if (getsockopt
1231                       (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
1232                       && err == WSAENOTCONN)
1233
1234                     {
1235                       if (!SAFE_FD_ISSET (i, &aread))
1236
1237                         {
1238                           FD_SET (i, &aread);
1239                           retcode++;
1240                         }
1241                     }
1242                 }
1243             }
1244         }
1245     select_loop_end:
1246       if (retcode == 0 && nfds == 0)
1247         Sleep (GNUNET_MIN (100, limit - GetTickCount ()));
1248     }
1249   while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
1250
1251   if (retcode != -1)
1252     {
1253       if (rfds)
1254         {
1255           GNUNET_NETWORK_fdset_zero (rfds);
1256           GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1257           GNUNET_CONTAINER_slist_clear (rfds->handles);
1258           GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1259         }
1260       if (wfds)
1261         {
1262           GNUNET_NETWORK_fdset_zero (wfds);
1263           GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1264           GNUNET_CONTAINER_slist_clear (wfds->handles);
1265           GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1266         }
1267       if (efds)
1268         {
1269           GNUNET_NETWORK_fdset_zero (efds);
1270           GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1271           GNUNET_CONTAINER_slist_clear (efds->handles);
1272           GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1273         }
1274     }
1275
1276   GNUNET_CONTAINER_slist_destroy (handles_read);
1277   GNUNET_CONTAINER_slist_destroy (handles_write);
1278   GNUNET_CONTAINER_slist_destroy (handles_except);
1279
1280   return retcode;
1281 #endif
1282 }
1283
1284
1285 /* end of network.c */