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