diff options
Diffstat (limited to 'src/usocket.c')
-rw-r--r-- | src/usocket.c | 98 |
1 files changed, 49 insertions, 49 deletions
diff --git a/src/usocket.c b/src/usocket.c index 89f774d..99e551b 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
@@ -4,12 +4,13 @@ | |||
4 | * | 4 | * |
5 | * The code is now interrupt-safe. | 5 | * The code is now interrupt-safe. |
6 | * The penalty of calling select to avoid busy-wait is only paid when | 6 | * The penalty of calling select to avoid busy-wait is only paid when |
7 | * the I/O call fail in the first place. | 7 | * the I/O call fail in the first place. |
8 | \*=========================================================================*/ | 8 | \*=========================================================================*/ |
9 | #include <string.h> | 9 | #include <string.h> |
10 | #include <signal.h> | 10 | #include <signal.h> |
11 | 11 | ||
12 | #include "socket.h" | 12 | #include "socket.h" |
13 | #include "pierror.h" | ||
13 | 14 | ||
14 | /*-------------------------------------------------------------------------*\ | 15 | /*-------------------------------------------------------------------------*\ |
15 | * Wait for readable/writable/connected socket with timeout | 16 | * Wait for readable/writable/connected socket with timeout |
@@ -72,7 +73,7 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | |||
72 | 73 | ||
73 | 74 | ||
74 | /*-------------------------------------------------------------------------*\ | 75 | /*-------------------------------------------------------------------------*\ |
75 | * Initializes module | 76 | * Initializes module |
76 | \*-------------------------------------------------------------------------*/ | 77 | \*-------------------------------------------------------------------------*/ |
77 | int socket_open(void) { | 78 | int socket_open(void) { |
78 | /* instals a handler to ignore sigpipe or it will crash us */ | 79 | /* instals a handler to ignore sigpipe or it will crash us */ |
@@ -81,7 +82,7 @@ int socket_open(void) { | |||
81 | } | 82 | } |
82 | 83 | ||
83 | /*-------------------------------------------------------------------------*\ | 84 | /*-------------------------------------------------------------------------*\ |
84 | * Close module | 85 | * Close module |
85 | \*-------------------------------------------------------------------------*/ | 86 | \*-------------------------------------------------------------------------*/ |
86 | int socket_close(void) { | 87 | int socket_close(void) { |
87 | return 1; | 88 | return 1; |
@@ -100,7 +101,7 @@ void socket_destroy(p_socket ps) { | |||
100 | /*-------------------------------------------------------------------------*\ | 101 | /*-------------------------------------------------------------------------*\ |
101 | * Select with timeout control | 102 | * Select with timeout control |
102 | \*-------------------------------------------------------------------------*/ | 103 | \*-------------------------------------------------------------------------*/ |
103 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | 104 | int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, |
104 | p_timeout tm) { | 105 | p_timeout tm) { |
105 | int ret; | 106 | int ret; |
106 | do { | 107 | do { |
@@ -119,8 +120,8 @@ int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, | |||
119 | \*-------------------------------------------------------------------------*/ | 120 | \*-------------------------------------------------------------------------*/ |
120 | int socket_create(p_socket ps, int domain, int type, int protocol) { | 121 | int socket_create(p_socket ps, int domain, int type, int protocol) { |
121 | *ps = socket(domain, type, protocol); | 122 | *ps = socket(domain, type, protocol); |
122 | if (*ps != SOCKET_INVALID) return IO_DONE; | 123 | if (*ps != SOCKET_INVALID) return IO_DONE; |
123 | else return errno; | 124 | else return errno; |
124 | } | 125 | } |
125 | 126 | ||
126 | /*-------------------------------------------------------------------------*\ | 127 | /*-------------------------------------------------------------------------*\ |
@@ -129,22 +130,22 @@ int socket_create(p_socket ps, int domain, int type, int protocol) { | |||
129 | int socket_bind(p_socket ps, SA *addr, socklen_t len) { | 130 | int socket_bind(p_socket ps, SA *addr, socklen_t len) { |
130 | int err = IO_DONE; | 131 | int err = IO_DONE; |
131 | socket_setblocking(ps); | 132 | socket_setblocking(ps); |
132 | if (bind(*ps, addr, len) < 0) err = errno; | 133 | if (bind(*ps, addr, len) < 0) err = errno; |
133 | socket_setnonblocking(ps); | 134 | socket_setnonblocking(ps); |
134 | return err; | 135 | return err; |
135 | } | 136 | } |
136 | 137 | ||
137 | /*-------------------------------------------------------------------------*\ | 138 | /*-------------------------------------------------------------------------*\ |
138 | * | 139 | * |
139 | \*-------------------------------------------------------------------------*/ | 140 | \*-------------------------------------------------------------------------*/ |
140 | int socket_listen(p_socket ps, int backlog) { | 141 | int socket_listen(p_socket ps, int backlog) { |
141 | int err = IO_DONE; | 142 | int err = IO_DONE; |
142 | if (listen(*ps, backlog)) err = errno; | 143 | if (listen(*ps, backlog)) err = errno; |
143 | return err; | 144 | return err; |
144 | } | 145 | } |
145 | 146 | ||
146 | /*-------------------------------------------------------------------------*\ | 147 | /*-------------------------------------------------------------------------*\ |
147 | * | 148 | * |
148 | \*-------------------------------------------------------------------------*/ | 149 | \*-------------------------------------------------------------------------*/ |
149 | void socket_shutdown(p_socket ps, int how) { | 150 | void socket_shutdown(p_socket ps, int how) { |
150 | shutdown(*ps, how); | 151 | shutdown(*ps, how); |
@@ -161,7 +162,7 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { | |||
161 | do if (connect(*ps, addr, len) == 0) return IO_DONE; | 162 | do if (connect(*ps, addr, len) == 0) return IO_DONE; |
162 | while ((err = errno) == EINTR); | 163 | while ((err = errno) == EINTR); |
163 | /* if connection failed immediately, return error code */ | 164 | /* if connection failed immediately, return error code */ |
164 | if (err != EINPROGRESS && err != EAGAIN) return err; | 165 | if (err != EINPROGRESS && err != EAGAIN) return err; |
165 | /* zero timeout case optimization */ | 166 | /* zero timeout case optimization */ |
166 | if (timeout_iszero(tm)) return IO_TIMEOUT; | 167 | if (timeout_iszero(tm)) return IO_TIMEOUT; |
167 | /* wait until we have the result of the connection attempt or timeout */ | 168 | /* wait until we have the result of the connection attempt or timeout */ |
@@ -176,7 +177,7 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) { | |||
176 | * Accept with timeout | 177 | * Accept with timeout |
177 | \*-------------------------------------------------------------------------*/ | 178 | \*-------------------------------------------------------------------------*/ |
178 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) { | 179 | int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) { |
179 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | 180 | if (*ps == SOCKET_INVALID) return IO_CLOSED; |
180 | for ( ;; ) { | 181 | for ( ;; ) { |
181 | int err; | 182 | int err; |
182 | if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; | 183 | if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE; |
@@ -192,7 +193,7 @@ int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout | |||
192 | /*-------------------------------------------------------------------------*\ | 193 | /*-------------------------------------------------------------------------*\ |
193 | * Send with timeout | 194 | * Send with timeout |
194 | \*-------------------------------------------------------------------------*/ | 195 | \*-------------------------------------------------------------------------*/ |
195 | int socket_send(p_socket ps, const char *data, size_t count, | 196 | int socket_send(p_socket ps, const char *data, size_t count, |
196 | size_t *sent, p_timeout tm) | 197 | size_t *sent, p_timeout tm) |
197 | { | 198 | { |
198 | int err; | 199 | int err; |
@@ -224,14 +225,14 @@ int socket_send(p_socket ps, const char *data, size_t count, | |||
224 | /*-------------------------------------------------------------------------*\ | 225 | /*-------------------------------------------------------------------------*\ |
225 | * Sendto with timeout | 226 | * Sendto with timeout |
226 | \*-------------------------------------------------------------------------*/ | 227 | \*-------------------------------------------------------------------------*/ |
227 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | 228 | int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, |
228 | SA *addr, socklen_t len, p_timeout tm) | 229 | SA *addr, socklen_t len, p_timeout tm) |
229 | { | 230 | { |
230 | int err; | 231 | int err; |
231 | *sent = 0; | 232 | *sent = 0; |
232 | if (*ps == SOCKET_INVALID) return IO_CLOSED; | 233 | if (*ps == SOCKET_INVALID) return IO_CLOSED; |
233 | for ( ;; ) { | 234 | for ( ;; ) { |
234 | long put = (long) sendto(*ps, data, count, 0, addr, len); | 235 | long put = (long) sendto(*ps, data, count, 0, addr, len); |
235 | if (put >= 0) { | 236 | if (put >= 0) { |
236 | *sent = put; | 237 | *sent = put; |
237 | return IO_DONE; | 238 | return IO_DONE; |
@@ -261,8 +262,8 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm | |||
261 | err = errno; | 262 | err = errno; |
262 | if (taken == 0) return IO_CLOSED; | 263 | if (taken == 0) return IO_CLOSED; |
263 | if (err == EINTR) continue; | 264 | if (err == EINTR) continue; |
264 | if (err != EAGAIN) return err; | 265 | if (err != EAGAIN) return err; |
265 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | 266 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; |
266 | } | 267 | } |
267 | return IO_UNKNOWN; | 268 | return IO_UNKNOWN; |
268 | } | 269 | } |
@@ -270,7 +271,7 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm | |||
270 | /*-------------------------------------------------------------------------*\ | 271 | /*-------------------------------------------------------------------------*\ |
271 | * Recvfrom with timeout | 272 | * Recvfrom with timeout |
272 | \*-------------------------------------------------------------------------*/ | 273 | \*-------------------------------------------------------------------------*/ |
273 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | 274 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, |
274 | SA *addr, socklen_t *len, p_timeout tm) { | 275 | SA *addr, socklen_t *len, p_timeout tm) { |
275 | int err; | 276 | int err; |
276 | *got = 0; | 277 | *got = 0; |
@@ -284,8 +285,8 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | |||
284 | err = errno; | 285 | err = errno; |
285 | if (taken == 0) return IO_CLOSED; | 286 | if (taken == 0) return IO_CLOSED; |
286 | if (err == EINTR) continue; | 287 | if (err == EINTR) continue; |
287 | if (err != EAGAIN) return err; | 288 | if (err != EAGAIN) return err; |
288 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | 289 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; |
289 | } | 290 | } |
290 | return IO_UNKNOWN; | 291 | return IO_UNKNOWN; |
291 | } | 292 | } |
@@ -298,7 +299,7 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | |||
298 | * with send/recv replaced with write/read. We can't just use write/read | 299 | * with send/recv replaced with write/read. We can't just use write/read |
299 | * in the socket version, because behaviour when size is zero is different. | 300 | * in the socket version, because behaviour when size is zero is different. |
300 | \*-------------------------------------------------------------------------*/ | 301 | \*-------------------------------------------------------------------------*/ |
301 | int socket_write(p_socket ps, const char *data, size_t count, | 302 | int socket_write(p_socket ps, const char *data, size_t count, |
302 | size_t *sent, p_timeout tm) | 303 | size_t *sent, p_timeout tm) |
303 | { | 304 | { |
304 | int err; | 305 | int err; |
@@ -344,8 +345,8 @@ int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm | |||
344 | err = errno; | 345 | err = errno; |
345 | if (taken == 0) return IO_CLOSED; | 346 | if (taken == 0) return IO_CLOSED; |
346 | if (err == EINTR) continue; | 347 | if (err == EINTR) continue; |
347 | if (err != EAGAIN) return err; | 348 | if (err != EAGAIN) return err; |
348 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; | 349 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; |
349 | } | 350 | } |
350 | return IO_UNKNOWN; | 351 | return IO_UNKNOWN; |
351 | } | 352 | } |
@@ -369,7 +370,7 @@ void socket_setnonblocking(p_socket ps) { | |||
369 | } | 370 | } |
370 | 371 | ||
371 | /*-------------------------------------------------------------------------*\ | 372 | /*-------------------------------------------------------------------------*\ |
372 | * DNS helpers | 373 | * DNS helpers |
373 | \*-------------------------------------------------------------------------*/ | 374 | \*-------------------------------------------------------------------------*/ |
374 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { | 375 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) { |
375 | *hp = gethostbyaddr(addr, len, AF_INET); | 376 | *hp = gethostbyaddr(addr, len, AF_INET); |
@@ -394,7 +395,7 @@ int socket_gethostbyname(const char *addr, struct hostent **hp) { | |||
394 | const char *socket_hoststrerror(int err) { | 395 | const char *socket_hoststrerror(int err) { |
395 | if (err <= 0) return io_strerror(err); | 396 | if (err <= 0) return io_strerror(err); |
396 | switch (err) { | 397 | switch (err) { |
397 | case HOST_NOT_FOUND: return "host not found"; | 398 | case HOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; |
398 | default: return hstrerror(err); | 399 | default: return hstrerror(err); |
399 | } | 400 | } |
400 | } | 401 | } |
@@ -402,13 +403,13 @@ const char *socket_hoststrerror(int err) { | |||
402 | const char *socket_strerror(int err) { | 403 | const char *socket_strerror(int err) { |
403 | if (err <= 0) return io_strerror(err); | 404 | if (err <= 0) return io_strerror(err); |
404 | switch (err) { | 405 | switch (err) { |
405 | case EADDRINUSE: return "address already in use"; | 406 | case EADDRINUSE: return PIE_ADDRINUSE; |
406 | case EISCONN: return "already connected"; | 407 | case EISCONN: return PIE_ISCONN; |
407 | case EACCES: return "permission denied"; | 408 | case EACCES: return PIE_ACCESS; |
408 | case ECONNREFUSED: return "connection refused"; | 409 | case ECONNREFUSED: return PIE_CONNREFUSED; |
409 | case ECONNABORTED: return "closed"; | 410 | case ECONNABORTED: return PIE_CONNABORTED; |
410 | case ECONNRESET: return "closed"; | 411 | case ECONNRESET: return PIE_CONNRESET; |
411 | case ETIMEDOUT: return "timeout"; | 412 | case ETIMEDOUT: return PIE_TIMEDOUT; |
412 | default: return strerror(err); | 413 | default: return strerror(err); |
413 | } | 414 | } |
414 | } | 415 | } |
@@ -416,28 +417,27 @@ const char *socket_strerror(int err) { | |||
416 | const char *socket_ioerror(p_socket ps, int err) { | 417 | const char *socket_ioerror(p_socket ps, int err) { |
417 | (void) ps; | 418 | (void) ps; |
418 | return socket_strerror(err); | 419 | return socket_strerror(err); |
419 | } | 420 | } |
420 | 421 | ||
421 | const char *socket_gaistrerror(int err) { | 422 | const char *socket_gaistrerror(int err) { |
422 | if (err == 0) return NULL; | 423 | if (err == 0) return NULL; |
423 | switch (err) { | 424 | switch (err) { |
424 | case EAI_AGAIN: return "temporary failure in name resolution"; | 425 | case EAI_AGAIN: return PIE_AGAIN; |
425 | case EAI_BADFLAGS: return "invalid value for ai_flags"; | 426 | case EAI_BADFLAGS: return PIE_BADFLAGS; |
426 | #ifdef EAI_BADHINTS | 427 | #ifdef EAI_BADHINTS |
427 | case EAI_BADHINTS: return "invalid value for hints"; | 428 | case EAI_BADHINTS: return PIE_BADHINTS; |
428 | #endif | 429 | #endif |
429 | case EAI_FAIL: return "non-recoverable failure in name resolution"; | 430 | case EAI_FAIL: return PIE_FAIL; |
430 | case EAI_FAMILY: return "ai_family not supported"; | 431 | case EAI_FAMILY: return PIE_FAMILY; |
431 | case EAI_MEMORY: return "memory allocation failure"; | 432 | case EAI_MEMORY: return PIE_MEMORY; |
432 | case EAI_NONAME: | 433 | case EAI_NONAME: return PIE_NONAME; |
433 | return "host or service not provided, or not known"; | 434 | case EAI_OVERFLOW: return PIE_OVERFLOW; |
434 | case EAI_OVERFLOW: return "argument buffer overflow"; | ||
435 | #ifdef EAI_PROTOCOL | 435 | #ifdef EAI_PROTOCOL |
436 | case EAI_PROTOCOL: return "resolved protocol is unknown"; | 436 | case EAI_PROTOCOL: return PIE_PROTOCOL; |
437 | #endif | 437 | #endif |
438 | case EAI_SERVICE: return "service not supported for socket type"; | 438 | case EAI_SERVICE: return PIE_SERVICE; |
439 | case EAI_SOCKTYPE: return "ai_socktype not supported"; | 439 | case EAI_SOCKTYPE: return PIE_SOCKTYPE; |
440 | case EAI_SYSTEM: return strerror(errno); | 440 | case EAI_SYSTEM: return strerror(errno); |
441 | default: return gai_strerror(err); | 441 | default: return gai_strerror(err); |
442 | } | 442 | } |
443 | } | 443 | } |