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