5ff49b1cae10ed3132832bb9a6dd24b4e53f6453
[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_YES
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    * Number of bytes in addr.
55    */
56   socklen_t addrlen;
57
58   /**
59    * Address we were bound to, or NULL.
60    */
61   struct sockaddr *addr;
62
63 };
64
65
66 struct GNUNET_NETWORK_FDSet
67 {
68
69   /**
70    * Maximum number of any socket socket descriptor in the set (plus one)
71    */
72   int nsds;
73
74   /**
75    * Bitset with the descriptors.
76    */
77   fd_set sds;
78
79 #ifdef WINDOWS
80   /**
81    * Linked list of handles
82    */
83   struct GNUNET_CONTAINER_SList *handles;
84 #endif
85
86 };
87
88 #ifndef FD_COPY
89 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
90 #endif
91
92
93 /**
94  * Set if a socket should use blocking or non-blocking IO.
95  * @param fd socket
96  * @param doBlock blocking mode
97  * @return GNUNET_OK on success, GNUNET_SYSERR on error
98  */
99 static int
100 socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
101 {
102
103 #if MINGW
104   u_long mode;
105   mode = !doBlock;
106   if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
107
108     {
109       SetErrnoFromWinsockError (WSAGetLastError ());
110       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
111       return GNUNET_SYSERR;
112     }
113   return GNUNET_OK;
114
115 #else
116   /* not MINGW */
117   int flags = fcntl (fd->fd, F_GETFL);
118   if (flags == -1)
119
120     {
121       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
122       return GNUNET_SYSERR;
123     }
124   if (doBlock)
125     flags &= ~O_NONBLOCK;
126
127   else
128     flags |= O_NONBLOCK;
129   if (0 != fcntl (fd->fd, F_SETFL, flags))
130
131     {
132       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
133       return GNUNET_SYSERR;
134     }
135   return GNUNET_OK;
136 #endif
137 }
138
139
140 #ifndef MINGW
141 /**
142  * Make a socket non-inheritable to child processes
143  *
144  * @param h the socket to make non-inheritable
145  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
146  * @warning Not implemented on Windows
147  */
148 static int
149 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
150 {
151   int i;
152
153   i = fcntl (h->fd, F_GETFD);  
154   if (i < 0)
155     return GNUNET_SYSERR;
156   if (i == (i | FD_CLOEXEC))
157     return GNUNET_OK;
158   i |= FD_CLOEXEC;
159   if (fcntl (h->fd, F_SETFD, i) < 0)
160     return GNUNET_SYSERR;
161   return GNUNET_OK;
162 }
163 #endif
164
165
166 #ifdef DARWIN
167 /**
168  * The MSG_NOSIGNAL equivalent on Mac OS X
169  *
170  * @param h the socket to make non-delaying
171  */
172 static void
173 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
174 {
175   int abs_value = 1;
176   if (0 !=
177       setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, &abs_value, sizeof (abs_value)))
178     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
179 }
180 #endif
181
182
183 /**
184  * Disable delays when sending data via the socket.
185  * (GNUnet makes sure that messages are as big as
186  * possible already).
187  *
188  * @param h the socket to make non-delaying
189  */
190 static void
191 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
192 {
193 #ifndef WINDOWS  
194   int value = 1;
195   if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
196     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
197 #else
198   const char * abs_value = "1";
199   if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, abs_value, sizeof (abs_value)))
200     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
201 #endif  
202 }
203
204
205 /**
206  * accept a new connection on a socket
207  *
208  * @param desc bound socket
209  * @param address address of the connecting peer, may be NULL
210  * @param address_len length of address
211  * @return client socket
212  */
213 struct GNUNET_NETWORK_Handle *
214 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
215                               struct sockaddr *address,
216                               socklen_t * address_len)
217 {
218   struct GNUNET_NETWORK_Handle *ret;
219
220   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
221   ret->fd = accept (desc->fd, address, address_len);
222   ret->af = address->sa_family;
223   if (ret->fd == INVALID_SOCKET)
224     {
225 #ifdef MINGW
226       SetErrnoFromWinsockError (WSAGetLastError ());
227 #endif
228       GNUNET_free (ret);
229       return NULL;
230     }
231 #ifndef MINGW
232   if (ret->fd >= FD_SETSIZE)
233     {
234       GNUNET_break (0 == close (ret->fd));
235       GNUNET_free (ret);
236       errno = EMFILE;
237       return NULL;
238     }
239 #endif
240   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
241
242     {
243
244       /* we might want to treat this one as fatal... */
245       GNUNET_break (0);
246       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret));
247       return NULL;
248     }
249
250 #ifndef MINGW
251   if (GNUNET_OK != socket_set_inheritable (ret))
252     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
253                          "socket_set_inheritable");
254 #endif
255 #ifdef DARWIN
256   socket_set_nosigpipe (ret);
257 #endif
258 #ifdef AF_UNIX
259   if (address->sa_family != AF_UNIX)
260 #endif
261     socket_set_nodelay (ret);
262   return ret;
263 }
264
265
266 /**
267  * Bind to a connected socket
268  * @param desc socket
269  * @param address address to be bound
270  * @param address_len length of address
271  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
272  */
273 int
274 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
275                             const struct sockaddr *address,
276                             socklen_t address_len)
277 {
278   int ret;
279   
280 #ifdef IPV6_V6ONLY 
281 #ifdef IPPROTO_IPV6
282   const int on = 1;
283   if (desc->af == AF_INET6)
284     if (0 != setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
285       GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
286 #if 0
287   /* is this needed or desired? or done elsewhere? */
288   if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
289     GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
290 #endif
291 #endif
292 #endif
293 #ifndef LINUX
294 #ifndef MINGW
295   if (address->sa_family == AF_UNIX)
296     {
297       const struct sockaddr_un *un = (const struct sockaddr_un*) address;
298       (void) unlink (un->sun_path);
299     }
300 #endif
301 #endif
302   ret = bind (desc->fd, address, address_len);
303 #ifdef MINGW
304   if (SOCKET_ERROR == ret)
305     SetErrnoFromWinsockError (WSAGetLastError ());
306 #endif
307   if (ret != 0)
308           return GNUNET_SYSERR;
309 #ifndef MINGW
310 #ifndef LINUX
311   desc->addr = GNUNET_malloc (address_len);
312   memcpy (desc->addr, address, address_len);
313   desc->addrlen = address_len;
314 #endif
315 #endif
316   return GNUNET_OK;
317 }
318
319
320 /**
321  * Close a socket
322  * @param desc socket
323  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
324  */
325 int
326 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
327 {
328   int ret;
329
330 #ifdef MINGW
331   ret = closesocket (desc->fd);
332   SetErrnoFromWinsockError (WSAGetLastError ());
333 #else
334   ret = close (desc->fd);
335 #endif
336 #ifndef LINUX
337 #ifndef MINGW
338   if ( (desc->af == AF_UNIX) && (NULL != desc->addr) )
339     {
340       const struct sockaddr_un *un = (const struct sockaddr_un*) desc->addr;
341       if (0 != unlink (un->sun_path))
342           GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
343                                   "unlink",
344                                   un->sun_path);
345     }
346 #endif
347 #endif
348    GNUNET_free_non_null (desc->addr);
349   GNUNET_free (desc);
350   return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
351 }
352
353
354 /**
355  * Box a native socket (and check that it is a socket).
356  *
357  * @param fd socket to box
358  * @return NULL on error (including not supported on target platform)
359  */
360 struct GNUNET_NETWORK_Handle *
361 GNUNET_NETWORK_socket_box_native (int fd)
362 {
363 #if MINGW
364   return NULL;
365 #else
366   struct GNUNET_NETWORK_Handle *ret;
367
368   if (fcntl (fd, F_GETFD) < 0)
369     return NULL; /* invalid FD */
370   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle)); 
371   ret->fd = fd;
372   ret->af = AF_UNSPEC;
373   return ret;
374 #endif
375 }
376
377
378 /**
379  * Connect a socket
380  * @param desc socket
381  * @param address peer address
382  * @param address_len length of address
383  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
384  */
385 int
386 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
387                                const struct sockaddr *address,
388                                socklen_t address_len)
389 {
390   int ret;
391   ret = connect (desc->fd, address, address_len);
392
393 #ifdef MINGW
394   if (SOCKET_ERROR == ret)
395
396     {
397       SetErrnoFromWinsockError (WSAGetLastError ());
398       if (errno == EWOULDBLOCK)
399         errno = EINPROGRESS;
400     }
401 #endif
402   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
403 }
404
405
406 /**
407  * Get socket options
408  *
409  * @param desc socket
410  * @param level protocol level of the option
411  * @param optname identifier of the option
412  * @param optval options
413  * @param optlen length of optval
414  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
415  */
416 int
417 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
418                                   int level, int optname, void *optval,
419                                   socklen_t * optlen)
420 {
421   int ret;
422   ret = getsockopt (desc->fd, level, optname, optval, optlen);
423
424 #ifdef MINGW
425   if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
426     *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
427
428   else if (SOCKET_ERROR == ret)
429     SetErrnoFromWinsockError (WSAGetLastError ());
430
431 #endif
432   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
433 }
434
435
436 /**
437  * Listen on a socket
438  * @param desc socket
439  * @param backlog length of the listen queue
440  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
441  */
442 int
443 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
444                               int backlog)
445 {
446   int ret;
447   ret = listen (desc->fd, backlog);
448
449 #ifdef MINGW
450   if (SOCKET_ERROR == ret)
451     SetErrnoFromWinsockError (WSAGetLastError ());
452
453 #endif
454   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
455 }
456
457
458 /**
459  * How much data is available to be read on this descriptor?
460  *
461  * Returns GNUNET_NO if no data is available, or on error!
462  * @param desc socket
463  */
464 ssize_t
465 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle
466                                        *desc)
467 {
468   int error;
469
470   /* How much is there to be read? */
471 #ifndef WINDOWS
472   int pending;
473   error = ioctl (desc->fd, FIONREAD, &pending);
474   if (error == 0)
475 #else
476   u_long pending;
477   error = ioctlsocket (desc->fd, FIONREAD, &pending);
478   if (error != SOCKET_ERROR)
479 #endif
480     return pending;
481   else
482     return GNUNET_NO;
483 }
484
485
486 /**
487  * Read data from a connected socket (always non-blocking).
488  * @param desc socket
489  * @param buffer buffer
490  * @param length length of buffer
491  * @param src_addr either the source to recv from, or all zeroes
492  *        to be filled in by recvfrom
493  * @param addrlen length of the addr
494  */
495 ssize_t
496 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
497                                 void *buffer, size_t length,
498                                 struct sockaddr * src_addr,
499                                 socklen_t * addrlen)
500 {
501   int ret;
502   int flags;
503   flags = 0;
504
505 #ifdef MSG_DONTWAIT
506   flags |= MSG_DONTWAIT;
507
508 #endif
509   ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
510 #ifdef MINGW
511   if (SOCKET_ERROR == ret)
512     SetErrnoFromWinsockError (WSAGetLastError ());
513 #endif 
514   return ret;
515 }
516
517
518 /**
519  * Read data from a connected socket (always non-blocking).
520  * @param desc socket
521  * @param buffer buffer
522  * @param length length of buffer
523  */
524 ssize_t
525 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
526                             void *buffer, size_t length)
527 {
528   int ret;
529   int flags;
530   flags = 0;
531
532 #ifdef MSG_DONTWAIT
533   flags |= MSG_DONTWAIT;
534 #endif
535   ret = recv (desc->fd, buffer, length, flags);
536 #ifdef MINGW
537   if (SOCKET_ERROR == ret)
538     SetErrnoFromWinsockError (WSAGetLastError ());
539 #endif
540   return ret;
541 }
542
543
544 /**
545  * Send data (always non-blocking).
546  *
547  * @param desc socket
548  * @param buffer data to send
549  * @param length size of the buffer
550  * @return number of bytes sent, GNUNET_SYSERR on error
551  */
552 ssize_t
553 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
554                             const void *buffer, size_t length)
555 {
556   int ret;
557   int flags;
558   flags = 0;
559
560 #ifdef MSG_DONTWAIT
561   flags |= MSG_DONTWAIT;
562
563 #endif /*  */
564 #ifdef MSG_NOSIGNAL
565   flags |= MSG_NOSIGNAL;
566
567 #endif /*  */
568   ret = send (desc->fd, buffer, length, flags);
569
570 #ifdef MINGW
571   if (SOCKET_ERROR == ret)
572     SetErrnoFromWinsockError (WSAGetLastError ());
573
574 #endif /*  */
575   return ret;
576 }
577
578
579 /**
580  * Send data to a particular destination (always non-blocking).
581  * This function only works for UDP sockets.
582  *
583  * @param desc socket
584  * @param message data to send
585  * @param length size of the data
586  * @param dest_addr destination address
587  * @param dest_len length of address
588  * @return number of bytes sent, GNUNET_SYSERR on error
589  */
590 ssize_t
591 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
592                               const void *message, size_t length,
593                               const struct sockaddr * dest_addr,
594                               socklen_t dest_len)
595 {
596   int ret;
597   int flags;
598   flags = 0;
599
600 #ifdef MSG_DONTWAIT
601   flags |= MSG_DONTWAIT;
602 #endif
603 #ifdef MSG_NOSIGNAL
604   flags |= MSG_NOSIGNAL;
605 #endif
606   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
607 #ifdef MINGW
608   if (SOCKET_ERROR == ret)
609     SetErrnoFromWinsockError (WSAGetLastError ());
610 #endif
611   return ret;
612 }
613
614
615 /**
616  * Set socket option
617  * @param fd socket
618  * @param level protocol level of the option
619  * @param option_name option identifier
620  * @param option_value value to set
621  * @param option_len size of option_value
622  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
623  */
624 int
625 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd,
626                                   int level, int option_name,
627                                   const void *option_value,
628                                   socklen_t option_len)
629 {
630   int ret;
631
632   ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
633 #ifdef MINGW
634   if (SOCKET_ERROR == ret)
635     SetErrnoFromWinsockError (WSAGetLastError ());
636 #endif
637   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
638 }
639
640
641 /**
642  * Create a new socket.  Configure it for non-blocking IO and
643  * mark it as non-inheritable to child processes (set the
644  * close-on-exec flag).
645  *
646  * @param domain domain of the socket
647  * @param type socket type
648  * @param protocol network protocol
649  * @return new socket, NULL on error
650  */
651 struct GNUNET_NETWORK_Handle *
652 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
653 {
654   struct GNUNET_NETWORK_Handle *ret;
655   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
656   ret->af = domain;
657   ret->fd = socket (domain, type, protocol);
658   if (INVALID_SOCKET == ret->fd)
659     {
660 #ifdef MINGW
661       SetErrnoFromWinsockError (WSAGetLastError ());
662 #endif
663       GNUNET_free (ret);
664       return NULL;
665     }
666
667 #ifndef MINGW
668   if (ret->fd >= FD_SETSIZE)
669     {
670       GNUNET_break (0 == close (ret->fd));
671       GNUNET_free (ret);
672       errno = EMFILE;
673       return NULL;
674     }
675
676 #endif
677   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
678     {
679       /* we might want to treat this one as fatal... */
680       GNUNET_break (0);
681       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret));
682       return NULL;
683     }
684
685 #ifndef MINGW
686   if (GNUNET_OK != socket_set_inheritable (ret))
687     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
688                          "socket_set_inheritable");
689 #endif
690 #ifdef DARWIN
691   socket_set_nosigpipe (ret);
692 #endif
693   if ( (type == SOCK_STREAM) 
694 #ifdef AF_UNIX
695        && (domain != AF_UNIX) 
696 #endif
697        )
698     socket_set_nodelay (ret);
699   return ret;
700 }
701
702
703 /**
704  * Shut down socket operations
705  * @param desc socket
706  * @param how type of shutdown
707  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
708  */
709 int
710 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
711 {
712   int ret;
713
714   ret = shutdown (desc->fd, how);
715 #ifdef MINGW
716   if (ret != 0)
717     SetErrnoFromWinsockError (WSAGetLastError ());
718 #endif
719   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
720 }
721
722
723 /**
724  * Reset FD set
725  * @param fds fd set
726  */
727 void
728 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
729 {
730   FD_ZERO (&fds->sds);
731   fds->nsds = 0;
732 #ifdef MINGW
733   GNUNET_CONTAINER_slist_clear (fds->handles);
734 #endif
735 }
736
737 /**
738  * Add a socket to the FD set
739  * @param fds fd set
740  * @param desc socket to add
741  */
742 void
743 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
744                           const struct GNUNET_NETWORK_Handle *desc)
745 {
746   FD_SET (desc->fd, &fds->sds);
747   if (desc->fd + 1 > fds->nsds)
748     fds->nsds = desc->fd + 1;
749 }
750
751
752 /**
753  * Check whether a socket is part of the fd set
754  * @param fds fd set
755  * @param desc socket
756  * @return 0 if the FD is not set
757  */
758 int
759 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
760                             const struct GNUNET_NETWORK_Handle *desc)
761 {
762   return FD_ISSET (desc->fd, &fds->sds);
763 }
764
765
766 /**
767  * Add one fd set to another
768  * @param dst the fd set to add to
769  * @param src the fd set to add from
770  */
771 void
772 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
773                           const struct GNUNET_NETWORK_FDSet *src)
774 {
775   int nfds;
776   for (nfds = src->nsds; nfds > 0; nfds--)
777     if (FD_ISSET (nfds, &src->sds))
778
779       {
780         FD_SET (nfds, &dst->sds);
781         if (nfds + 1 > dst->nsds)
782           dst->nsds = nfds + 1;
783       }
784 #ifdef MINGW
785   GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
786 #endif
787 }
788
789
790 /**
791  * Copy one fd set to another
792  *
793  * @param to destination
794  * @param from source
795  */
796 void
797 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
798                            const struct GNUNET_NETWORK_FDSet *from)
799 {
800   FD_COPY (&from->sds, &to->sds);
801   to->nsds = from->nsds;
802
803 #ifdef MINGW
804   GNUNET_CONTAINER_slist_clear (to->handles);
805   GNUNET_CONTAINER_slist_append (to->handles, from->handles);
806 #endif
807 }
808
809
810 /**
811  * Return file descriptor for this network handle
812  *
813  * @param desc wrapper to process
814  * @return POSIX file descriptor
815  */
816 int
817 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
818 {
819   return desc->fd;
820 }
821
822
823 /**
824  * Copy a native fd set
825  *
826  * @param to destination
827  * @param from native source set
828  * @param nfds the biggest socket number in from + 1
829  */
830 void
831 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
832                                   const fd_set * from, int nfds)
833 {
834   FD_COPY (from, &to->sds);
835   to->nsds = nfds;
836 }
837
838
839 /**
840  * Set a native fd in a set
841  *
842  * @param to destination
843  * @param nfd native FD to set
844  */
845 void GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to,
846                                       int nfd)
847 {
848   GNUNET_assert(nfd >= 0);
849   FD_SET (nfd, &to->sds);
850   to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
851 }
852
853
854 /**
855  * Test native fd in a set
856  *
857  * @param to set to test, NULL for empty set
858  * @param nfd native FD to test, or -1 for none
859  * @return GNUNET_YES if FD is set in the set
860  */
861 int 
862 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
863                                   int nfd)
864 {
865   if ( (nfd == -1) || (to == NULL) )
866     return GNUNET_NO;
867   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
868 }
869
870
871 /**
872  * Add a file handle to the fd set
873  * @param fds fd set
874  * @param h the file handle to add
875  */
876 void
877 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
878                                  const struct GNUNET_DISK_FileHandle *h)
879 {
880 #ifdef MINGW
881   GNUNET_CONTAINER_slist_add (fds->handles,
882                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
883                               h, sizeof (struct GNUNET_DISK_FileHandle));
884
885 #else
886   int fd;
887   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
888   FD_SET (fd, &fds->sds);
889   if (fd + 1 > fds->nsds)
890     fds->nsds = fd + 1;
891
892 #endif
893 }
894
895
896 /**
897  * Check if a file handle is part of an fd set
898  * @param fds fd set
899  * @param h file handle
900  * @return GNUNET_YES if the file handle is part of the set
901  */
902 int
903 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
904                                    const struct GNUNET_DISK_FileHandle *h)
905 {
906
907 #ifdef MINGW
908   return GNUNET_CONTAINER_slist_contains (fds->handles, h,
909                                           sizeof (struct GNUNET_DISK_FileHandle));
910 #else
911   return FD_ISSET (h->fd, &fds->sds);
912 #endif
913 }
914
915
916 /**
917  * Checks if two fd sets overlap
918  * @param fds1 first fd set
919  * @param fds2 second fd set
920  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
921  */
922 int
923 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
924                               const struct GNUNET_NETWORK_FDSet *fds2)
925 {
926 #ifndef MINGW
927   int nfds;
928
929   nfds = fds1->nsds;
930   if (nfds > fds2->nsds)
931     nfds = fds2->nsds;
932   while (nfds > 0)
933     {
934       nfds--;
935       if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
936         return GNUNET_YES;
937     }
938 #else
939   struct GNUNET_CONTAINER_SList_Iterator *it;
940   struct GNUNET_DISK_FileHandle *h;
941   int i;
942   int j;
943
944   /*This code is somewhat hacky, we are not supposed to know what's
945     inside of fd_set; also the O(n^2) is really bad... */
946
947   for (i = 0; i < fds1->sds.fd_count; i++)
948   {
949     for (j = 0; j < fds2->sds.fd_count; j++)
950     {
951       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
952         return GNUNET_YES;
953     }
954   }
955   it = GNUNET_CONTAINER_slist_begin (fds1->handles);
956   while (GNUNET_CONTAINER_slist_end (it) != GNUNET_YES)
957     {
958       h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (it, NULL);
959       if (GNUNET_CONTAINER_slist_contains
960           (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
961         {
962           GNUNET_CONTAINER_slist_iter_destroy (it);
963           return GNUNET_YES;
964         }
965       GNUNET_CONTAINER_slist_next (it);
966     }
967   GNUNET_CONTAINER_slist_iter_destroy (it);
968 #endif
969   return GNUNET_NO;
970 }
971
972
973 /**
974  * Creates an fd set
975  * @return a new fd set
976  */
977 struct GNUNET_NETWORK_FDSet *
978 GNUNET_NETWORK_fdset_create ()
979 {
980   struct GNUNET_NETWORK_FDSet *fds;
981   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
982 #ifdef MINGW
983   fds->handles = GNUNET_CONTAINER_slist_create ();
984 #endif
985   GNUNET_NETWORK_fdset_zero (fds);
986   return fds;
987 }
988
989
990 /**
991  * Releases the associated memory of an fd set
992  * @param fds fd set
993  */
994 void
995 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
996 {
997 #ifdef MINGW
998   GNUNET_CONTAINER_slist_destroy (fds->handles);
999 #endif
1000   GNUNET_free (fds);
1001 }
1002
1003 /**
1004  * Check if sockets meet certain conditions
1005  * @param rfds set of sockets to be checked for readability
1006  * @param wfds set of sockets to be checked for writability
1007  * @param efds set of sockets to be checked for exceptions
1008  * @param timeout relative value when to return
1009  * @return number of selected sockets, GNUNET_SYSERR on error
1010  */
1011 int
1012 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1013                               struct GNUNET_NETWORK_FDSet *wfds,
1014                               struct GNUNET_NETWORK_FDSet *efds,
1015                               const struct GNUNET_TIME_Relative timeout)
1016 {
1017   int nfds;
1018 #ifdef MINGW
1019   int handles;
1020 #endif
1021   nfds = 0;
1022 #ifdef MINGW
1023   handles = 0;
1024 #endif
1025   if (NULL != rfds)
1026     {
1027       nfds = rfds->nsds;
1028 #ifdef MINGW
1029       handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1030 #endif
1031     }
1032   if (NULL != wfds)
1033     {
1034       nfds = GNUNET_MAX (nfds, wfds->nsds);
1035 #ifdef MINGW
1036       handles += GNUNET_CONTAINER_slist_count (wfds->handles);
1037 #endif
1038     }
1039   if (NULL != efds)
1040     {
1041       nfds = GNUNET_MAX (nfds, efds->nsds);
1042 #ifdef MINGW
1043       handles += GNUNET_CONTAINER_slist_count (efds->handles);
1044 #endif
1045     }
1046
1047   struct timeval tv;
1048   tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1049   tv.tv_usec =
1050     1000 * (timeout.rel_value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1051   if ((nfds == 0) && (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1052 #ifdef MINGW
1053       && handles == 0
1054 #endif
1055     )
1056     {
1057       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1058                   _
1059                   ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1060                   "select");
1061       GNUNET_break (0);
1062     }
1063 #ifndef MINGW
1064   return select (nfds,
1065                  (rfds != NULL) ? &rfds->sds : NULL,
1066                  (wfds != NULL) ? &wfds->sds : NULL,
1067                  (efds != NULL) ? &efds->sds : NULL,
1068                  (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1069                  ? NULL : &tv);
1070
1071 #else
1072   DWORD limit;
1073   fd_set sock_read, sock_write, sock_except;
1074   fd_set aread, awrite, aexcept;
1075   struct GNUNET_CONTAINER_SList *handles_read, *handles_write,
1076     *handles_except;
1077
1078   int i;
1079   struct timeval tvslice;
1080   int retcode;
1081   DWORD ms_total;
1082
1083 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1084
1085   /* calculate how long we need to wait in milliseconds */
1086   if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1087     ms_total = INFINITE;
1088
1089   else
1090     ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1091
1092   /* select() may be used as a portable way to sleep */
1093   if (!(rfds || wfds || efds))
1094
1095     {
1096       Sleep (ms_total);
1097       return 0;
1098     }
1099
1100   handles_read = GNUNET_CONTAINER_slist_create ();
1101   handles_write = GNUNET_CONTAINER_slist_create ();
1102   handles_except = GNUNET_CONTAINER_slist_create ();
1103
1104   if (rfds)
1105     sock_read = rfds->sds;
1106   else
1107     FD_ZERO (&sock_read);
1108   if (wfds)
1109     sock_write = wfds->sds;
1110   else
1111     FD_ZERO (&sock_write);
1112   if (efds)
1113     sock_except = efds->sds;
1114   else
1115     FD_ZERO (&sock_except);
1116
1117   /* multiplex between winsock select() and waiting on the handles */
1118   FD_ZERO (&aread);
1119   FD_ZERO (&awrite);
1120   FD_ZERO (&aexcept);
1121   limit = GetTickCount () + ms_total;
1122
1123   do
1124     {
1125       retcode = 0;
1126       if (nfds > 0)
1127
1128         {
1129
1130           /* overwrite the zero'd sets here; the select call
1131            * will clear those that are not active */
1132           FD_COPY (&sock_read, &aread);
1133           FD_COPY (&sock_write, &awrite);
1134           FD_COPY (&sock_except, &aexcept);
1135           tvslice.tv_sec = 0;
1136           tvslice.tv_usec = 100000;
1137           if ((retcode =
1138                select (nfds + 1, &aread, &awrite, &aexcept,
1139                        &tvslice)) == SOCKET_ERROR)
1140
1141             {
1142               SetErrnoFromWinsockError (WSAGetLastError ());
1143               if (errno == ENOTSOCK)
1144                 errno = EBADF;
1145
1146 #if DEBUG_NETWORK
1147               GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
1148
1149 #endif
1150               goto select_loop_end;
1151             }
1152         }
1153
1154       /* Poll read pipes */
1155       if (rfds)
1156
1157         {
1158           struct GNUNET_CONTAINER_SList_Iterator *i;
1159           for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1160                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1161                GNUNET_CONTAINER_slist_next (i))
1162
1163             {
1164               struct GNUNET_DISK_FileHandle *fh;
1165               DWORD dwBytes;
1166               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1167               if (fh->type == GNUNET_PIPE)
1168                 {
1169                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1170                     {
1171                       DWORD error_code = GetLastError ();
1172                       switch (error_code)
1173                       {
1174                       case ERROR_BROKEN_PIPE:
1175                         GNUNET_CONTAINER_slist_add (handles_read,
1176                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1177                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1178                         retcode++;
1179                         break;
1180                       default:
1181                         retcode = -1;
1182                         SetErrnoFromWinError (error_code);
1183
1184     #if DEBUG_NETWORK
1185                         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1186                                              "PeekNamedPipe");
1187
1188     #endif
1189                         goto select_loop_end;
1190                       }
1191                     }
1192                   else if (dwBytes)
1193
1194                     {
1195                       GNUNET_CONTAINER_slist_add (handles_read,
1196                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1197                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1198                       retcode++;
1199                     }
1200                 }
1201               else
1202                 {
1203                   /* Should we wait for more bytes to read here (in case of previous EOF)? */
1204                   GNUNET_CONTAINER_slist_add (handles_read,
1205                                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1206                                               fh, sizeof (struct GNUNET_DISK_FileHandle));
1207                 }
1208             }
1209           GNUNET_CONTAINER_slist_iter_destroy (i);
1210         }
1211
1212       /* Poll for faulty pipes */
1213       if (efds)
1214
1215         {
1216           struct GNUNET_CONTAINER_SList_Iterator *i;
1217           for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1218                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1219                GNUNET_CONTAINER_slist_next (i))
1220
1221             {
1222               struct GNUNET_DISK_FileHandle *fh;
1223               DWORD dwBytes;
1224
1225               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1226               if (fh->type == GNUNET_PIPE)
1227                 {
1228                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1229
1230                     {
1231                       GNUNET_CONTAINER_slist_add (handles_except,
1232                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1233                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1234                       retcode++;
1235                     }
1236                 }
1237             }
1238           GNUNET_CONTAINER_slist_iter_destroy (i);
1239         }
1240
1241       if (wfds)
1242         {
1243           GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1244           retcode += GNUNET_CONTAINER_slist_count (wfds->handles);
1245         }
1246
1247       /* Check for closed sockets */
1248       for (i = 0; i < nfds; i++)
1249
1250         {
1251           if (SAFE_FD_ISSET (i, &sock_read))
1252
1253             {
1254               struct sockaddr addr;
1255               int len;
1256               if (getpeername (i, &addr, &len) == SOCKET_ERROR)
1257
1258                 {
1259                   int err, len;
1260                   len = sizeof (err);
1261                   if (getsockopt
1262                       (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
1263                       && err == WSAENOTCONN)
1264
1265                     {
1266                       if (!SAFE_FD_ISSET (i, &aread))
1267
1268                         {
1269                           FD_SET (i, &aread);
1270                           retcode++;
1271                         }
1272                     }
1273                 }
1274             }
1275         }
1276     select_loop_end:
1277       if (retcode == 0 && nfds == 0)
1278         Sleep (GNUNET_MIN (100, limit - GetTickCount ()));
1279     }
1280   while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
1281
1282   if (retcode != -1)
1283     {
1284       if (rfds)
1285         {
1286           GNUNET_NETWORK_fdset_zero (rfds);
1287           GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1288           GNUNET_CONTAINER_slist_clear (rfds->handles);
1289           GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1290         }
1291       if (wfds)
1292         {
1293           GNUNET_NETWORK_fdset_zero (wfds);
1294           GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1295           GNUNET_CONTAINER_slist_clear (wfds->handles);
1296           GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1297         }
1298       if (efds)
1299         {
1300           GNUNET_NETWORK_fdset_zero (efds);
1301           GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1302           GNUNET_CONTAINER_slist_clear (efds->handles);
1303           GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1304         }
1305     }
1306
1307   GNUNET_CONTAINER_slist_destroy (handles_read);
1308   GNUNET_CONTAINER_slist_destroy (handles_write);
1309   GNUNET_CONTAINER_slist_destroy (handles_except);
1310
1311   return retcode;
1312 #endif
1313 }
1314
1315
1316 /* end of network.c */