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