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