aboutsummaryrefslogtreecommitdiff
path: root/src/usocket.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usocket.c')
-rw-r--r--src/usocket.c334
1 files changed, 123 insertions, 211 deletions
diff --git a/src/usocket.c b/src/usocket.c
index cf0458d..12a13a5 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -20,17 +20,10 @@
20 20
21#include "socket.h" 21#include "socket.h"
22 22
23static const char *sock_createstrerror(int err);
24static const char *sock_bindstrerror(int err);
25static const char *sock_connectstrerror(int err);
26static const char *sock_acceptstrerror(int err);
27static const char *sock_listenstrerror(int err);
28
29/*-------------------------------------------------------------------------*\ 23/*-------------------------------------------------------------------------*\
30* Initializes module 24* Initializes module
31\*-------------------------------------------------------------------------*/ 25\*-------------------------------------------------------------------------*/
32int sock_open(void) 26int sock_open(void) {
33{
34#if DOESNT_COMPILE_TRY_THIS 27#if DOESNT_COMPILE_TRY_THIS
35 struct sigaction ignore; 28 struct sigaction ignore;
36 memset(&ignore, 0, sizeof(ignore)); 29 memset(&ignore, 0, sizeof(ignore));
@@ -45,16 +38,14 @@ int sock_open(void)
45/*-------------------------------------------------------------------------*\ 38/*-------------------------------------------------------------------------*\
46* Close module 39* Close module
47\*-------------------------------------------------------------------------*/ 40\*-------------------------------------------------------------------------*/
48int sock_close(void) 41int sock_close(void) {
49{
50 return 1; 42 return 1;
51} 43}
52 44
53/*-------------------------------------------------------------------------*\ 45/*-------------------------------------------------------------------------*\
54* Close and inutilize socket 46* Close and inutilize socket
55\*-------------------------------------------------------------------------*/ 47\*-------------------------------------------------------------------------*/
56void sock_destroy(p_sock ps) 48void sock_destroy(p_sock ps) {
57{
58 if (*ps != SOCK_INVALID) { 49 if (*ps != SOCK_INVALID) {
59 sock_setblocking(ps); 50 sock_setblocking(ps);
60 close(*ps); 51 close(*ps);
@@ -63,23 +54,26 @@ void sock_destroy(p_sock ps)
63} 54}
64 55
65/*-------------------------------------------------------------------------*\ 56/*-------------------------------------------------------------------------*\
66* Select with int timeout in ms 57* Select with timeout control
67\*-------------------------------------------------------------------------*/ 58\*-------------------------------------------------------------------------*/
68int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, int timeout) 59int sock_select(int n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_tm tm) {
69{ 60 int ret;
70 struct timeval tv; 61 do {
71 tv.tv_sec = timeout / 1000; 62 struct timeval tv;
72 tv.tv_usec = (timeout % 1000) * 1000; 63 double t = tm_getretry(tm);
73 return select(n, rfds, wfds, efds, timeout >= 0? &tv: NULL); 64 tv.tv_sec = (int) t;
65 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
66 ret = select(n, rfds, wfds, efds, t >= 0.0? &tv: NULL);
67 } while (ret < 0 && errno == EINTR);
68 return ret;
74} 69}
75 70
76/*-------------------------------------------------------------------------*\ 71/*-------------------------------------------------------------------------*\
77* Creates and sets up a socket 72* Creates and sets up a socket
78\*-------------------------------------------------------------------------*/ 73\*-------------------------------------------------------------------------*/
79const char *sock_create(p_sock ps, int domain, int type, int protocol) 74const char *sock_create(p_sock ps, int domain, int type, int protocol) {
80{
81 t_sock sock = socket(domain, type, protocol); 75 t_sock sock = socket(domain, type, protocol);
82 if (sock == SOCK_INVALID) return sock_createstrerror(errno); 76 if (sock == SOCK_INVALID) return sock_strerror();
83 *ps = sock; 77 *ps = sock;
84 return NULL; 78 return NULL;
85} 79}
@@ -87,50 +81,49 @@ const char *sock_create(p_sock ps, int domain, int type, int protocol)
87/*-------------------------------------------------------------------------*\ 81/*-------------------------------------------------------------------------*\
88* Connects or returns error message 82* Connects or returns error message
89\*-------------------------------------------------------------------------*/ 83\*-------------------------------------------------------------------------*/
90const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm) 84const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm) {
91{
92 t_sock sock = *ps; 85 t_sock sock = *ps;
93 int err; 86 int err;
94 /* don't call on closed socket */ 87 /* don't call on closed socket */
95 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED); 88 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED);
96 /* ask system to connect */ 89 /* ask system to connect */
97 do err = connect(sock, addr, addr_len); 90 do err = connect(sock, addr, addr_len);
98 while (err < 0 && errno == EINTR); 91 while (err < 0 && errno == EINTR);
99 /* if no error, we're done */ 92 /* if no error, we're done */
100 if (err == 0) return NULL; 93 if (err == 0) return NULL;
101 /* make sure the system is trying to connect */ 94 /* make sure the system is trying to connect */
102 if (errno != EINPROGRESS) return sock_connectstrerror(errno); 95 if (errno != EINPROGRESS) return sock_strerror();
96 /* optimize for timeout = 0 */
97 if (tm_get(tm) == 0.0) return io_strerror(IO_TIMEOUT);
103 /* wait for a timeout or for the system's answer */ 98 /* wait for a timeout or for the system's answer */
104 for ( ;; ) { 99 for ( ;; ) {
105 fd_set rfds, wfds, efds; 100 fd_set rfds, wfds;
106 FD_ZERO(&rfds); FD_SET(sock, &rfds); 101 FD_ZERO(&rfds); FD_SET(sock, &rfds);
107 FD_ZERO(&wfds); FD_SET(sock, &wfds); 102 FD_ZERO(&wfds); FD_SET(sock, &wfds);
108 FD_ZERO(&efds); FD_SET(sock, &efds);
109 /* we run select to avoid busy waiting */ 103 /* we run select to avoid busy waiting */
110 do err = sock_select(sock+1, &rfds, &wfds, &efds, tm_getretry(tm)); 104 err = sock_select(sock+1, &rfds, &wfds, NULL, tm);
111 while (err < 0 && errno == EINTR); 105 /* if there was an event, check what happened */
112 /* if selects readable, try reading */
113 if (err > 0) { 106 if (err > 0) {
114 char dummy; 107 char dummy;
115 /* recv will set errno to the value a blocking connect would set */ 108 /* recv will set errno to the value a blocking connect would set */
116 if (recv(sock, &dummy, 0, 0) < 0 && errno != EAGAIN) 109 if (err > 1 && FD_ISSET(sock, &rfds) &&
117 return sock_connectstrerror(errno); 110 recv(sock, &dummy, 0, 0) < 0 && errno != EAGAIN)
111 return sock_strerror();
118 else 112 else
119 return NULL; 113 return NULL;
120 /* if no event happened, there was a timeout */ 114 /* if no event happened, there was a timeout */
121 } else return io_strerror(IO_TIMEOUT); 115 } else if (err == 0) return io_strerror(IO_TIMEOUT);
122 } 116 }
123 return io_strerror(IO_TIMEOUT); /* can't get here */ 117 return sock_strerror();
124} 118}
125 119
126/*-------------------------------------------------------------------------*\ 120/*-------------------------------------------------------------------------*\
127* Binds or returns error message 121* Binds or returns error message
128\*-------------------------------------------------------------------------*/ 122\*-------------------------------------------------------------------------*/
129const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) 123const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) {
130{
131 const char *err = NULL; 124 const char *err = NULL;
132 sock_setblocking(ps); 125 sock_setblocking(ps);
133 if (bind(*ps, addr, addr_len) < 0) err = sock_bindstrerror(errno); 126 if (bind(*ps, addr, addr_len) < 0) err = sock_strerror();
134 sock_setnonblocking(ps); 127 sock_setnonblocking(ps);
135 return err; 128 return err;
136} 129}
@@ -138,12 +131,10 @@ const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
138/*-------------------------------------------------------------------------*\ 131/*-------------------------------------------------------------------------*\
139* 132*
140\*-------------------------------------------------------------------------*/ 133\*-------------------------------------------------------------------------*/
141const char* sock_listen(p_sock ps, int backlog) 134const char* sock_listen(p_sock ps, int backlog) {
142{
143 const char *err = NULL; 135 const char *err = NULL;
144 sock_setblocking(ps); 136 sock_setblocking(ps);
145 if (listen(*ps, backlog)) 137 if (listen(*ps, backlog)) err = sock_strerror();
146 err = sock_listenstrerror(errno);
147 sock_setnonblocking(ps); 138 sock_setnonblocking(ps);
148 return err; 139 return err;
149} 140}
@@ -151,8 +142,7 @@ const char* sock_listen(p_sock ps, int backlog)
151/*-------------------------------------------------------------------------*\ 142/*-------------------------------------------------------------------------*\
152* 143*
153\*-------------------------------------------------------------------------*/ 144\*-------------------------------------------------------------------------*/
154void sock_shutdown(p_sock ps, int how) 145void sock_shutdown(p_sock ps, int how) {
155{
156 sock_setblocking(ps); 146 sock_setblocking(ps);
157 shutdown(*ps, how); 147 shutdown(*ps, how);
158 sock_setnonblocking(ps); 148 sock_setnonblocking(ps);
@@ -162,12 +152,11 @@ void sock_shutdown(p_sock ps, int how)
162* Accept with timeout 152* Accept with timeout
163\*-------------------------------------------------------------------------*/ 153\*-------------------------------------------------------------------------*/
164const char *sock_accept(p_sock ps, p_sock pa, SA *addr, 154const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
165 socklen_t *addr_len, p_tm tm) 155 socklen_t *addr_len, p_tm tm) {
166{
167 t_sock sock = *ps; 156 t_sock sock = *ps;
168 SA dummy_addr; 157 SA dummy_addr;
169 socklen_t dummy_len = sizeof(dummy_addr); 158 socklen_t dummy_len = sizeof(dummy_addr);
170 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED); 159 if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED);
171 if (!addr) addr = &dummy_addr; 160 if (!addr) addr = &dummy_addr;
172 if (!addr_len) addr_len = &dummy_len; 161 if (!addr_len) addr_len = &dummy_len;
173 for (;;) { 162 for (;;) {
@@ -179,14 +168,16 @@ const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
179 /* if result is valid, we are done */ 168 /* if result is valid, we are done */
180 if (*pa != SOCK_INVALID) return NULL; 169 if (*pa != SOCK_INVALID) return NULL;
181 /* find out if we failed for a fatal reason */ 170 /* find out if we failed for a fatal reason */
182 if (errno != EAGAIN && errno != ECONNABORTED) 171 /* if connection was aborted, we can try again if we have time */
183 return sock_acceptstrerror(errno); 172 if (errno != EAGAIN && errno != ECONNABORTED) return sock_strerror();
173 /* optimize for timeout = 0 case */
174 if (tm_get(tm) == 0.0) return io_strerror(IO_TIMEOUT);
184 /* call select to avoid busy-wait. */ 175 /* call select to avoid busy-wait. */
185 FD_ZERO(&fds); 176 FD_ZERO(&fds);
186 FD_SET(sock, &fds); 177 FD_SET(sock, &fds);
187 do err = sock_select(sock+1, &fds, NULL, NULL, tm_getretry(tm)); 178 err = sock_select(sock+1, &fds, NULL, NULL, tm);
188 while (err < 0 && errno == EINTR);
189 if (err == 0) return io_strerror(IO_TIMEOUT); 179 if (err == 0) return io_strerror(IO_TIMEOUT);
180 else if (err < 0) return sock_strerror();
190 } 181 }
191 return io_strerror(IO_TIMEOUT); /* can't get here */ 182 return io_strerror(IO_TIMEOUT); /* can't get here */
192} 183}
@@ -194,136 +185,136 @@ const char *sock_accept(p_sock ps, p_sock pa, SA *addr,
194/*-------------------------------------------------------------------------*\ 185/*-------------------------------------------------------------------------*\
195* Send with timeout 186* Send with timeout
196\*-------------------------------------------------------------------------*/ 187\*-------------------------------------------------------------------------*/
197int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, 188int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, p_tm tm)
198 int timeout)
199{ 189{
200 t_sock sock = *ps; 190 t_sock sock = *ps;
201 ssize_t put;
202 /* avoid making system calls on closed sockets */ 191 /* avoid making system calls on closed sockets */
203 if (sock == SOCK_INVALID) return IO_CLOSED; 192 if (sock == SOCK_INVALID) return IO_CLOSED;
204 /* make sure we repeat in case the call was interrupted */ 193 /* loop until we send something or we give up on error */
205 do put = send(sock, data, count, 0); 194 for ( ;; ) {
206 while (put < 0 && errno == EINTR);
207 /* deal with failure */
208 if (put <= 0) {
209 int ret; 195 int ret;
210 fd_set fds; 196 fd_set fds;
211 /* in any case, nothing has been sent */ 197 ssize_t put;
198 /* make sure we repeat in case the call was interrupted */
199 do put = send(sock, data, count, 0);
200 while (put < 0 && errno == EINTR);
201 /* if we sent something, get out */
202 if (put > 0) {
203 *sent = put;
204 return IO_DONE;
205 }
206 /* deal with failure */
212 *sent = 0; 207 *sent = 0;
213 /* only proceed to select if no error happened */
214 if (errno != EAGAIN) return IO_ERROR;
215 /* optimize for the timeout = 0 case */
216 if (timeout == 0) return IO_TIMEOUT;
217 /* here we know the connection has been closed */ 208 /* here we know the connection has been closed */
218 if (errno == EPIPE) return IO_CLOSED; 209 if (put < 0 && errno == EPIPE) return IO_CLOSED;
210 /* send shouldn't return zero and we can only proceed if
211 * there was no serious error */
212 if (put == 0 || errno != EAGAIN) return IO_USER;
213 /* optimize for the timeout = 0 case */
214 if (tm_get(tm) == 0.0) return IO_TIMEOUT;
219 /* run select to avoid busy wait */ 215 /* run select to avoid busy wait */
220 FD_ZERO(&fds); 216 FD_ZERO(&fds);
221 FD_SET(sock, &fds); 217 FD_SET(sock, &fds);
222 ret = sock_select(sock+1, NULL, &fds, NULL, timeout); 218 ret = sock_select(sock+1, NULL, &fds, NULL, tm);
223 if (ret == 0) return IO_TIMEOUT; 219 if (ret == 0) return IO_TIMEOUT;
224 else if (ret > 0 || errno == EINTR) return IO_RETRY; 220 if (ret < 0) return IO_USER;
225 else return IO_ERROR; 221 /* otherwise, try sending again */
226 /* here we successfully sent something */ 222 }
227 } else {
228 *sent = put;
229 return IO_DONE;
230 }
231} 223}
232 224
233/*-------------------------------------------------------------------------*\ 225/*-------------------------------------------------------------------------*\
234* Sendto with timeout 226* Sendto with timeout
235\*-------------------------------------------------------------------------*/ 227\*-------------------------------------------------------------------------*/
236int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, 228int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
237 SA *addr, socklen_t addr_len, int timeout) 229 SA *addr, socklen_t addr_len, p_tm tm)
238{ 230{
239 t_sock sock = *ps; 231 t_sock sock = *ps;
240 ssize_t put; 232 /* avoid making system calls on closed sockets */
241 if (sock == SOCK_INVALID) return IO_CLOSED; 233 if (sock == SOCK_INVALID) return IO_CLOSED;
242 do put = sendto(sock, data, count, 0, addr, addr_len); 234 /* loop until we send something or we give up on error */
243 while (put < 0 && errno == EINTR); 235 for ( ;; ) {
244 if (put <= 0) {
245 int ret; 236 int ret;
246 fd_set fds; 237 fd_set fds;
238 ssize_t put;
239 do put = sendto(sock, data, count, 0, addr, addr_len);
240 while (put < 0 && errno == EINTR);
241 if (put > 0) {
242 *sent = put;
243 return IO_DONE;
244 }
247 *sent = 0; 245 *sent = 0;
248 if (errno != EAGAIN) return IO_ERROR; 246 if (put < 0 && errno == EPIPE) return IO_CLOSED;
249 if (timeout == 0) return IO_TIMEOUT; 247 if (put == 0 || errno != EAGAIN) return IO_USER;
250 if (errno == EPIPE) return IO_CLOSED; 248 if (tm_get(tm) == 0.0) return IO_TIMEOUT;
251 FD_ZERO(&fds); 249 FD_ZERO(&fds);
252 FD_SET(sock, &fds); 250 FD_SET(sock, &fds);
253 ret = sock_select(sock+1, NULL, &fds, NULL, timeout); 251 ret = sock_select(sock+1, NULL, &fds, NULL, tm);
254 if (ret == 0) return IO_TIMEOUT; 252 if (ret == 0) return IO_TIMEOUT;
255 else if (ret > 0 || errno == EINTR) return IO_RETRY; 253 if (ret < 0) return IO_USER;
256 else return IO_ERROR; 254 }
257 } else {
258 *sent = put;
259 return IO_DONE;
260 }
261} 255}
262 256
263/*-------------------------------------------------------------------------*\ 257/*-------------------------------------------------------------------------*\
264* Receive with timeout 258* Receive with timeout
265\*-------------------------------------------------------------------------*/ 259\*-------------------------------------------------------------------------*/
266int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) 260int sock_recv(p_sock ps, char *data, size_t count, size_t *got, p_tm tm) {
267{
268 t_sock sock = *ps; 261 t_sock sock = *ps;
269 ssize_t taken;
270 if (sock == SOCK_INVALID) return IO_CLOSED; 262 if (sock == SOCK_INVALID) return IO_CLOSED;
271 do taken = read(sock, data, count); 263 for ( ;; ) {
272 while (taken < 0 && errno == EINTR);
273 if (taken <= 0) {
274 fd_set fds; 264 fd_set fds;
275 int ret; 265 int ret;
266 ssize_t taken;
267 do taken = read(sock, data, count);
268 while (taken < 0 && errno == EINTR);
269 if (taken > 0) {
270 *got = taken;
271 return IO_DONE;
272 }
276 *got = 0; 273 *got = 0;
277 if (taken == 0) return IO_CLOSED; 274 if (taken == 0) return IO_CLOSED;
278 if (errno != EAGAIN) return IO_ERROR; 275 if (errno != EAGAIN) return IO_USER;
279 if (timeout == 0) return IO_TIMEOUT; 276 if (tm_get(tm) == 0.0) return IO_TIMEOUT;
280 FD_ZERO(&fds); 277 FD_ZERO(&fds);
281 FD_SET(sock, &fds); 278 FD_SET(sock, &fds);
282 ret = sock_select(sock+1, &fds, NULL, NULL, timeout); 279 ret = sock_select(sock+1, &fds, NULL, NULL, tm);
283 if (ret == 0) return IO_TIMEOUT; 280 if (ret == 0) return IO_TIMEOUT;
284 else if (ret > 0 || errno == EINTR) return IO_RETRY; 281 if (ret < 0) return IO_USER;
285 else return IO_ERROR; 282 }
286 } else {
287 *got = taken;
288 return IO_DONE;
289 }
290} 283}
291 284
292/*-------------------------------------------------------------------------*\ 285/*-------------------------------------------------------------------------*\
293* Recvfrom with timeout 286* Recvfrom with timeout
294\*-------------------------------------------------------------------------*/ 287\*-------------------------------------------------------------------------*/
295int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, 288int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
296 SA *addr, socklen_t *addr_len, int timeout) 289 SA *addr, socklen_t *addr_len, p_tm tm) {
297{
298 t_sock sock = *ps; 290 t_sock sock = *ps;
299 ssize_t taken;
300 if (sock == SOCK_INVALID) return IO_CLOSED; 291 if (sock == SOCK_INVALID) return IO_CLOSED;
301 do taken = recvfrom(sock, data, count, 0, addr, addr_len); 292 for ( ;; ) {
302 while (taken < 0 && errno == EINTR);
303 if (taken <= 0) {
304 fd_set fds; 293 fd_set fds;
305 int ret; 294 int ret;
295 ssize_t taken;
296 do taken = recvfrom(sock, data, count, 0, addr, addr_len);
297 while (taken < 0 && errno == EINTR);
298 if (taken > 0) {
299 *got = taken;
300 return IO_DONE;
301 }
306 *got = 0; 302 *got = 0;
307 if (taken == 0) return IO_CLOSED; 303 if (taken == 0) return IO_CLOSED;
308 if (errno != EAGAIN) return IO_ERROR; 304 if (errno != EAGAIN) return IO_USER;
309 if (timeout == 0) return IO_TIMEOUT; 305 if (tm_get(tm) == 0.0) return IO_TIMEOUT;
310 FD_ZERO(&fds); 306 FD_ZERO(&fds);
311 FD_SET(sock, &fds); 307 FD_SET(sock, &fds);
312 ret = sock_select(sock+1, &fds, NULL, NULL, timeout); 308 ret = sock_select(sock+1, &fds, NULL, NULL, tm);
313 if (ret == 0) return IO_TIMEOUT; 309 if (ret == 0) return IO_TIMEOUT;
314 else if (ret > 0 || errno == EINTR) return IO_RETRY; 310 if (ret < 0) return IO_USER;
315 else return IO_ERROR; 311 }
316 } else {
317 *got = taken;
318 return IO_DONE;
319 }
320} 312}
321 313
322/*-------------------------------------------------------------------------*\ 314/*-------------------------------------------------------------------------*\
323* Put socket into blocking mode 315* Put socket into blocking mode
324\*-------------------------------------------------------------------------*/ 316\*-------------------------------------------------------------------------*/
325void sock_setblocking(p_sock ps) 317void sock_setblocking(p_sock ps) {
326{
327 int flags = fcntl(*ps, F_GETFL, 0); 318 int flags = fcntl(*ps, F_GETFL, 0);
328 flags &= (~(O_NONBLOCK)); 319 flags &= (~(O_NONBLOCK));
329 fcntl(*ps, F_SETFL, flags); 320 fcntl(*ps, F_SETFL, flags);
@@ -332,8 +323,7 @@ void sock_setblocking(p_sock ps)
332/*-------------------------------------------------------------------------*\ 323/*-------------------------------------------------------------------------*\
333* Put socket into non-blocking mode 324* Put socket into non-blocking mode
334\*-------------------------------------------------------------------------*/ 325\*-------------------------------------------------------------------------*/
335void sock_setnonblocking(p_sock ps) 326void sock_setnonblocking(p_sock ps) {
336{
337 int flags = fcntl(*ps, F_GETFL, 0); 327 int flags = fcntl(*ps, F_GETFL, 0);
338 flags |= O_NONBLOCK; 328 flags |= O_NONBLOCK;
339 fcntl(*ps, F_SETFL, flags); 329 fcntl(*ps, F_SETFL, flags);
@@ -342,98 +332,20 @@ void sock_setnonblocking(p_sock ps)
342/*-------------------------------------------------------------------------*\ 332/*-------------------------------------------------------------------------*\
343* Error translation functions 333* Error translation functions
344\*-------------------------------------------------------------------------*/ 334\*-------------------------------------------------------------------------*/
345/* return error messages for the known errors reported by gethostbyname */ 335const char *sock_hoststrerror(void) {
346const char *sock_hoststrerror(void) 336 return hstrerror(h_errno);
347{
348 switch (h_errno) {
349 case HOST_NOT_FOUND: return "host not found";
350 case NO_ADDRESS: return "valid host but no ip found";
351 case NO_RECOVERY: return "name server error";
352 case TRY_AGAIN: return "name server unavailable, try again later";
353 default: return "unknown error";
354 }
355}
356
357/* return error messages for the known errors reported by socket */
358static const char *sock_createstrerror(int err)
359{
360 switch (err) {
361 case EPROTONOSUPPORT: return "protocol not supported";
362 case EACCES: return "access denied";
363 case EMFILE: return "process file table is full";
364 case ENFILE: return "kernel file table is full";
365 case EINVAL: return "unknown protocol or family";
366 case ENOBUFS: return "insuffucient buffer space";
367 default: return "unknown error";
368 }
369} 337}
370 338
371/* return error messages for the known errors reported by accept */ 339/* make sure important error messages are standard */
372static const char *sock_acceptstrerror(int err) 340const char *sock_strerror(void) {
373{ 341 switch (errno) {
374 switch (err) { 342 case EADDRINUSE:
375 case EAGAIN: return io_strerror(IO_RETRY); 343 return "address already in use";
376 case EBADF: return "invalid descriptor"; 344 default:
377 case ENOBUFS: case ENOMEM: return "insuffucient buffer space"; 345 return strerror(errno);
378 case ENOTSOCK: return "descriptor not a socket";
379 case EOPNOTSUPP: return "not supported";
380 case EINTR: return "call interrupted";
381 case ECONNABORTED: return "connection aborted";
382 case EINVAL: return "not listening";
383 case EMFILE: return "process file table is full";
384 case ENFILE: return "kernel file table is full";
385 case EFAULT: return "invalid memory address";
386 default: return "unknown error";
387 }
388}
389
390
391/* return error messages for the known errors reported by bind */
392static const char *sock_bindstrerror(int err)
393{
394 switch (err) {
395 case EBADF: return "invalid descriptor";
396 case ENOTSOCK: return "descriptor not a socket";
397 case EADDRNOTAVAIL: return "address unavailable in local host";
398 case EADDRINUSE: return "address already in use";
399 case EINVAL: return "already bound";
400 case EACCES: return "access denied";
401 case EFAULT: return "invalid memory address";
402 case ENOMEM: return "out of memory";
403 default: return "unknown error";
404 } 346 }
405} 347}
406 348
407/* return error messages for the known errors reported by listen */ 349const char *sock_geterr(p_sock ps, int code) {
408static const char *sock_listenstrerror(int err) 350 return sock_strerror();
409{
410 switch (err) {
411 case EADDRINUSE: return "local address already in use";
412 case EBADF: return "invalid descriptor";
413 case ENOTSOCK: return "descriptor not a socket";
414 case EOPNOTSUPP: return "not supported";
415 default: return "unknown error";
416 }
417}
418
419/* return error messages for the known errors reported by connect */
420static const char *sock_connectstrerror(int err)
421{
422 switch (err) {
423 case EBADF: return "invalid descriptor";
424 case EFAULT: return "invalid memory address";
425 case ENOTSOCK: return "descriptor not a socket";
426 case EADDRNOTAVAIL: return "address not available in local host";
427 case EISCONN: return "already connected";
428 case ECONNREFUSED: return "connection refused";
429 case ETIMEDOUT: return io_strerror(IO_TIMEOUT);
430 case ENETUNREACH: return "network is unreachable";
431 case EADDRINUSE: return "local address already in use";
432 case EINPROGRESS: return "would block";
433 case EALREADY: return "connect already in progress";
434 case EAGAIN: return "not enough free ports";
435 case EAFNOSUPPORT: return "address family not supported";
436 case EPERM: return "broadcast not enabled or firewall block";
437 default: return "unknown error";
438 }
439} 351}