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