diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-21 18:40:52 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2004-01-21 18:40:52 +0000 |
commit | 195069cf5f929f445b0ce20e531cd482d2559083 (patch) | |
tree | 6444d37c4ce32395428ba26ee0d16c0c372bd9da /src/usocket.c | |
parent | e63f500d24ff0238425c9e13f220daf09a277ef5 (diff) | |
download | luasocket-195069cf5f929f445b0ce20e531cd482d2559083.tar.gz luasocket-195069cf5f929f445b0ce20e531cd482d2559083.tar.bz2 luasocket-195069cf5f929f445b0ce20e531cd482d2559083.zip |
Fixed functions that return messages in ?socket.c.
Moved complexity of connect and accept there.
Created a new options.c module to take care of options.
Auxiliar.c is now cleaner.
Diffstat (limited to 'src/usocket.c')
-rw-r--r-- | src/usocket.c | 78 |
1 files changed, 45 insertions, 33 deletions
diff --git a/src/usocket.c b/src/usocket.c index f5939a9..54f203b 100644 --- a/src/usocket.c +++ b/src/usocket.c | |||
@@ -20,6 +20,10 @@ | |||
20 | 20 | ||
21 | #include "socket.h" | 21 | #include "socket.h" |
22 | 22 | ||
23 | static const char *sock_createstrerror(void); | ||
24 | static const char *sock_bindstrerror(void); | ||
25 | static const char *sock_connectstrerror(void); | ||
26 | |||
23 | /*-------------------------------------------------------------------------*\ | 27 | /*-------------------------------------------------------------------------*\ |
24 | * Initializes module | 28 | * Initializes module |
25 | \*-------------------------------------------------------------------------*/ | 29 | \*-------------------------------------------------------------------------*/ |
@@ -50,31 +54,37 @@ void sock_destroy(p_sock ps) | |||
50 | /*-------------------------------------------------------------------------*\ | 54 | /*-------------------------------------------------------------------------*\ |
51 | * Creates and sets up a socket | 55 | * Creates and sets up a socket |
52 | \*-------------------------------------------------------------------------*/ | 56 | \*-------------------------------------------------------------------------*/ |
53 | int sock_create(p_sock ps, int domain, int type, int protocol) | 57 | const char *sock_create(p_sock ps, int domain, int type, int protocol) |
54 | { | 58 | { |
55 | int val = 1; | 59 | int val = 1; |
56 | t_sock sock = socket(domain, type, protocol); | 60 | t_sock sock = socket(domain, type, protocol); |
57 | if (sock == SOCK_INVALID) return IO_ERROR; | 61 | if (sock == SOCK_INVALID) return sock_createstrerror(); |
58 | *ps = sock; | 62 | *ps = sock; |
59 | sock_setnonblocking(ps); | 63 | sock_setnonblocking(ps); |
60 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val)); | 64 | setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val)); |
61 | return IO_DONE; | 65 | return NULL; |
62 | } | 66 | } |
63 | 67 | ||
64 | /*-------------------------------------------------------------------------*\ | 68 | /*-------------------------------------------------------------------------*\ |
65 | * Connects or returns error message | 69 | * Connects or returns error message |
66 | \*-------------------------------------------------------------------------*/ | 70 | \*-------------------------------------------------------------------------*/ |
67 | int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout) | 71 | const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, p_tm tm) |
68 | { | 72 | { |
69 | t_sock sock = *ps; | 73 | t_sock sock = *ps; |
70 | if (sock == SOCK_INVALID) return IO_CLOSED; | 74 | int err; |
71 | /* if connect fails, we have to find out why */ | 75 | /* don't call on closed socket */ |
72 | if (connect(sock, addr, addr_len) < 0) { | 76 | if (sock == SOCK_INVALID) return io_strerror(IO_CLOSED); |
77 | /* ask system to connect */ | ||
78 | err = connect(sock, addr, addr_len); | ||
79 | /* if no error, we're done */ | ||
80 | if (err == 0) return NULL; | ||
81 | /* make sure the system is trying to connect */ | ||
82 | if (errno != EINPROGRESS) return io_strerror(IO_ERROR); | ||
83 | /* wait for a timeout or for the system's answer */ | ||
84 | for ( ;; ) { | ||
73 | struct timeval tv; | 85 | struct timeval tv; |
74 | fd_set rfds, efds, wfds; | 86 | fd_set rfds, wfds, efds; |
75 | int err; | 87 | int timeout = tm_getretry(tm); |
76 | /* make sure the system is trying to connect */ | ||
77 | if (errno != EINPROGRESS) return IO_ERROR; | ||
78 | tv.tv_sec = timeout / 1000; | 88 | tv.tv_sec = timeout / 1000; |
79 | tv.tv_usec = (timeout % 1000) * 1000; | 89 | tv.tv_usec = (timeout % 1000) * 1000; |
80 | FD_ZERO(&rfds); FD_SET(sock, &rfds); | 90 | FD_ZERO(&rfds); FD_SET(sock, &rfds); |
@@ -82,28 +92,29 @@ int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout) | |||
82 | FD_ZERO(&efds); FD_SET(sock, &efds); | 92 | FD_ZERO(&efds); FD_SET(sock, &efds); |
83 | /* we run select to avoid busy waiting */ | 93 | /* we run select to avoid busy waiting */ |
84 | err = select(sock+1, &rfds, &wfds, &efds, timeout >= 0? &tv: NULL); | 94 | err = select(sock+1, &rfds, &wfds, &efds, timeout >= 0? &tv: NULL); |
85 | /* if select was interrupted, ask the user to retry */ | 95 | /* if select was interrupted, try again */ |
86 | if (err < 0 && errno == EINTR) return IO_RETRY; | 96 | if (err < 0 && errno == EINTR) continue; |
87 | /* if selects readable, try reading */ | 97 | /* if selects readable, try reading */ |
88 | if (err > 0) { | 98 | if (err > 0) { |
89 | char dummy; | 99 | char dummy; |
90 | /* try reading so that errno is set */ | 100 | /* recv will set errno to the value a blocking connect would set */ |
91 | if (recv(sock, &dummy, 0, 0) < 0 && errno != EAGAIN) | 101 | if (recv(sock, &dummy, 0, 0) < 0 && errno != EAGAIN) |
92 | return IO_ERROR; | 102 | return sock_connectstrerror(); |
93 | else return IO_DONE; | 103 | else |
104 | return NULL; | ||
94 | /* if no event happened, there was a timeout */ | 105 | /* if no event happened, there was a timeout */ |
95 | } else return IO_TIMEOUT; | 106 | } else return io_strerror(IO_TIMEOUT); |
96 | /* otherwise connection succeeded */ | 107 | } |
97 | } else return IO_DONE; | 108 | return io_strerror(IO_TIMEOUT); /* can't get here */ |
98 | } | 109 | } |
99 | 110 | ||
100 | /*-------------------------------------------------------------------------*\ | 111 | /*-------------------------------------------------------------------------*\ |
101 | * Binds or returns error message | 112 | * Binds or returns error message |
102 | \*-------------------------------------------------------------------------*/ | 113 | \*-------------------------------------------------------------------------*/ |
103 | int sock_bind(p_sock ps, SA *addr, socklen_t addr_len) | 114 | const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) |
104 | { | 115 | { |
105 | if (bind(*ps, addr, addr_len) < 0) return IO_ERROR; | 116 | if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); |
106 | else return IO_DONE; | 117 | else return NULL; |
107 | } | 118 | } |
108 | 119 | ||
109 | /*-------------------------------------------------------------------------*\ | 120 | /*-------------------------------------------------------------------------*\ |
@@ -125,8 +136,7 @@ void sock_shutdown(p_sock ps, int how) | |||
125 | /*-------------------------------------------------------------------------*\ | 136 | /*-------------------------------------------------------------------------*\ |
126 | * Accept with timeout | 137 | * Accept with timeout |
127 | \*-------------------------------------------------------------------------*/ | 138 | \*-------------------------------------------------------------------------*/ |
128 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | 139 | int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, p_tm tm) |
129 | int timeout) | ||
130 | { | 140 | { |
131 | t_sock sock = *ps; | 141 | t_sock sock = *ps; |
132 | SA dummy_addr; | 142 | SA dummy_addr; |
@@ -134,19 +144,21 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, | |||
134 | if (sock == SOCK_INVALID) return IO_CLOSED; | 144 | if (sock == SOCK_INVALID) return IO_CLOSED; |
135 | if (!addr) addr = &dummy_addr; | 145 | if (!addr) addr = &dummy_addr; |
136 | if (!addr_len) addr_len = &dummy_len; | 146 | if (!addr_len) addr_len = &dummy_len; |
137 | *pa = accept(sock, addr, addr_len); | 147 | for (;;) { |
138 | if (*pa == SOCK_INVALID) { | 148 | int timeout = tm_getretry(tm); |
139 | struct timeval tv; | 149 | struct timeval tv; |
140 | fd_set fds; | 150 | fd_set fds; |
151 | *pa = accept(sock, addr, addr_len); | ||
152 | if (*pa != SOCK_INVALID) return IO_DONE; | ||
153 | if (timeout == 0) return IO_TIMEOUT; | ||
141 | tv.tv_sec = timeout / 1000; | 154 | tv.tv_sec = timeout / 1000; |
142 | tv.tv_usec = (timeout % 1000) * 1000; | 155 | tv.tv_usec = (timeout % 1000) * 1000; |
143 | FD_ZERO(&fds); | 156 | FD_ZERO(&fds); |
144 | FD_SET(sock, &fds); | 157 | FD_SET(sock, &fds); |
145 | /* just call select to avoid busy-wait. doesn't really matter | 158 | /* call select just to avoid busy-wait. */ |
146 | * what happens. the caller will choose to retry or not */ | ||
147 | select(sock+1, &fds, NULL, NULL, timeout >= 0? &tv: NULL); | 159 | select(sock+1, &fds, NULL, NULL, timeout >= 0? &tv: NULL); |
148 | return IO_RETRY; | 160 | } |
149 | } else return IO_DONE; | 161 | return IO_TIMEOUT; /* can't get here */ |
150 | } | 162 | } |
151 | 163 | ||
152 | /*-------------------------------------------------------------------------*\ | 164 | /*-------------------------------------------------------------------------*\ |
@@ -314,7 +326,7 @@ const char *sock_hoststrerror(void) | |||
314 | } | 326 | } |
315 | } | 327 | } |
316 | 328 | ||
317 | const char *sock_createstrerror(void) | 329 | static const char *sock_createstrerror(void) |
318 | { | 330 | { |
319 | switch (errno) { | 331 | switch (errno) { |
320 | case EACCES: return "access denied"; | 332 | case EACCES: return "access denied"; |
@@ -325,7 +337,7 @@ const char *sock_createstrerror(void) | |||
325 | } | 337 | } |
326 | } | 338 | } |
327 | 339 | ||
328 | const char *sock_bindstrerror(void) | 340 | static const char *sock_bindstrerror(void) |
329 | { | 341 | { |
330 | switch (errno) { | 342 | switch (errno) { |
331 | case EBADF: return "invalid descriptor"; | 343 | case EBADF: return "invalid descriptor"; |
@@ -339,7 +351,7 @@ const char *sock_bindstrerror(void) | |||
339 | } | 351 | } |
340 | } | 352 | } |
341 | 353 | ||
342 | const char *sock_connectstrerror(void) | 354 | static const char *sock_connectstrerror(void) |
343 | { | 355 | { |
344 | switch (errno) { | 356 | switch (errno) { |
345 | case EBADF: return "invalid descriptor"; | 357 | case EBADF: return "invalid descriptor"; |