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