diff options
Diffstat (limited to 'src/util/network_socket.c')
-rw-r--r-- | src/util/network_socket.c | 678 |
1 files changed, 678 insertions, 0 deletions
diff --git a/src/util/network_socket.c b/src/util/network_socket.c new file mode 100644 index 000000000..59afb7246 --- /dev/null +++ b/src/util/network_socket.c | |||
@@ -0,0 +1,678 @@ | |||
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/sock.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_SOCK GNUNET_NO | ||
33 | |||
34 | struct GNUNET_NETWORK_Descriptor | ||
35 | { | ||
36 | int fd; | ||
37 | }; | ||
38 | |||
39 | struct GNUNET_NETWORK_FDSet | ||
40 | { | ||
41 | /* socket descriptors */ | ||
42 | int nsds; | ||
43 | fd_set sds; | ||
44 | #ifdef WINDOWS | ||
45 | /* handles */ | ||
46 | struct GNUNET_CONTAINER_Vector *handles; | ||
47 | #endif | ||
48 | }; | ||
49 | |||
50 | #ifndef FD_COPY | ||
51 | #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set))) | ||
52 | #endif | ||
53 | |||
54 | struct GNUNET_NETWORK_Descriptor * | ||
55 | GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Descriptor *desc, | ||
56 | struct sockaddr *address, | ||
57 | socklen_t * address_len) | ||
58 | { | ||
59 | struct GNUNET_NETWORK_Descriptor *ret; | ||
60 | |||
61 | ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor)); | ||
62 | ret->fd = accept (desc->fd, address, address_len); | ||
63 | #ifdef MINGW | ||
64 | if (INVALID_SOCKET == ret->fd) | ||
65 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
66 | #endif | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | int | ||
71 | GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Descriptor *desc, | ||
72 | const struct sockaddr *address, | ||
73 | socklen_t address_len) | ||
74 | { | ||
75 | int ret; | ||
76 | |||
77 | ret = bind (desc->fd, address, address_len); | ||
78 | #ifdef MINGW | ||
79 | if (SOCKET_ERROR == ret) | ||
80 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
81 | #endif | ||
82 | return ret; | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * Set if a socket should use blocking or non-blocking IO. | ||
87 | * | ||
88 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
89 | */ | ||
90 | int | ||
91 | GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Descriptor *fd, | ||
92 | int doBlock) | ||
93 | { | ||
94 | #if MINGW | ||
95 | u_long mode; | ||
96 | mode = !doBlock; | ||
97 | if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR) | ||
98 | { | ||
99 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
100 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket"); | ||
101 | return GNUNET_SYSERR; | ||
102 | } | ||
103 | return GNUNET_OK; | ||
104 | |||
105 | #else | ||
106 | /* not MINGW */ | ||
107 | int flags = fcntl (fd->fd, F_GETFL); | ||
108 | if (flags == -1) | ||
109 | { | ||
110 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl"); | ||
111 | return GNUNET_SYSERR; | ||
112 | } | ||
113 | if (doBlock) | ||
114 | flags &= ~O_NONBLOCK; | ||
115 | else | ||
116 | flags |= O_NONBLOCK; | ||
117 | if (0 != fcntl (fd->fd, F_SETFL, flags)) | ||
118 | { | ||
119 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl"); | ||
120 | return GNUNET_SYSERR; | ||
121 | } | ||
122 | return GNUNET_OK; | ||
123 | #endif | ||
124 | } | ||
125 | |||
126 | int | ||
127 | GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Descriptor *desc) | ||
128 | { | ||
129 | int ret; | ||
130 | #ifdef MINGW | ||
131 | ret = closesocket (desc->fd); | ||
132 | if (SOCKET_ERROR != ret) | ||
133 | GNUNET_free (desc); | ||
134 | else | ||
135 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
136 | #else | ||
137 | ret = close (desc->fd); | ||
138 | if (-1 == ret) | ||
139 | { | ||
140 | GNUNET_free (desc); | ||
141 | } | ||
142 | #endif | ||
143 | |||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | int | ||
148 | GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Descriptor *desc, | ||
149 | const struct sockaddr *address, | ||
150 | socklen_t address_len) | ||
151 | { | ||
152 | int ret; | ||
153 | |||
154 | ret = connect (desc->fd, address, address_len); | ||
155 | #ifdef MINGW | ||
156 | if (SOCKET_ERROR == ret) | ||
157 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
158 | #endif | ||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | int | ||
163 | GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Descriptor *desc, | ||
164 | int level, int optname, void *optval, | ||
165 | socklen_t * optlen) | ||
166 | { | ||
167 | int ret; | ||
168 | |||
169 | ret = getsockopt (desc->fd, level, optname, optval, optlen); | ||
170 | #ifdef MINGW | ||
171 | if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR) | ||
172 | *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval)); | ||
173 | else if (SOCKET_ERROR == ret) | ||
174 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
175 | #endif | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | int | ||
180 | GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Descriptor *desc, | ||
181 | int backlog) | ||
182 | { | ||
183 | int ret; | ||
184 | |||
185 | ret = listen (desc->fd, backlog); | ||
186 | #ifdef MINGW | ||
187 | if (SOCKET_ERROR == ret) | ||
188 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
189 | #endif | ||
190 | |||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | ssize_t | ||
195 | GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Descriptor * desc, | ||
196 | void *buffer, size_t length, int flags) | ||
197 | { | ||
198 | int ret; | ||
199 | |||
200 | ret = recv (desc->fd, buffer, length, flags); | ||
201 | #ifdef MINGW | ||
202 | if (SOCKET_ERROR == ret) | ||
203 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
204 | #endif | ||
205 | |||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | ssize_t | ||
210 | GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Descriptor * desc, | ||
211 | const void *buffer, size_t length, int flags) | ||
212 | { | ||
213 | int ret; | ||
214 | |||
215 | ret = send (desc->fd, buffer, length, flags); | ||
216 | #ifdef MINGW | ||
217 | if (SOCKET_ERROR == ret) | ||
218 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
219 | #endif | ||
220 | |||
221 | return ret; | ||
222 | } | ||
223 | |||
224 | ssize_t | ||
225 | GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Descriptor * desc, | ||
226 | const void *message, size_t length, int flags, | ||
227 | const struct sockaddr * dest_addr, | ||
228 | socklen_t dest_len) | ||
229 | { | ||
230 | int ret; | ||
231 | |||
232 | ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len); | ||
233 | #ifdef MINGW | ||
234 | if (SOCKET_ERROR == ret) | ||
235 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
236 | #endif | ||
237 | |||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | int | ||
242 | GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Descriptor *fd, | ||
243 | int level, int option_name, | ||
244 | const void *option_value, | ||
245 | socklen_t option_len) | ||
246 | { | ||
247 | int ret; | ||
248 | |||
249 | ret = setsockopt (fd->fd, level, option_name, option_value, option_len); | ||
250 | #ifdef MINGW | ||
251 | if (SOCKET_ERROR == ret) | ||
252 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
253 | #endif | ||
254 | |||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | struct GNUNET_NETWORK_Descriptor * | ||
259 | GNUNET_NETWORK_socket_socket (int domain, int type, int protocol) | ||
260 | { | ||
261 | struct GNUNET_NETWORK_Descriptor *ret; | ||
262 | |||
263 | ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor)); | ||
264 | ret->fd = socket (domain, type, protocol); | ||
265 | #ifdef MINGW | ||
266 | if (INVALID_SOCKET == ret->fd) | ||
267 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
268 | #endif | ||
269 | |||
270 | if (ret->fd < 0) | ||
271 | { | ||
272 | GNUNET_free (ret); | ||
273 | ret = NULL; | ||
274 | } | ||
275 | |||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | int | ||
280 | GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Descriptor *desc, | ||
281 | int how) | ||
282 | { | ||
283 | int ret; | ||
284 | |||
285 | ret = shutdown (desc->fd, how); | ||
286 | #ifdef MINGW | ||
287 | if (ret != 0) | ||
288 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
289 | #endif | ||
290 | |||
291 | return ret; | ||
292 | } | ||
293 | |||
294 | int | ||
295 | GNUNET_NETWORK_socket_set_inheritable (const struct GNUNET_NETWORK_Descriptor | ||
296 | *desc) | ||
297 | { | ||
298 | #ifdef MINGW | ||
299 | errno = ENOSYS; | ||
300 | return GNUNET_SYSERR; | ||
301 | #else | ||
302 | return fcntl (desc->fd, F_SETFD, | ||
303 | fcntl (desc->fd, | ||
304 | F_GETFD) | FD_CLOEXEC) == | ||
305 | 0 ? GNUNET_OK : GNUNET_SYSERR; | ||
306 | #endif | ||
307 | } | ||
308 | |||
309 | void | ||
310 | GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds) | ||
311 | { | ||
312 | FD_ZERO (&fds->sds); | ||
313 | fds->nsds = 0; | ||
314 | #ifdef MINGW | ||
315 | if (fds->handles) | ||
316 | GNUNET_CONTAINER_vector_destroy (fds->handles); | ||
317 | fds->handles = GNUNET_CONTAINER_vector_create (2); | ||
318 | #endif | ||
319 | } | ||
320 | |||
321 | void | ||
322 | GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds, | ||
323 | const struct GNUNET_NETWORK_Descriptor *desc) | ||
324 | { | ||
325 | FD_SET (desc->fd, &fds->sds); | ||
326 | |||
327 | if (desc->fd + 1 > fds->nsds) | ||
328 | fds->nsds = desc->fd + 1; | ||
329 | } | ||
330 | |||
331 | int | ||
332 | GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds, | ||
333 | const struct GNUNET_NETWORK_Descriptor *desc) | ||
334 | { | ||
335 | return FD_ISSET (desc->fd, &fds->sds); | ||
336 | } | ||
337 | |||
338 | void | ||
339 | GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst, | ||
340 | const struct GNUNET_NETWORK_FDSet *src) | ||
341 | { | ||
342 | int nfds; | ||
343 | |||
344 | for (nfds = src->nsds; nfds > 0; nfds--) | ||
345 | if (FD_ISSET (nfds, &src->sds)) | ||
346 | { | ||
347 | FD_SET (nfds, &dst->sds); | ||
348 | if (nfds + 1 > dst->nsds) | ||
349 | dst->nsds = nfds + 1; | ||
350 | } | ||
351 | } | ||
352 | |||
353 | void | ||
354 | GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, | ||
355 | const struct GNUNET_NETWORK_FDSet *from) | ||
356 | { | ||
357 | FD_COPY (&from->sds, &to->sds); | ||
358 | to->nsds = from->nsds; | ||
359 | #ifdef MINGW | ||
360 | void *obj; | ||
361 | |||
362 | if (to->handles) | ||
363 | GNUNET_CONTAINER_vector_destroy (to->handles); | ||
364 | to->handles = GNUNET_CONTAINER_vector_create (2); | ||
365 | for (obj = GNUNET_CONTAINER_vector_get_first (from->handles); obj != NULL; | ||
366 | obj = GNUNET_CONTAINER_vector_get_next (from->handles)) | ||
367 | { | ||
368 | GNUNET_CONTAINER_vector_insert_last (to->handles, obj); | ||
369 | } | ||
370 | #endif | ||
371 | } | ||
372 | |||
373 | void | ||
374 | GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to, | ||
375 | const fd_set * from, int nfds) | ||
376 | { | ||
377 | FD_COPY (from, &to->sds); | ||
378 | to->nsds = nfds; | ||
379 | } | ||
380 | |||
381 | void | ||
382 | GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds, | ||
383 | const struct GNUNET_DISK_FileHandle *h) | ||
384 | { | ||
385 | #ifdef MINGW | ||
386 | HANDLE hw; | ||
387 | |||
388 | GNUNET_internal_disk_file_handle (h, &hw, sizeof (HANDLE)); | ||
389 | GNUNET_CONTAINER_vector_insert_last (fds->handles, h); | ||
390 | #else | ||
391 | int fd; | ||
392 | |||
393 | GNUNET_internal_disk_file_handle (h, &fd, sizeof (int)); | ||
394 | FD_SET (fd, &fds->sds); | ||
395 | if (fd + 1 > fds->nsds) | ||
396 | fds->nsds = fd + 1; | ||
397 | #endif | ||
398 | } | ||
399 | |||
400 | int | ||
401 | GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds, | ||
402 | const struct GNUNET_DISK_FileHandle *h) | ||
403 | { | ||
404 | #ifdef MINGW | ||
405 | return GNUNET_CONTAINER_vector_index_of (fds->handles, h->h) != | ||
406 | (unsigned int) -1; | ||
407 | #else | ||
408 | return FD_ISSET (h->fd, &fds->sds); | ||
409 | #endif | ||
410 | } | ||
411 | |||
412 | int | ||
413 | GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1, | ||
414 | const struct GNUNET_NETWORK_FDSet *fds2) | ||
415 | { | ||
416 | int nfds; | ||
417 | |||
418 | nfds = fds1->nsds; | ||
419 | if (nfds < fds2->nsds) | ||
420 | nfds = fds2->nsds; | ||
421 | |||
422 | for (; nfds >= 0; nfds--) | ||
423 | if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds)) | ||
424 | return GNUNET_YES; | ||
425 | |||
426 | return GNUNET_NO; | ||
427 | } | ||
428 | |||
429 | struct GNUNET_NETWORK_FDSet * | ||
430 | GNUNET_NETWORK_fdset_create () | ||
431 | { | ||
432 | struct GNUNET_NETWORK_FDSet *fds; | ||
433 | |||
434 | fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet)); | ||
435 | #ifdef MINGW | ||
436 | fds->handles = NULL; | ||
437 | #endif | ||
438 | GNUNET_NETWORK_fdset_zero (fds); | ||
439 | |||
440 | return fds; | ||
441 | } | ||
442 | |||
443 | void | ||
444 | GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds) | ||
445 | { | ||
446 | #ifdef MINGW | ||
447 | GNUNET_CONTAINER_vector_destroy (fds->handles); | ||
448 | #endif | ||
449 | GNUNET_free (fds); | ||
450 | } | ||
451 | |||
452 | int | ||
453 | GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, | ||
454 | struct GNUNET_NETWORK_FDSet *wfds, | ||
455 | struct GNUNET_NETWORK_FDSet *efds, | ||
456 | const struct GNUNET_TIME_Relative timeout) | ||
457 | { | ||
458 | int nfds; | ||
459 | |||
460 | nfds = 0; | ||
461 | |||
462 | if (rfds) | ||
463 | nfds = rfds->nsds; | ||
464 | if (wfds && wfds->nsds > nfds) | ||
465 | nfds = wfds->nsds; | ||
466 | if (efds && efds->nsds > nfds) | ||
467 | nfds = efds->nsds; | ||
468 | |||
469 | #ifndef MINGW | ||
470 | struct timeval tv; | ||
471 | |||
472 | tv.tv_sec = timeout.value / GNUNET_TIME_UNIT_SECONDS.value; | ||
473 | tv.tv_usec = (timeout.value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.value)) | ||
474 | / GNUNET_TIME_UNIT_MILLISECONDS.value; | ||
475 | |||
476 | return select (nfds + 1, rfds ? &rfds->sds : NULL, wfds ? &wfds->sds : NULL, | ||
477 | efds ? &efds->sds : NULL, timeout.value | ||
478 | == GNUNET_TIME_UNIT_FOREVER_REL.value ? NULL : &tv); | ||
479 | #else | ||
480 | DWORD limit; | ||
481 | fd_set sock_read, sock_write, sock_except; | ||
482 | fd_set aread, awrite, aexcept; | ||
483 | int i; | ||
484 | struct timeval tvslice; | ||
485 | int retcode; | ||
486 | DWORD ms_total; | ||
487 | |||
488 | #define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set)) | ||
489 | |||
490 | /* calculate how long we need to wait in milliseconds */ | ||
491 | if (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value) | ||
492 | ms_total = INFINITE; | ||
493 | else | ||
494 | ms_total = timeout.value / GNUNET_TIME_UNIT_MILLISECONDS.value; | ||
495 | |||
496 | /* select() may be used as a portable way to sleep */ | ||
497 | if (!(rfds || wfds || efds)) | ||
498 | { | ||
499 | Sleep (ms_total); | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | if (rfds) | ||
505 | sock_read = rfds->sds; | ||
506 | else | ||
507 | FD_ZERO(&sock_read); | ||
508 | |||
509 | if (wfds) | ||
510 | sock_write = wfds->sds; | ||
511 | else | ||
512 | FD_ZERO(&sock_write); | ||
513 | |||
514 | if (efds) | ||
515 | sock_except = efds->sds; | ||
516 | else | ||
517 | FD_ZERO(&sock_except); | ||
518 | |||
519 | /* | ||
520 | if (rfds) | ||
521 | FD_COPY (&rfds->sds, &sock_read); | ||
522 | else | ||
523 | FD_ZERO(&sock_read); | ||
524 | |||
525 | if (wfds) | ||
526 | FD_COPY (&wfds->sds, &sock_write); | ||
527 | else | ||
528 | FD_ZERO(&sock_write); | ||
529 | |||
530 | if (efds) | ||
531 | FD_COPY (&efds->sds, &sock_except); | ||
532 | else | ||
533 | FD_ZERO(&sock_except); | ||
534 | */ | ||
535 | |||
536 | /* multiplex between winsock select() and waiting on the handles */ | ||
537 | |||
538 | FD_ZERO (&aread); | ||
539 | FD_ZERO (&awrite); | ||
540 | FD_ZERO (&aexcept); | ||
541 | |||
542 | limit = GetTickCount () + ms_total; | ||
543 | do | ||
544 | { | ||
545 | retcode = 0; | ||
546 | |||
547 | if (nfds > 0) | ||
548 | { | ||
549 | /* overwrite the zero'd sets here; the select call | ||
550 | * will clear those that are not active */ | ||
551 | |||
552 | FD_COPY (&sock_read, &aread); | ||
553 | FD_COPY (&sock_write, &awrite); | ||
554 | FD_COPY (&sock_except, &aexcept); | ||
555 | |||
556 | tvslice.tv_sec = 0; | ||
557 | tvslice.tv_usec = 100000; | ||
558 | |||
559 | if ((retcode = | ||
560 | select (nfds + 1, &aread, &awrite, &aexcept, | ||
561 | &tvslice)) == SOCKET_ERROR) | ||
562 | { | ||
563 | SetErrnoFromWinsockError (WSAGetLastError ()); | ||
564 | if (errno == ENOTSOCK) | ||
565 | errno = EBADF; | ||
566 | |||
567 | #if DEBUG_SOCK | ||
568 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select"); | ||
569 | #endif | ||
570 | |||
571 | goto select_loop_end; | ||
572 | } | ||
573 | } | ||
574 | |||
575 | /* Poll read pipes */ | ||
576 | if (rfds) | ||
577 | for (i = GNUNET_CONTAINER_vector_size (rfds->handles) - 1; i >= 0; i--) | ||
578 | { | ||
579 | DWORD dwBytes; | ||
580 | |||
581 | if (!PeekNamedPipe | ||
582 | (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0, | ||
583 | NULL, &dwBytes, NULL)) | ||
584 | { | ||
585 | GNUNET_CONTAINER_vector_remove_at (rfds->handles, i); | ||
586 | |||
587 | retcode = -1; | ||
588 | SetErrnoFromWinError (GetLastError ()); | ||
589 | #if DEBUG_SOCK | ||
590 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "PeekNamedPipe"); | ||
591 | #endif | ||
592 | goto select_loop_end; | ||
593 | } | ||
594 | else if (dwBytes) | ||
595 | { | ||
596 | retcode++; | ||
597 | } | ||
598 | else | ||
599 | GNUNET_CONTAINER_vector_remove_at (rfds->handles, i); | ||
600 | } | ||
601 | |||
602 | /* Poll for faulty pipes */ | ||
603 | if (efds) | ||
604 | for (i = GNUNET_CONTAINER_vector_size (efds->handles); i >= 0; i--) | ||
605 | { | ||
606 | DWORD dwBytes; | ||
607 | |||
608 | if (PeekNamedPipe | ||
609 | (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0, | ||
610 | NULL, &dwBytes, NULL)) | ||
611 | { | ||
612 | GNUNET_CONTAINER_vector_remove_at (efds->handles, i); | ||
613 | |||
614 | retcode++; | ||
615 | } | ||
616 | } | ||
617 | |||
618 | /* FIXME */ | ||
619 | if (wfds) | ||
620 | GNUNET_assert (GNUNET_CONTAINER_vector_size (wfds->handles) == 0); | ||
621 | |||
622 | /* Check for closed sockets */ | ||
623 | for (i = 0; i < nfds; i++) | ||
624 | { | ||
625 | if (SAFE_FD_ISSET (i, &sock_read)) | ||
626 | { | ||
627 | struct sockaddr addr; | ||
628 | int len; | ||
629 | |||
630 | if (getpeername (i, &addr, &len) == SOCKET_ERROR) | ||
631 | { | ||
632 | int err, len; | ||
633 | |||
634 | len = sizeof (err); | ||
635 | if (getsockopt | ||
636 | (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0 | ||
637 | && err == WSAENOTCONN) | ||
638 | { | ||
639 | if (!SAFE_FD_ISSET (i, &aread)) | ||
640 | { | ||
641 | FD_SET (i, &aread); | ||
642 | retcode++; | ||
643 | } | ||
644 | } | ||
645 | } | ||
646 | } | ||
647 | } | ||
648 | |||
649 | select_loop_end:; | ||
650 | } | ||
651 | while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit)); | ||
652 | |||
653 | if (retcode != -1) | ||
654 | { | ||
655 | if (rfds) | ||
656 | { | ||
657 | GNUNET_NETWORK_fdset_zero (rfds); | ||
658 | GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode); | ||
659 | } | ||
660 | |||
661 | if (wfds) | ||
662 | { | ||
663 | GNUNET_NETWORK_fdset_zero (wfds); | ||
664 | GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode); | ||
665 | } | ||
666 | |||
667 | if (efds) | ||
668 | { | ||
669 | GNUNET_NETWORK_fdset_zero (efds); | ||
670 | GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode); | ||
671 | } | ||
672 | } | ||
673 | |||
674 | return retcode; | ||
675 | #endif | ||
676 | } | ||
677 | |||
678 | /* end of sock.c */ | ||