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