aboutsummaryrefslogtreecommitdiff
path: root/src/usocket.c
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-18 00:04:20 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-01-18 00:04:20 +0000
commitc8d58798f0b0c789df5c566494112f81ac302432 (patch)
tree40c52eab0a4bf92636ebe13027d165f0b8452bb1 /src/usocket.c
parent02ef4e7daae6bef629dcb568052755fb85ed2efc (diff)
downloadluasocket-c8d58798f0b0c789df5c566494112f81ac302432.tar.gz
luasocket-c8d58798f0b0c789df5c566494112f81ac302432.tar.bz2
luasocket-c8d58798f0b0c789df5c566494112f81ac302432.zip
Trying to get connect-with-timeout to work. Darwin works...
Diffstat (limited to 'src/usocket.c')
-rw-r--r--src/usocket.c163
1 files changed, 77 insertions, 86 deletions
diff --git a/src/usocket.c b/src/usocket.c
index 9fcf4e8..acac852 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -46,50 +46,59 @@ void sock_destroy(p_sock ps)
46/*-------------------------------------------------------------------------*\ 46/*-------------------------------------------------------------------------*\
47* Creates and sets up a socket 47* Creates and sets up a socket
48\*-------------------------------------------------------------------------*/ 48\*-------------------------------------------------------------------------*/
49const char *sock_create(p_sock ps, int domain, int type, int protocol) 49int sock_create(p_sock ps, int domain, int type, int protocol)
50{ 50{
51 int val = 1; 51 int val = 1;
52 t_sock sock = socket(domain, type, protocol); 52 t_sock sock = socket(domain, type, protocol);
53 if (sock == SOCK_INVALID) return sock_createstrerror(); 53 if (sock == SOCK_INVALID) return IO_ERROR;
54 *ps = sock; 54 *ps = sock;
55 sock_setnonblocking(ps); 55 sock_setnonblocking(ps);
56 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val)); 56 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
57 return NULL; 57 return IO_DONE;
58} 58}
59 59
60/*-------------------------------------------------------------------------*\ 60/*-------------------------------------------------------------------------*\
61* Connects or returns error message 61* Connects or returns error message
62\*-------------------------------------------------------------------------*/ 62\*-------------------------------------------------------------------------*/
63const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout) 63int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout)
64{ 64{
65 t_sock sock = *ps; 65 t_sock sock = *ps;
66 if (sock == SOCK_INVALID) return "closed"; 66 if (sock == SOCK_INVALID) return IO_CLOSED;
67 /* if connect fails, we have to find out why */
67 if (connect(sock, addr, addr_len) < 0) { 68 if (connect(sock, addr, addr_len) < 0) {
68 struct timeval tv; 69 struct timeval tv;
69 fd_set wfds, efds; 70 fd_set rfds, efds, wfds;
70 int err; 71 int err;
72 /* make sure the system is trying to connect */
73 if (errno != EINPROGRESS) return IO_ERROR;
71 tv.tv_sec = timeout / 1000; 74 tv.tv_sec = timeout / 1000;
72 tv.tv_usec = (timeout % 1000) * 1000; 75 tv.tv_usec = (timeout % 1000) * 1000;
73 FD_ZERO(&wfds); FD_ZERO(&efds); 76 FD_ZERO(&rfds); FD_SET(sock, &rfds);
74 FD_SET(sock, &wfds); FD_SET(sock, &efds); 77 FD_ZERO(&wfds); FD_SET(sock, &wfds);
75 do err = select(sock+1, NULL, &wfds, &efds, timeout >= 0 ? &tv : NULL); 78 FD_ZERO(&efds); FD_SET(sock, &efds);
76 while (err < 0 && errno == EINTR); 79 /* we run select to avoid busy waiting */
77 if (err <= 0) return "timeout"; 80 err = select(sock+1, &rfds, &wfds, &efds, timeout >= 0? &tv: NULL);
78 if (FD_ISSET(sock, &efds)) { 81 /* if select was interrupted, ask the user to retry */
82 if (err < 0 && errno == EINTR) return IO_RETRY;
83 /* if selects readable, try reading */
84 if (err > 0) {
79 char dummy; 85 char dummy;
80 recv(sock, &dummy, 0, 0); 86 /* try reading so that errno is set */
81 return sock_connectstrerror(); 87 if (recv(sock, &dummy, 0, 0) < 0) return IO_ERROR;
82 } else return NULL; 88 return IO_DONE;
83 } else return NULL; 89 /* if no event happened, there was a timeout */
90 } else return IO_TIMEOUT;
91 /* otherwise connection succeeded */
92 } else return IO_DONE;
84} 93}
85 94
86/*-------------------------------------------------------------------------*\ 95/*-------------------------------------------------------------------------*\
87* Binds or returns error message 96* Binds or returns error message
88\*-------------------------------------------------------------------------*/ 97\*-------------------------------------------------------------------------*/
89const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) 98int sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
90{ 99{
91 if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); 100 if (bind(*ps, addr, addr_len) < 0) return IO_ERROR;
92 else return NULL; 101 else return IO_DONE;
93} 102}
94 103
95/*-------------------------------------------------------------------------*\ 104/*-------------------------------------------------------------------------*\
@@ -115,25 +124,24 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
115 int timeout) 124 int timeout)
116{ 125{
117 t_sock sock = *ps; 126 t_sock sock = *ps;
118 struct timeval tv;
119 SA dummy_addr; 127 SA dummy_addr;
120 socklen_t dummy_len; 128 socklen_t dummy_len;
121 fd_set fds;
122 int err;
123 if (sock == SOCK_INVALID) return IO_CLOSED; 129 if (sock == SOCK_INVALID) return IO_CLOSED;
124 tv.tv_sec = timeout / 1000;
125 tv.tv_usec = (timeout % 1000) * 1000;
126 FD_ZERO(&fds);
127 FD_SET(sock, &fds);
128 *pa = SOCK_INVALID;
129 do err = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
130 while (err < 0 && errno == EINTR);
131 if (err <= 0) return IO_TIMEOUT;
132 if (!addr) addr = &dummy_addr; 130 if (!addr) addr = &dummy_addr;
133 if (!addr_len) addr_len = &dummy_len; 131 if (!addr_len) addr_len = &dummy_len;
134 *pa = accept(sock, addr, addr_len); 132 *pa = accept(sock, addr, addr_len);
135 if (*pa == SOCK_INVALID) return IO_ERROR; 133 if (*pa == SOCK_INVALID) {
136 else return IO_DONE; 134 struct timeval tv;
135 fd_set fds;
136 tv.tv_sec = timeout / 1000;
137 tv.tv_usec = (timeout % 1000) * 1000;
138 FD_ZERO(&fds);
139 FD_SET(sock, &fds);
140 /* just call select to avoid busy-wait. doesn't really matter
141 * what happens. the caller will choose to retry or not */
142 select(sock+1, &fds, NULL, NULL, timeout >= 0? &tv: NULL);
143 return IO_RETRY;
144 } else return IO_DONE;
137} 145}
138 146
139/*-------------------------------------------------------------------------*\ 147/*-------------------------------------------------------------------------*\
@@ -144,32 +152,31 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
144{ 152{
145 t_sock sock = *ps; 153 t_sock sock = *ps;
146 ssize_t put; 154 ssize_t put;
147 int ret;
148 /* avoid making system calls on closed sockets */ 155 /* avoid making system calls on closed sockets */
149 if (sock == SOCK_INVALID) return IO_CLOSED; 156 if (sock == SOCK_INVALID) return IO_CLOSED;
150 /* make sure we repeat in case the call was interrupted */ 157 /* make sure we repeat in case the call was interrupted */
151 do put = write(sock, data, count); 158 do put = send(sock, data, count, 0);
152 while (put <= 0 && errno == EINTR); 159 while (put < 0 && errno == EINTR);
153 /* deal with failure */ 160 /* deal with failure */
154 if (put <= 0) { 161 if (put <= 0) {
162 struct timeval tv;
163 fd_set fds;
155 /* in any case, nothing has been sent */ 164 /* in any case, nothing has been sent */
156 *sent = 0; 165 *sent = 0;
166 /* here we know the connection has been closed */
167 if (errno == EPIPE) return IO_CLOSED;
157 /* run select to avoid busy wait */ 168 /* run select to avoid busy wait */
158 if (errno != EPIPE) { 169 tv.tv_sec = timeout / 1000;
159 struct timeval tv; 170 tv.tv_usec = (timeout % 1000) * 1000;
160 fd_set fds; 171 FD_ZERO(&fds);
161 tv.tv_sec = timeout / 1000; 172 FD_SET(sock, &fds);
162 tv.tv_usec = (timeout % 1000) * 1000; 173 if (select(sock+1, NULL, &fds, NULL, timeout >= 0? &tv: NULL) <= 0) {
163 FD_ZERO(&fds); 174 /* here the call was interrupted. calling again might work */
164 FD_SET(sock, &fds); 175 if (errno == EINTR) return IO_RETRY;
165 do ret = select(sock+1, NULL, &fds, NULL, timeout >= 0 ?&tv : NULL); 176 /* here there was no data before timeout */
166 while (ret < 0 && errno == EINTR);
167 /* tell the caller to call us again because there is more data */
168 if (ret > 0) return IO_DONE;
169 /* tell the caller there was no data before timeout */
170 else return IO_TIMEOUT; 177 else return IO_TIMEOUT;
171 /* here we know the connection has been closed */ 178 /* here we didn't send anything, but now we can */
172 } else return IO_CLOSED; 179 } else return IO_DONE;
173 /* here we successfully sent something */ 180 /* here we successfully sent something */
174 } else { 181 } else {
175 *sent = put; 182 *sent = put;
@@ -185,33 +192,22 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
185{ 192{
186 t_sock sock = *ps; 193 t_sock sock = *ps;
187 ssize_t put; 194 ssize_t put;
188 int ret;
189 /* avoid making system calls on closed sockets */
190 if (sock == SOCK_INVALID) return IO_CLOSED; 195 if (sock == SOCK_INVALID) return IO_CLOSED;
191 /* make sure we repeat in case the call was interrupted */
192 do put = sendto(sock, data, count, 0, addr, addr_len); 196 do put = sendto(sock, data, count, 0, addr, addr_len);
193 while (put <= 0 && errno == EINTR); 197 while (put < 0 && errno == EINTR);
194 /* deal with failure */
195 if (put <= 0) { 198 if (put <= 0) {
196 /* in any case, nothing has been sent */ 199 struct timeval tv;
200 fd_set fds;
197 *sent = 0; 201 *sent = 0;
198 /* run select to avoid busy wait */ 202 if (errno == EPIPE) return IO_CLOSED;
199 if (errno != EPIPE) { 203 tv.tv_sec = timeout / 1000;
200 struct timeval tv; 204 tv.tv_usec = (timeout % 1000) * 1000;
201 fd_set fds; 205 FD_ZERO(&fds);
202 tv.tv_sec = timeout / 1000; 206 FD_SET(sock, &fds);
203 tv.tv_usec = (timeout % 1000) * 1000; 207 if (select(sock+1, NULL, &fds, NULL, timeout >= 0? &tv: NULL) <= 0) {
204 FD_ZERO(&fds); 208 if (errno == EINTR) return IO_RETRY;
205 FD_SET(sock, &fds);
206 do ret = select(sock+1, NULL, &fds, NULL, timeout >= 0? &tv: NULL);
207 while (ret < 0 && errno == EINTR);
208 /* tell the caller to call us again because there is more data */
209 if (ret > 0) return IO_DONE;
210 /* tell the caller there was no data before timeout */
211 else return IO_TIMEOUT; 209 else return IO_TIMEOUT;
212 /* here we know the connection has been closed */ 210 } else return IO_DONE;
213 } else return IO_CLOSED;
214 /* here we successfully sent something */
215 } else { 211 } else {
216 *sent = put; 212 *sent = put;
217 return IO_DONE; 213 return IO_DONE;
@@ -220,11 +216,6 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
220 216
221/*-------------------------------------------------------------------------*\ 217/*-------------------------------------------------------------------------*\
222* Receive with timeout 218* Receive with timeout
223* Here we exchanged the order of the calls to write and select
224* The idea is that the outer loop (whoever is calling sock_send)
225* will call the function again if we didn't time out, so we can
226* call write and then select only if it fails.
227* Should speed things up!
228\*-------------------------------------------------------------------------*/ 219\*-------------------------------------------------------------------------*/
229int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) 220int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
230{ 221{
@@ -232,7 +223,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
232 ssize_t taken; 223 ssize_t taken;
233 if (sock == SOCK_INVALID) return IO_CLOSED; 224 if (sock == SOCK_INVALID) return IO_CLOSED;
234 do taken = read(sock, data, count); 225 do taken = read(sock, data, count);
235 while (taken <= 0 && errno == EINTR); 226 while (taken < 0 && errno == EINTR);
236 if (taken <= 0) { 227 if (taken <= 0) {
237 struct timeval tv; 228 struct timeval tv;
238 fd_set fds; 229 fd_set fds;
@@ -243,10 +234,10 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
243 tv.tv_usec = (timeout % 1000) * 1000; 234 tv.tv_usec = (timeout % 1000) * 1000;
244 FD_ZERO(&fds); 235 FD_ZERO(&fds);
245 FD_SET(sock, &fds); 236 FD_SET(sock, &fds);
246 do ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); 237 ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
247 while (ret < 0 && errno == EINTR); 238 if (ret < 0 && errno == EINTR) return IO_RETRY;
248 if (ret > 0) return IO_DONE; 239 if (ret == 0) return IO_TIMEOUT;
249 else return IO_TIMEOUT; 240 else return IO_DONE;
250 } else { 241 } else {
251 *got = taken; 242 *got = taken;
252 return IO_DONE; 243 return IO_DONE;
@@ -263,7 +254,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
263 ssize_t taken; 254 ssize_t taken;
264 if (sock == SOCK_INVALID) return IO_CLOSED; 255 if (sock == SOCK_INVALID) return IO_CLOSED;
265 do taken = recvfrom(sock, data, count, 0, addr, addr_len); 256 do taken = recvfrom(sock, data, count, 0, addr, addr_len);
266 while (taken <= 0 && errno == EINTR); 257 while (taken < 0 && errno == EINTR);
267 if (taken <= 0) { 258 if (taken <= 0) {
268 struct timeval tv; 259 struct timeval tv;
269 fd_set fds; 260 fd_set fds;
@@ -274,10 +265,10 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
274 tv.tv_usec = (timeout % 1000) * 1000; 265 tv.tv_usec = (timeout % 1000) * 1000;
275 FD_ZERO(&fds); 266 FD_ZERO(&fds);
276 FD_SET(sock, &fds); 267 FD_SET(sock, &fds);
277 do ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); 268 ret = select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
278 while (ret < 0 && errno == EINTR); 269 if (ret < 0 && errno == EINTR) return IO_RETRY;
279 if (ret > 0) return IO_DONE; 270 if (ret == 0) return IO_TIMEOUT;
280 else return IO_TIMEOUT; 271 else return IO_DONE;
281 } else { 272 } else {
282 *got = taken; 273 *got = taken;
283 return IO_DONE; 274 return IO_DONE;