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