diff options
author | Christian Grothoff <christian@grothoff.org> | 2009-11-08 21:29:03 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2009-11-08 21:29:03 +0000 |
commit | bb82fb7f4ea781b843f032c6869f98e6fa6fa107 (patch) | |
tree | cd3adfb5b3cffae4c0929a9b841684d6e524f727 /src/util | |
parent | 505a1289db1a7556d71324b87abe10aec0cfe7f5 (diff) | |
download | gnunet-bb82fb7f4ea781b843f032c6869f98e6fa6fa107.tar.gz gnunet-bb82fb7f4ea781b843f032c6869f98e6fa6fa107.zip |
formatting
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/network.c | 1885 |
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 | 37 | struct GNUNET_NETWORK_Handle |
38 | { | 38 | { |
39 | int fd; | 39 | int fd; |
40 | }; | 40 | }; |
41 | struct GNUNET_NETWORK_FDSet | 41 | struct 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 | */ |
65 | static int | 65 | static int |
66 | socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock) | 66 | socket_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 | */ |
115 | static int | 115 | static int |
116 | socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h) | 116 | socket_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 | */ |
135 | static void | 135 | static void |
136 | socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h) | 136 | socket_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 | */ |
154 | static void | 154 | static void |
155 | socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h) | 155 | socket_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 | */ |
172 | struct GNUNET_NETWORK_Handle * | 172 | struct GNUNET_NETWORK_Handle * |
173 | GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc, | 173 | GNUNET_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 | */ |
235 | int | 235 | int |
236 | GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc, | 236 | GNUNET_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 | */ |
257 | int | 257 | int |
258 | GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc) | 258 | GNUNET_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 | */ |
285 | int | 285 | int |
286 | GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc, | 286 | GNUNET_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 | */ |
317 | int | 317 | int |
318 | GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc, | 318 | GNUNET_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 | */ |
343 | int | 343 | int |
344 | GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc, | 344 | GNUNET_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 | 365 | ssize_t |
366 | GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc, | 366 | GNUNET_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 | 396 | ssize_t |
397 | GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc, | 397 | GNUNET_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 | 434 | ssize_t |
435 | GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc, | 435 | GNUNET_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 | */ |
472 | int | 472 | int |
473 | GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, | 473 | GNUNET_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 | */ |
500 | struct GNUNET_NETWORK_Handle * | 500 | struct GNUNET_NETWORK_Handle * |
501 | GNUNET_NETWORK_socket_create (int domain, int type, int protocol) | 501 | GNUNET_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 | */ |
561 | int | 561 | int |
562 | GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, | 562 | GNUNET_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 | */ |
581 | void | 580 | void |
582 | GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds) | 581 | GNUNET_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 | */ |
598 | void | 597 | void |
599 | GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds, | 598 | GNUNET_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 | */ |
614 | int | 613 | int |
615 | GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds, | 614 | GNUNET_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 | */ |
627 | void | 626 | void |
628 | GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst, | 627 | GNUNET_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 | */ |
648 | void | 647 | void |
649 | GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, | 648 | GNUNET_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 | */ |
679 | void | 678 | void |
680 | GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to, | 679 | GNUNET_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 | */ |
692 | void | 691 | void |
693 | GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds, | 692 | GNUNET_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 | */ |
719 | int | 718 | int |
720 | GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds, | 719 | GNUNET_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 | */ |
741 | int | 740 | int |
742 | GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1, | 741 | GNUNET_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 | */ |
760 | struct GNUNET_NETWORK_FDSet * | 759 | struct GNUNET_NETWORK_FDSet * |
761 | GNUNET_NETWORK_fdset_create () | 760 | GNUNET_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 | */ |
779 | void | 778 | void |
780 | GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds) | 779 | GNUNET_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 | */ |
798 | int | 797 | int |
799 | GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, | 798 | GNUNET_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 */ |