aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/buffer.c12
-rw-r--r--src/http.lua8
-rw-r--r--src/inet.c41
-rw-r--r--src/inet.h8
-rw-r--r--src/io.c35
-rw-r--r--src/io.h6
-rw-r--r--src/socket.h7
-rw-r--r--src/tcp.c69
-rw-r--r--src/timeout.c4
-rw-r--r--src/timeout.h4
-rw-r--r--src/udp.c64
-rw-r--r--src/usocket.c163
-rw-r--r--test/httptest.lua3
-rw-r--r--test/testclnt.lua4
14 files changed, 231 insertions, 197 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 04419e7..e6d4ce8 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -138,8 +138,7 @@ int sendraw(p_buf buf, const char *data, size_t count, size_t *sent)
138 int err = IO_DONE; 138 int err = IO_DONE;
139 while (total < count && err == IO_DONE) { 139 while (total < count && err == IO_DONE) {
140 size_t done; 140 size_t done;
141 err = io->send(io->ctx, data+total, count-total, &done, 141 err = io->send(io->ctx, data+total, count-total, &done, tm_get(tm));
142 tm_getsuccess(tm));
143 total += done; 142 total += done;
144 } 143 }
145 *sent = total; 144 *sent = total;
@@ -156,7 +155,7 @@ int recvraw(lua_State *L, p_buf buf, size_t wanted)
156 size_t total = 0; 155 size_t total = 0;
157 luaL_Buffer b; 156 luaL_Buffer b;
158 luaL_buffinit(L, &b); 157 luaL_buffinit(L, &b);
159 while (total < wanted && err == IO_DONE) { 158 while (total < wanted && (err == IO_DONE || err == IO_RETRY)) {
160 size_t count; const char *data; 159 size_t count; const char *data;
161 err = buf_get(buf, &data, &count); 160 err = buf_get(buf, &data, &count);
162 count = MIN(count, wanted - total); 161 count = MIN(count, wanted - total);
@@ -177,7 +176,7 @@ int recvall(lua_State *L, p_buf buf)
177 int err = IO_DONE; 176 int err = IO_DONE;
178 luaL_Buffer b; 177 luaL_Buffer b;
179 luaL_buffinit(L, &b); 178 luaL_buffinit(L, &b);
180 while (err == IO_DONE) { 179 while (err == IO_DONE || err == IO_RETRY) {
181 const char *data; size_t count; 180 const char *data; size_t count;
182 err = buf_get(buf, &data, &count); 181 err = buf_get(buf, &data, &count);
183 luaL_addlstring(&b, data, count); 182 luaL_addlstring(&b, data, count);
@@ -197,7 +196,7 @@ int recvline(lua_State *L, p_buf buf)
197 int err = IO_DONE; 196 int err = IO_DONE;
198 luaL_Buffer b; 197 luaL_Buffer b;
199 luaL_buffinit(L, &b); 198 luaL_buffinit(L, &b);
200 while (err == IO_DONE) { 199 while (err == IO_DONE || err == IO_RETRY) {
201 size_t count, pos; const char *data; 200 size_t count, pos; const char *data;
202 err = buf_get(buf, &data, &count); 201 err = buf_get(buf, &data, &count);
203 pos = 0; 202 pos = 0;
@@ -240,8 +239,7 @@ int buf_get(p_buf buf, const char **data, size_t *count)
240 p_tm tm = buf->tm; 239 p_tm tm = buf->tm;
241 if (buf_isempty(buf)) { 240 if (buf_isempty(buf)) {
242 size_t got; 241 size_t got;
243 err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, 242 err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm_get(tm));
244 tm_getsuccess(tm));
245 buf->first = 0; 243 buf->first = 0;
246 buf->last = got; 244 buf->last = got;
247 } 245 }
diff --git a/src/http.lua b/src/http.lua
index 1925c68..2fc9e87 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -549,10 +549,16 @@ function request_cb(reqt, respt)
549 reqt.headers = fill_headers(reqt.headers, parsed) 549 reqt.headers = fill_headers(reqt.headers, parsed)
550 -- try to connect to server 550 -- try to connect to server
551 local sock 551 local sock
552 sock, respt.error = socket.connect(parsed.host, parsed.port) 552 sock, respt.error = socket.tcp()
553 if not sock then return respt end 553 if not sock then return respt end
554 -- set connection timeout so that we do not hang forever 554 -- set connection timeout so that we do not hang forever
555 sock:settimeout(TIMEOUT) 555 sock:settimeout(TIMEOUT)
556 local ret
557 ret, respt.error = sock:connect(parsed.host, parsed.port)
558 if not ret then
559 sock:close()
560 return respt
561 end
556 -- send request message 562 -- send request message
557 respt.error = send_request(sock, reqt.method, 563 respt.error = send_request(sock, reqt.method,
558 request_uri(parsed), reqt.headers, reqt.body_cb) 564 request_uri(parsed), reqt.headers, reqt.body_cb)
diff --git a/src/inet.c b/src/inet.c
index 2334f53..80c488b 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -180,11 +180,11 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
180/*-------------------------------------------------------------------------*\ 180/*-------------------------------------------------------------------------*\
181* Tries to connect to remote address (address, port) 181* Tries to connect to remote address (address, port)
182\*-------------------------------------------------------------------------*/ 182\*-------------------------------------------------------------------------*/
183const char *inet_tryconnect(p_sock ps, const char *address, 183const char *inet_tryconnect(p_sock ps, p_tm tm, const char *address,
184 unsigned short port, int timeout) 184 unsigned short port)
185{ 185{
186 struct sockaddr_in remote; 186 struct sockaddr_in remote;
187 const char *err; 187 int err;
188 memset(&remote, 0, sizeof(remote)); 188 memset(&remote, 0, sizeof(remote));
189 remote.sin_family = AF_INET; 189 remote.sin_family = AF_INET;
190 remote.sin_port = htons(port); 190 remote.sin_port = htons(port);
@@ -197,14 +197,14 @@ const char *inet_tryconnect(p_sock ps, const char *address,
197 memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr)); 197 memcpy(&remote.sin_addr, *addr, sizeof(struct in_addr));
198 } 198 }
199 } else remote.sin_family = AF_UNSPEC; 199 } else remote.sin_family = AF_UNSPEC;
200 err = sock_connect(ps, (SA *) &remote, sizeof(remote), timeout); 200 do err = sock_connect(ps, (SA *) &remote, sizeof(remote), tm_getretry(tm));
201 if (err) { 201 while (err == IO_RETRY && tm_getretry(tm));
202 if (err != IO_DONE) {
202 sock_destroy(ps); 203 sock_destroy(ps);
203 *ps = SOCK_INVALID; 204 *ps = SOCK_INVALID;
204 return err; 205 if (err == IO_ERROR) return sock_connectstrerror();
205 } else { 206 else return io_strerror(err);
206 return NULL; 207 } else return NULL;
207 }
208} 208}
209 209
210/*-------------------------------------------------------------------------*\ 210/*-------------------------------------------------------------------------*\
@@ -214,7 +214,6 @@ const char *inet_trybind(p_sock ps, const char *address, unsigned short port,
214 int backlog) 214 int backlog)
215{ 215{
216 struct sockaddr_in local; 216 struct sockaddr_in local;
217 const char *err;
218 memset(&local, 0, sizeof(local)); 217 memset(&local, 0, sizeof(local));
219 /* address is either wildcard or a valid ip address */ 218 /* address is either wildcard or a valid ip address */
220 local.sin_addr.s_addr = htonl(INADDR_ANY); 219 local.sin_addr.s_addr = htonl(INADDR_ANY);
@@ -229,11 +228,10 @@ const char *inet_trybind(p_sock ps, const char *address, unsigned short port,
229 memcpy(&local.sin_addr, *addr, sizeof(struct in_addr)); 228 memcpy(&local.sin_addr, *addr, sizeof(struct in_addr));
230 } 229 }
231 sock_setblocking(ps); 230 sock_setblocking(ps);
232 err = sock_bind(ps, (SA *) &local, sizeof(local)); 231 if (sock_bind(ps, (SA *) &local, sizeof(local)) != IO_DONE) {
233 if (err) {
234 sock_destroy(ps); 232 sock_destroy(ps);
235 *ps = SOCK_INVALID; 233 *ps = SOCK_INVALID;
236 return err; 234 return sock_bindstrerror();
237 } else { 235 } else {
238 sock_setnonblocking(ps); 236 sock_setnonblocking(ps);
239 if (backlog > 0) sock_listen(ps, backlog); 237 if (backlog > 0) sock_listen(ps, backlog);
@@ -246,7 +244,22 @@ const char *inet_trybind(p_sock ps, const char *address, unsigned short port,
246\*-------------------------------------------------------------------------*/ 244\*-------------------------------------------------------------------------*/
247const char *inet_trycreate(p_sock ps, int type) 245const char *inet_trycreate(p_sock ps, int type)
248{ 246{
249 return sock_create(ps, AF_INET, type, 0); 247 if (sock_create(ps, AF_INET, type, 0) == IO_DONE) return NULL;
248 else return sock_createstrerror();
249}
250
251/*-------------------------------------------------------------------------*\
252* Tries to accept an inet socket
253\*-------------------------------------------------------------------------*/
254const char *inet_tryaccept(p_sock ps, p_tm tm, p_sock pc)
255{
256 struct sockaddr_in addr;
257 socklen_t addr_len = sizeof(addr);
258 int err;
259 /* loop until connection accepted or timeout happens */
260 do err = sock_accept(ps, pc, (SA *) &addr, &addr_len, tm_getretry(tm));
261 while (err == IO_RETRY && tm_getretry(tm) != 0);
262 return io_strerror(err);
250} 263}
251 264
252/*-------------------------------------------------------------------------*\ 265/*-------------------------------------------------------------------------*\
diff --git a/src/inet.h b/src/inet.h
index 08979c1..ad52801 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -18,17 +18,21 @@
18\*=========================================================================*/ 18\*=========================================================================*/
19#include <lua.h> 19#include <lua.h>
20#include "socket.h" 20#include "socket.h"
21#include "timeout.h"
21 22
22#ifdef WIN32 23#ifdef WIN32
23#define INET_ATON 24#define INET_ATON
24#endif 25#endif
25 26
26void inet_open(lua_State *L); 27void inet_open(lua_State *L);
27const char *inet_tryconnect(p_sock ps, const char *address, 28
28 unsigned short port, int timeout); 29const char *inet_tryconnect(p_sock ps, p_tm tm, const char *address,
30 unsigned short port);
29const char *inet_trybind(p_sock ps, const char *address, 31const char *inet_trybind(p_sock ps, const char *address,
30 unsigned short port, int backlog); 32 unsigned short port, int backlog);
31const char *inet_trycreate(p_sock ps, int type); 33const char *inet_trycreate(p_sock ps, int type);
34const char *inet_tryaccept(p_sock ps, p_tm tm, p_sock pc);
35
32int inet_meth_getpeername(lua_State *L, p_sock ps); 36int inet_meth_getpeername(lua_State *L, p_sock ps);
33int inet_meth_getsockname(lua_State *L, p_sock ps); 37int inet_meth_getsockname(lua_State *L, p_sock ps);
34 38
diff --git a/src/io.c b/src/io.c
index 2d62147..612454b 100644
--- a/src/io.c
+++ b/src/io.c
@@ -22,27 +22,24 @@ void io_init(p_io io, p_send send, p_recv recv, void *ctx)
22/*-------------------------------------------------------------------------*\ 22/*-------------------------------------------------------------------------*\
23* Translate error codes to Lua 23* Translate error codes to Lua
24\*-------------------------------------------------------------------------*/ 24\*-------------------------------------------------------------------------*/
25void io_pusherror(lua_State *L, int code) 25const char *io_strerror(int code)
26{ 26{
27 switch (code) { 27 switch (code) {
28 case IO_DONE: 28 case IO_DONE: return NULL;
29 lua_pushnil(L); 29 case IO_TIMEOUT: return "timeout";
30 break; 30 case IO_RETRY: return "retry";
31 case IO_TIMEOUT: 31 case IO_CLOSED: return "closed";
32 lua_pushstring(L, "timeout"); 32 case IO_REFUSED: return "refused";
33 break; 33 default: return "unknown error";
34 case IO_LIMITED:
35 lua_pushstring(L, "limited");
36 break;
37 case IO_CLOSED:
38 lua_pushstring(L, "closed");
39 break;
40 case IO_REFUSED:
41 lua_pushstring(L, "refused");
42 break;
43 default:
44 lua_pushstring(L, "unknown error");
45 break;
46 } 34 }
47} 35}
48 36
37/*-------------------------------------------------------------------------*\
38* Translate error codes to Lua
39\*-------------------------------------------------------------------------*/
40void io_pusherror(lua_State *L, int code)
41{
42 const char *err = io_strerror(code);
43 if (err) lua_pushstring(L, err);
44 else lua_pushnil(L);
45}
diff --git a/src/io.h b/src/io.h
index 33675d8..495bdc6 100644
--- a/src/io.h
+++ b/src/io.h
@@ -20,12 +20,11 @@
20/* IO error codes */ 20/* IO error codes */
21enum { 21enum {
22 IO_DONE, /* operation completed successfully */ 22 IO_DONE, /* operation completed successfully */
23 IO_RETRY, /* please try again */
23 IO_TIMEOUT, /* operation timed out */ 24 IO_TIMEOUT, /* operation timed out */
24 IO_CLOSED, /* the connection has been closed */ 25 IO_CLOSED, /* the connection has been closed */
25 IO_ERROR, /* something wrong... */
26 IO_REFUSED, /* transfer has been refused */ 26 IO_REFUSED, /* transfer has been refused */
27 IO_RETRY, /* please try again */ 27 IO_ERROR /* something else wrong... */
28 IO_LIMITED /* maximum number of bytes reached */
29}; 28};
30 29
31/* interface to send function */ 30/* interface to send function */
@@ -54,6 +53,7 @@ typedef struct t_io_ {
54} t_io; 53} t_io;
55typedef t_io *p_io; 54typedef t_io *p_io;
56 55
56const char *io_strerror(int code);
57void io_pusherror(lua_State *L, int code); 57void io_pusherror(lua_State *L, int code);
58void io_init(p_io io, p_send send, p_recv recv, void *ctx); 58void io_init(p_io io, p_send send, p_recv recv, void *ctx);
59 59
diff --git a/src/socket.h b/src/socket.h
index aeadff0..739dedd 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -30,12 +30,12 @@ typedef struct sockaddr SA;
30* interface to sockets 30* interface to sockets
31\*=========================================================================*/ 31\*=========================================================================*/
32int sock_open(void); 32int sock_open(void);
33const char *sock_create(p_sock ps, int domain, int type, int protocol); 33int sock_create(p_sock ps, int domain, int type, int protocol);
34void sock_destroy(p_sock ps); 34void sock_destroy(p_sock ps);
35int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, 35int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
36 int timeout); 36 int timeout);
37const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout); 37int sock_connect(p_sock ps, SA *addr, socklen_t addr_len, int timeout);
38const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len); 38int sock_bind(p_sock ps, SA *addr, socklen_t addr_len);
39void sock_listen(p_sock ps, int backlog); 39void sock_listen(p_sock ps, int backlog);
40void sock_shutdown(p_sock ps, int how); 40void sock_shutdown(p_sock ps, int how);
41int sock_send(p_sock ps, const char *data, size_t count, 41int sock_send(p_sock ps, const char *data, size_t count,
@@ -48,6 +48,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count,
48 size_t *got, SA *addr, socklen_t *addr_len, int timeout); 48 size_t *got, SA *addr, socklen_t *addr_len, int timeout);
49void sock_setnonblocking(p_sock ps); 49void sock_setnonblocking(p_sock ps);
50void sock_setblocking(p_sock ps); 50void sock_setblocking(p_sock ps);
51
51const char *sock_hoststrerror(void); 52const char *sock_hoststrerror(void);
52const char *sock_createstrerror(void); 53const char *sock_createstrerror(void);
53const char *sock_bindstrerror(void); 54const char *sock_bindstrerror(void);
diff --git a/src/tcp.c b/src/tcp.c
index fe09e8c..74f32f4 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -63,7 +63,7 @@ static luaL_reg tcp[] = {
63static luaL_reg opt[] = { 63static luaL_reg opt[] = {
64 {"keepalive", opt_keepalive}, 64 {"keepalive", opt_keepalive},
65 {"reuseaddr", opt_reuseaddr}, 65 {"reuseaddr", opt_reuseaddr},
66 {"tcp-nodelay", opt_tcp_nodelay}, 66 {"tcp-nodelay", opt_tcp_nodelay},
67 {"linger", opt_linger}, 67 {"linger", opt_linger},
68 {NULL, NULL} 68 {NULL, NULL}
69}; 69};
@@ -200,32 +200,26 @@ static int meth_dirty(lua_State *L)
200\*-------------------------------------------------------------------------*/ 200\*-------------------------------------------------------------------------*/
201static int meth_accept(lua_State *L) 201static int meth_accept(lua_State *L)
202{ 202{
203 struct sockaddr_in addr;
204 socklen_t addr_len = sizeof(addr);
205 int err = IO_ERROR;
206 p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1); 203 p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1);
207 p_tm tm = &server->tm; 204 p_tm tm = &server->tm;
208 p_tcp client;
209 t_sock sock; 205 t_sock sock;
210 tm_markstart(tm); 206 tm_markstart(tm);
211 /* loop until connection accepted or timeout happens */ 207 const char *err = inet_tryaccept(&server->sock, tm, &sock);
212 while (err != IO_DONE) { 208 /* if successful, push client socket */
213 err = sock_accept(&server->sock, &sock, 209 if (!err) {
214 (SA *) &addr, &addr_len, tm_getfailure(tm)); 210 p_tcp clnt = lua_newuserdata(L, sizeof(t_tcp));
215 if (err == IO_CLOSED || (err == IO_TIMEOUT && !tm_getfailure(tm))) { 211 aux_setclass(L, "tcp{client}", -1);
216 lua_pushnil(L); 212 /* initialize structure fields */
217 io_pusherror(L, err); 213 clnt->sock = sock;
218 return 2; 214 io_init(&clnt->io, (p_send)sock_send, (p_recv)sock_recv, &clnt->sock);
219 } 215 tm_init(&clnt->tm, -1, -1);
216 buf_init(&clnt->buf, &clnt->io, &clnt->tm);
217 return 1;
218 } else {
219 lua_pushnil(L);
220 lua_pushstring(L, err);
221 return 2;
220 } 222 }
221 client = lua_newuserdata(L, sizeof(t_tcp));
222 aux_setclass(L, "tcp{client}", -1);
223 client->sock = sock;
224 /* initialize remaining structure fields */
225 io_init(&client->io, (p_send) sock_send, (p_recv) sock_recv, &client->sock);
226 tm_init(&client->tm, -1, -1);
227 buf_init(&client->buf, &client->io, &client->tm);
228 return 1;
229} 223}
230 224
231/*-------------------------------------------------------------------------*\ 225/*-------------------------------------------------------------------------*\
@@ -260,7 +254,7 @@ static int meth_connect(lua_State *L)
260 p_tm tm = &tcp->tm; 254 p_tm tm = &tcp->tm;
261 const char *err; 255 const char *err;
262 tm_markstart(tm); 256 tm_markstart(tm);
263 err = inet_tryconnect(&tcp->sock, address, port, tm_getfailure(tm)); 257 err = inet_tryconnect(&tcp->sock, tm, address, port);
264 if (err) { 258 if (err) {
265 lua_pushnil(L); 259 lua_pushnil(L);
266 lua_pushstring(L, err); 260 lua_pushstring(L, err);
@@ -283,7 +277,7 @@ static int meth_close(lua_State *L)
283} 277}
284 278
285/*-------------------------------------------------------------------------*\ 279/*-------------------------------------------------------------------------*\
286* Shuts the connection down 280* Shuts the connection down partially
287\*-------------------------------------------------------------------------*/ 281\*-------------------------------------------------------------------------*/
288static int meth_shutdown(lua_State *L) 282static int meth_shutdown(lua_State *L)
289{ 283{
@@ -341,22 +335,23 @@ static int meth_settimeout(lua_State *L)
341\*-------------------------------------------------------------------------*/ 335\*-------------------------------------------------------------------------*/
342int global_create(lua_State *L) 336int global_create(lua_State *L)
343{ 337{
344 const char *err; 338 t_sock sock;
345 /* allocate tcp object */ 339 const char *err = inet_trycreate(&sock, SOCK_STREAM);
346 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
347 /* set its type as master object */
348 aux_setclass(L, "tcp{master}", -1);
349 /* try to allocate a system socket */ 340 /* try to allocate a system socket */
350 err = inet_trycreate(&tcp->sock, SOCK_STREAM); 341 if (!err) {
351 if (err) { /* get rid of object on stack and push error */ 342 /* allocate tcp object */
352 lua_pop(L, 1); 343 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
344 tcp->sock = sock;
345 /* set its type as master object */
346 aux_setclass(L, "tcp{master}", -1);
347 /* initialize remaining structure fields */
348 io_init(&tcp->io, (p_send) sock_send, (p_recv) sock_recv, &tcp->sock);
349 tm_init(&tcp->tm, -1, -1);
350 buf_init(&tcp->buf, &tcp->io, &tcp->tm);
351 return 1;
352 } else {
353 lua_pushnil(L); 353 lua_pushnil(L);
354 lua_pushstring(L, err); 354 lua_pushstring(L, err);
355 return 2; 355 return 2;
356 } 356 }
357 /* initialize remaining structure fields */
358 io_init(&tcp->io, (p_send) sock_send, (p_recv) sock_recv, &tcp->sock);
359 tm_init(&tcp->tm, -1, -1);
360 buf_init(&tcp->buf, &tcp->io, &tcp->tm);
361 return 1;
362} 357}
diff --git a/src/timeout.c b/src/timeout.c
index 2d88ded..0063378 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -54,7 +54,7 @@ void tm_init(p_tm tm, int block, int total)
54* Returns 54* Returns
55* the number of ms left or -1 if there is no time limit 55* the number of ms left or -1 if there is no time limit
56\*-------------------------------------------------------------------------*/ 56\*-------------------------------------------------------------------------*/
57int tm_getsuccess(p_tm tm) 57int tm_get(p_tm tm)
58{ 58{
59 if (tm->block < 0 && tm->total < 0) { 59 if (tm->block < 0 && tm->total < 0) {
60 return -1; 60 return -1;
@@ -89,7 +89,7 @@ int tm_getstart(p_tm tm)
89* Returns 89* Returns
90* the number of ms left or -1 if there is no time limit 90* the number of ms left or -1 if there is no time limit
91\*-------------------------------------------------------------------------*/ 91\*-------------------------------------------------------------------------*/
92int tm_getfailure(p_tm tm) 92int tm_getretry(p_tm tm)
93{ 93{
94 if (tm->block < 0 && tm->total < 0) { 94 if (tm->block < 0 && tm->total < 0) {
95 return -1; 95 return -1;
diff --git a/src/timeout.h b/src/timeout.h
index 17f44ea..0a036f4 100644
--- a/src/timeout.h
+++ b/src/timeout.h
@@ -18,8 +18,8 @@ typedef t_tm *p_tm;
18 18
19void tm_open(lua_State *L); 19void tm_open(lua_State *L);
20void tm_init(p_tm tm, int block, int total); 20void tm_init(p_tm tm, int block, int total);
21int tm_getsuccess(p_tm tm); 21int tm_get(p_tm tm);
22int tm_getfailure(p_tm tm); 22int tm_getretry(p_tm tm);
23void tm_markstart(p_tm tm); 23void tm_markstart(p_tm tm);
24int tm_getstart(p_tm tm); 24int tm_getstart(p_tm tm);
25int tm_gettime(void); 25int tm_gettime(void);
diff --git a/src/udp.c b/src/udp.c
index eb2cea0..c730206 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -29,6 +29,7 @@ static int meth_getpeername(lua_State *L);
29static int meth_setsockname(lua_State *L); 29static int meth_setsockname(lua_State *L);
30static int meth_setpeername(lua_State *L); 30static int meth_setpeername(lua_State *L);
31static int meth_close(lua_State *L); 31static int meth_close(lua_State *L);
32static int meth_shutdown(lua_State *L);
32static int meth_setoption(lua_State *L); 33static int meth_setoption(lua_State *L);
33static int meth_settimeout(lua_State *L); 34static int meth_settimeout(lua_State *L);
34static int meth_fd(lua_State *L); 35static int meth_fd(lua_State *L);
@@ -53,6 +54,7 @@ static luaL_reg udp[] = {
53 {"receivefrom", meth_receivefrom}, 54 {"receivefrom", meth_receivefrom},
54 {"settimeout", meth_settimeout}, 55 {"settimeout", meth_settimeout},
55 {"close", meth_close}, 56 {"close", meth_close},
57 {"shutdown", meth_shutdown},
56 {"setoption", meth_setoption}, 58 {"setoption", meth_setoption},
57 {"__gc", meth_close}, 59 {"__gc", meth_close},
58 {"fd", meth_fd}, 60 {"fd", meth_fd},
@@ -110,7 +112,7 @@ static int meth_send(lua_State *L)
110 int err; 112 int err;
111 const char *data = luaL_checklstring(L, 2, &count); 113 const char *data = luaL_checklstring(L, 2, &count);
112 tm_markstart(tm); 114 tm_markstart(tm);
113 err = sock_send(&udp->sock, data, count, &sent, tm_getsuccess(tm)); 115 err = sock_send(&udp->sock, data, count, &sent, tm_get(tm));
114 if (err == IO_DONE) lua_pushnumber(L, sent); 116 if (err == IO_DONE) lua_pushnumber(L, sent);
115 else lua_pushnil(L); 117 else lua_pushnil(L);
116 /* a 'closed' error on an unconnected means the target address was not 118 /* a 'closed' error on an unconnected means the target address was not
@@ -139,7 +141,7 @@ static int meth_sendto(lua_State *L)
139 addr.sin_port = htons(port); 141 addr.sin_port = htons(port);
140 tm_markstart(tm); 142 tm_markstart(tm);
141 err = sock_sendto(&udp->sock, data, count, &sent, 143 err = sock_sendto(&udp->sock, data, count, &sent,
142 (SA *) &addr, sizeof(addr), tm_getsuccess(tm)); 144 (SA *) &addr, sizeof(addr), tm_get(tm));
143 if (err == IO_DONE) lua_pushnumber(L, sent); 145 if (err == IO_DONE) lua_pushnumber(L, sent);
144 else lua_pushnil(L); 146 else lua_pushnil(L);
145 /* a 'closed' error on an unconnected means the target address was not 147 /* a 'closed' error on an unconnected means the target address was not
@@ -160,7 +162,7 @@ static int meth_receive(lua_State *L)
160 p_tm tm = &udp->tm; 162 p_tm tm = &udp->tm;
161 count = MIN(count, sizeof(buffer)); 163 count = MIN(count, sizeof(buffer));
162 tm_markstart(tm); 164 tm_markstart(tm);
163 err = sock_recv(&udp->sock, buffer, count, &got, tm_getsuccess(tm)); 165 err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm));
164 if (err == IO_DONE) lua_pushlstring(L, buffer, got); 166 if (err == IO_DONE) lua_pushlstring(L, buffer, got);
165 else lua_pushnil(L); 167 else lua_pushnil(L);
166 io_pusherror(L, err); 168 io_pusherror(L, err);
@@ -182,7 +184,7 @@ static int meth_receivefrom(lua_State *L)
182 tm_markstart(tm); 184 tm_markstart(tm);
183 count = MIN(count, sizeof(buffer)); 185 count = MIN(count, sizeof(buffer));
184 err = sock_recvfrom(&udp->sock, buffer, count, &got, 186 err = sock_recvfrom(&udp->sock, buffer, count, &got,
185 (SA *) &addr, &addr_len, tm_getsuccess(tm)); 187 (SA *) &addr, &addr_len, tm_get(tm));
186 if (err == IO_DONE) { 188 if (err == IO_DONE) {
187 lua_pushlstring(L, buffer, got); 189 lua_pushlstring(L, buffer, got);
188 lua_pushstring(L, inet_ntoa(addr.sin_addr)); 190 lua_pushstring(L, inet_ntoa(addr.sin_addr));
@@ -341,8 +343,7 @@ static int meth_setpeername(lua_State *L)
341 unsigned short port = connecting ? 343 unsigned short port = connecting ?
342 (unsigned short) luaL_checknumber(L, 3) : 344 (unsigned short) luaL_checknumber(L, 3) :
343 (unsigned short) luaL_optnumber(L, 3, 0); 345 (unsigned short) luaL_optnumber(L, 3, 0);
344 const char *err; 346 const char *err = inet_tryconnect(&udp->sock, tm, address, port);
345 err = inet_tryconnect(&udp->sock, address, port, tm_getfailure(tm));
346 if (err) { 347 if (err) {
347 lua_pushnil(L); 348 lua_pushnil(L);
348 lua_pushstring(L, err); 349 lua_pushstring(L, err);
@@ -366,6 +367,33 @@ static int meth_close(lua_State *L)
366} 367}
367 368
368/*-------------------------------------------------------------------------*\ 369/*-------------------------------------------------------------------------*\
370* Shuts the connection down partially
371\*-------------------------------------------------------------------------*/
372static int meth_shutdown(lua_State *L)
373{
374 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
375 const char *how = luaL_optstring(L, 2, "both");
376 switch (how[0]) {
377 case 'b':
378 if (strcmp(how, "both")) goto error;
379 sock_shutdown(&udp->sock, 2);
380 break;
381 case 's':
382 if (strcmp(how, "send")) goto error;
383 sock_shutdown(&udp->sock, 1);
384 break;
385 case 'r':
386 if (strcmp(how, "receive")) goto error;
387 sock_shutdown(&udp->sock, 0);
388 break;
389 }
390 return 0;
391error:
392 luaL_argerror(L, 2, "invalid shutdown method");
393 return 0;
394}
395
396/*-------------------------------------------------------------------------*\
369* Turns a master object into a server object 397* Turns a master object into a server object
370\*-------------------------------------------------------------------------*/ 398\*-------------------------------------------------------------------------*/
371static int meth_setsockname(lua_State *L) 399static int meth_setsockname(lua_State *L)
@@ -391,21 +419,21 @@ static int meth_setsockname(lua_State *L)
391\*-------------------------------------------------------------------------*/ 419\*-------------------------------------------------------------------------*/
392int global_create(lua_State *L) 420int global_create(lua_State *L)
393{ 421{
394 const char *err; 422 t_sock sock;
395 /* allocate udp object */ 423 const char *err = inet_trycreate(&sock, SOCK_DGRAM);
396 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
397 /* set its type as master object */
398 aux_setclass(L, "udp{unconnected}", -1);
399 /* try to allocate a system socket */ 424 /* try to allocate a system socket */
400 err = inet_trycreate(&udp->sock, SOCK_DGRAM); 425 if (!err) {
401 if (err) { 426 /* allocate tcp object */
402 /* get rid of object on stack and push error */ 427 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
403 lua_pop(L, 1); 428 udp->sock = sock;
429 /* set its type as master object */
430 aux_setclass(L, "udp{unconnected}", -1);
431 /* initialize remaining structure fields */
432 tm_init(&udp->tm, -1, -1);
433 return 1;
434 } else {
404 lua_pushnil(L); 435 lua_pushnil(L);
405 lua_pushstring(L, err); 436 lua_pushstring(L, err);
406 return 2; 437 return 2;
407 } 438 }
408 /* initialize timeout management */
409 tm_init(&udp->tm, -1, -1);
410 return 1;
411} 439}
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;
diff --git a/test/httptest.lua b/test/httptest.lua
index 9d9fa25..d3a4dc0 100644
--- a/test/httptest.lua
+++ b/test/httptest.lua
@@ -314,9 +314,10 @@ body = socket.http.get {
314check(body == index) 314check(body == index)
315 315
316io.write("testing HEAD method: ") 316io.write("testing HEAD method: ")
317socket.http.TIMEOUT = 1
317response = socket.http.request { 318response = socket.http.request {
318 method = "HEAD", 319 method = "HEAD",
319 url = "http://www.tecgraf.puc-rio.br/~diego/" 320 url = "http://www.cs.princeton.edu/~diego/"
320} 321}
321check(response and response.headers) 322check(response and response.headers)
322 323
diff --git a/test/testclnt.lua b/test/testclnt.lua
index 6b07dca..3dea831 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -359,6 +359,7 @@ test_methods(socket.tcp(), {
359 "getsockname", 359 "getsockname",
360 "setoption", 360 "setoption",
361 "settimeout", 361 "settimeout",
362 "shutdown",
362 "close", 363 "close",
363}) 364})
364test_methods(socket.udp(), { 365test_methods(socket.udp(), {
@@ -372,6 +373,7 @@ test_methods(socket.udp(), {
372 "receivefrom", 373 "receivefrom",
373 "setoption", 374 "setoption",
374 "settimeout", 375 "settimeout",
376 "shutdown",
375 "close", 377 "close",
376}) 378})
377 379
@@ -484,6 +486,4 @@ test_blockingtimeoutreceive(800091, 3, 2)
484test_blockingtimeoutreceive(800091, 3, 1) 486test_blockingtimeoutreceive(800091, 3, 1)
485]] 487]]
486 488
487socket.done()
488
489test(string.format("done in %.2fs", socket.time() - start)) 489test(string.format("done in %.2fs", socket.time() - start))