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