aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2003-11-27 00:30:54 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2003-11-27 00:30:54 +0000
commit3febb302ad28fd25de51cbc686739469b92d8921 (patch)
tree0a8d9a1070a7c1f2566c22562693fb27963037d9
parent9bc4e0648ab4a177293a94425594bdc54c9a84fa (diff)
downloadluasocket-3febb302ad28fd25de51cbc686739469b92d8921.tar.gz
luasocket-3febb302ad28fd25de51cbc686739469b92d8921.tar.bz2
luasocket-3febb302ad28fd25de51cbc686739469b92d8921.zip
Killed a few bugs found by Tomas.
-rw-r--r--TODO12
-rw-r--r--src/buffer.c6
-rw-r--r--src/http.lua5
-rw-r--r--src/tcp.c22
-rw-r--r--src/timeout.c74
-rw-r--r--src/timeout.h7
-rw-r--r--src/udp.c8
-rw-r--r--src/usocket.c6
-rw-r--r--src/usocket.h5
-rw-r--r--src/wsocket.c6
10 files changed, 96 insertions, 55 deletions
diff --git a/TODO b/TODO
index ce3ee38..9fdb1e8 100644
--- a/TODO
+++ b/TODO
@@ -1,3 +1,15 @@
1replace times by getrusage
2
3make sure modules know if their dependencies are there.
4
5one thing i noticed in usocket.c is that it doesn't check for EINTR
6after write(), sendto(), read(), recvfrom() etc. ? the usual trick is
7to loop while you get EINTR:
8
9 do
10 ret = write(...);
11 while(ret < 0 && errno == EINTR)
12
1 13
2Read about 14Read about
3 15
diff --git a/src/buffer.c b/src/buffer.c
index c860f35..04419e7 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -138,7 +138,8 @@ 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, tm_get(tm)); 141 err = io->send(io->ctx, data+total, count-total, &done,
142 tm_getsuccess(tm));
142 total += done; 143 total += done;
143 } 144 }
144 *sent = total; 145 *sent = total;
@@ -239,7 +240,8 @@ int buf_get(p_buf buf, const char **data, size_t *count)
239 p_tm tm = buf->tm; 240 p_tm tm = buf->tm;
240 if (buf_isempty(buf)) { 241 if (buf_isempty(buf)) {
241 size_t got; 242 size_t got;
242 err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm_get(tm)); 243 err = io->recv(io->ctx, buf->data, BUF_SIZE, &got,
244 tm_getsuccess(tm));
243 buf->first = 0; 245 buf->first = 0;
244 buf->last = got; 246 buf->last = got;
245 } 247 }
diff --git a/src/http.lua b/src/http.lua
index 252285a..18a44b6 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -18,7 +18,7 @@ Public.TIMEOUT = 60
18-- default port for document retrieval 18-- default port for document retrieval
19Public.PORT = 80 19Public.PORT = 80
20-- user agent field sent in request 20-- user agent field sent in request
21Public.USERAGENT = "LuaSocket 1.5" 21Public.USERAGENT = "LuaSocket 2.0"
22-- block size used in transfers 22-- block size used in transfers
23Public.BLOCKSIZE = 8192 23Public.BLOCKSIZE = 8192
24 24
@@ -193,7 +193,8 @@ function Private.receivebody_bylength(sock, length, receive_cb)
193 while length > 0 do 193 while length > 0 do
194 local size = math.min(Public.BLOCKSIZE, length) 194 local size = math.min(Public.BLOCKSIZE, length)
195 local chunk, err = sock:receive(size) 195 local chunk, err = sock:receive(size)
196 if err then 196 -- if there was an error before we got all the data
197 if err and string.len(chunk) ~= length then
197 go, uerr = receive_cb(nil, err) 198 go, uerr = receive_cb(nil, err)
198 return uerr or err 199 return uerr or err
199 end 200 end
diff --git a/src/tcp.c b/src/tcp.c
index 098e29d..d68db08 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -198,21 +198,21 @@ static int meth_accept(lua_State *L)
198{ 198{
199 struct sockaddr_in addr; 199 struct sockaddr_in addr;
200 socklen_t addr_len = sizeof(addr); 200 socklen_t addr_len = sizeof(addr);
201 int err = IO_ERROR;
201 p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1); 202 p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1);
202 p_tm tm = &server->tm; 203 p_tm tm = &server->tm;
203 p_tcp client = lua_newuserdata(L, sizeof(t_tcp)); 204 p_tcp client = lua_newuserdata(L, sizeof(t_tcp));
204 tm_markstart(tm);
205 aux_setclass(L, "tcp{client}", -1); 205 aux_setclass(L, "tcp{client}", -1);
206 for ( ;; ) { 206 tm_markstart(tm);
207 sock_accept(&server->sock, &client->sock, 207 /* loop until connection accepted or timeout happens */
208 (SA *) &addr, &addr_len, tm_get(tm)); 208 while (err != IO_DONE) {
209 if (client->sock == SOCK_INVALID) { 209 err = sock_accept(&server->sock, &client->sock,
210 if (tm_get(tm) == 0) { 210 (SA *) &addr, &addr_len, tm_getfailure(tm));
211 lua_pushnil(L); 211 if (err == IO_CLOSED || (err == IO_TIMEOUT && !tm_getfailure(tm))) {
212 io_pusherror(L, IO_TIMEOUT); 212 lua_pushnil(L);
213 return 2; 213 io_pusherror(L, err);
214 } 214 return 2;
215 } else break; 215 }
216 } 216 }
217 /* initialize remaining structure fields */ 217 /* initialize remaining structure fields */
218 io_init(&client->io, (p_send) sock_send, (p_recv) sock_recv, &client->sock); 218 io_init(&client->io, (p_send) sock_send, (p_recv) sock_recv, &client->sock);
diff --git a/src/timeout.c b/src/timeout.c
index 38d1135..5d6de99 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -16,8 +16,8 @@
16#ifdef WIN32 16#ifdef WIN32
17#include <windows.h> 17#include <windows.h>
18#else 18#else
19#include <sys/time.h>
19#include <sys/times.h> 20#include <sys/times.h>
20#include <time.h>
21#include <unistd.h> 21#include <unistd.h>
22#endif 22#endif
23 23
@@ -46,40 +46,62 @@ void tm_init(p_tm tm, int block, int total)
46} 46}
47 47
48/*-------------------------------------------------------------------------*\ 48/*-------------------------------------------------------------------------*\
49* Set and get timeout limits 49* Determines how much time we have left for the next system call,
50* if the previous call was successful
51* Input
52* tm: timeout control structure
53* Returns
54* the number of ms left or -1 if there is no time limit
55\*-------------------------------------------------------------------------*/
56int tm_getsuccess(p_tm tm)
57{
58 if (tm->block < 0 && tm->total < 0) {
59 return -1;
60 } else if (tm->block < 0) {
61 int t = tm->total - tm_gettime() + tm->start;
62 return MAX(t, 0);
63 } else if (tm->total < 0) {
64 return tm->block;
65 } else {
66 int t = tm->total - tm_gettime() + tm->start;
67 return MIN(tm->block, MAX(t, 0));
68 }
69}
70
71/*-------------------------------------------------------------------------*\
72* Returns time since start of operation
73* Input
74* tm: timeout control structure
75* Returns
76* start field of structure
50\*-------------------------------------------------------------------------*/ 77\*-------------------------------------------------------------------------*/
51void tm_setblock(p_tm tm, int block)
52{ tm->block = block; }
53void tm_settotal(p_tm tm, int total)
54{ tm->total = total; }
55int tm_getblock(p_tm tm)
56{ return tm->block; }
57int tm_gettotal(p_tm tm)
58{ return tm->total; }
59int tm_getstart(p_tm tm) 78int tm_getstart(p_tm tm)
60{ return tm->start; } 79{
80 return tm->start;
81}
61 82
62/*-------------------------------------------------------------------------*\ 83/*-------------------------------------------------------------------------*\
63* Determines how much time we have left for the current operation 84* Determines how much time we have left for the next system call,
85* if the previous call was a failure
64* Input 86* Input
65* tm: timeout control structure 87* tm: timeout control structure
66* Returns 88* Returns
67* the number of ms left or -1 if there is no time limit 89* the number of ms left or -1 if there is no time limit
68\*-------------------------------------------------------------------------*/ 90\*-------------------------------------------------------------------------*/
69int tm_get(p_tm tm) 91int tm_getfailure(p_tm tm)
70{ 92{
71 /* no timeout */ 93 if (tm->block < 0 && tm->total < 0) {
72 if (tm->block < 0 && tm->total < 0)
73 return -1; 94 return -1;
74 /* there is no block timeout, we use the return timeout */ 95 } else if (tm->block < 0) {
75 else if (tm->block < 0) 96 int t = tm->total - tm_gettime() + tm->start;
76 return MAX(tm->total - tm_gettime() + tm->start, 0); 97 return MAX(t, 0);
77 /* there is no return timeout, we use the block timeout */ 98 } else if (tm->total < 0) {
78 else if (tm->total < 0) 99 int t = tm->block - tm_gettime() + tm->start;
79 return tm->block; 100 return MAX(t, 0);
80 /* both timeouts are specified */ 101 } else {
81 else return MIN(tm->block, 102 int t = tm->total - tm_gettime() + tm->start;
82 MAX(tm->total - tm_gettime() + tm->start, 0)); 103 return MIN(tm->block, MAX(t, 0));
104 }
83} 105}
84 106
85/*-------------------------------------------------------------------------*\ 107/*-------------------------------------------------------------------------*\
@@ -131,10 +153,10 @@ int tm_meth_settimeout(lua_State *L, p_tm tm)
131 const char *mode = luaL_optstring(L, 3, "b"); 153 const char *mode = luaL_optstring(L, 3, "b");
132 switch (*mode) { 154 switch (*mode) {
133 case 'b': 155 case 'b':
134 tm_setblock(tm, ms); 156 tm->block = ms;
135 break; 157 break;
136 case 'r': case 't': 158 case 'r': case 't':
137 tm_settotal(tm, ms); 159 tm->total = ms;
138 break; 160 break;
139 default: 161 default:
140 luaL_argcheck(L, 0, 3, "invalid timeout mode"); 162 luaL_argcheck(L, 0, 3, "invalid timeout mode");
diff --git a/src/timeout.h b/src/timeout.h
index ef2f533..17f44ea 100644
--- a/src/timeout.h
+++ b/src/timeout.h
@@ -18,13 +18,10 @@ 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);
21void tm_setblock(p_tm tm, int block); 21int tm_getsuccess(p_tm tm);
22void tm_settotal(p_tm tm, int total); 22int tm_getfailure(p_tm tm);
23int tm_getblock(p_tm tm);
24int tm_gettotal(p_tm tm);
25void tm_markstart(p_tm tm); 23void tm_markstart(p_tm tm);
26int tm_getstart(p_tm tm); 24int tm_getstart(p_tm tm);
27int tm_get(p_tm tm);
28int tm_gettime(void); 25int tm_gettime(void);
29int tm_meth_settimeout(lua_State *L, p_tm tm); 26int tm_meth_settimeout(lua_State *L, p_tm tm);
30 27
diff --git a/src/udp.c b/src/udp.c
index 6647711..58119cd 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -100,7 +100,7 @@ static int meth_send(lua_State *L)
100 int err; 100 int err;
101 const char *data = luaL_checklstring(L, 2, &count); 101 const char *data = luaL_checklstring(L, 2, &count);
102 tm_markstart(tm); 102 tm_markstart(tm);
103 err = sock_send(&udp->sock, data, count, &sent, tm_get(tm)); 103 err = sock_send(&udp->sock, data, count, &sent, tm_getsuccess(tm));
104 if (err == IO_DONE) lua_pushnumber(L, sent); 104 if (err == IO_DONE) lua_pushnumber(L, sent);
105 else lua_pushnil(L); 105 else lua_pushnil(L);
106 /* a 'closed' error on an unconnected means the target address was not 106 /* a 'closed' error on an unconnected means the target address was not
@@ -129,7 +129,7 @@ static int meth_sendto(lua_State *L)
129 addr.sin_port = htons(port); 129 addr.sin_port = htons(port);
130 tm_markstart(tm); 130 tm_markstart(tm);
131 err = sock_sendto(&udp->sock, data, count, &sent, 131 err = sock_sendto(&udp->sock, data, count, &sent,
132 (SA *) &addr, sizeof(addr), tm_get(tm)); 132 (SA *) &addr, sizeof(addr), tm_getsuccess(tm));
133 if (err == IO_DONE) lua_pushnumber(L, sent); 133 if (err == IO_DONE) lua_pushnumber(L, sent);
134 else lua_pushnil(L); 134 else lua_pushnil(L);
135 /* a 'closed' error on an unconnected means the target address was not 135 /* a 'closed' error on an unconnected means the target address was not
@@ -150,7 +150,7 @@ static int meth_receive(lua_State *L)
150 p_tm tm = &udp->tm; 150 p_tm tm = &udp->tm;
151 count = MIN(count, sizeof(buffer)); 151 count = MIN(count, sizeof(buffer));
152 tm_markstart(tm); 152 tm_markstart(tm);
153 err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm)); 153 err = sock_recv(&udp->sock, buffer, count, &got, tm_getsuccess(tm));
154 if (err == IO_DONE) lua_pushlstring(L, buffer, got); 154 if (err == IO_DONE) lua_pushlstring(L, buffer, got);
155 else lua_pushnil(L); 155 else lua_pushnil(L);
156 io_pusherror(L, err); 156 io_pusherror(L, err);
@@ -172,7 +172,7 @@ static int meth_receivefrom(lua_State *L)
172 tm_markstart(tm); 172 tm_markstart(tm);
173 count = MIN(count, sizeof(buffer)); 173 count = MIN(count, sizeof(buffer));
174 err = sock_recvfrom(&udp->sock, buffer, count, &got, 174 err = sock_recvfrom(&udp->sock, buffer, count, &got,
175 (SA *) &addr, &addr_len, tm_get(tm)); 175 (SA *) &addr, &addr_len, tm_getsuccess(tm));
176 if (err == IO_DONE) { 176 if (err == IO_DONE) {
177 lua_pushlstring(L, buffer, got); 177 lua_pushlstring(L, buffer, got);
178 lua_pushstring(L, inet_ntoa(addr.sin_addr)); 178 lua_pushstring(L, inet_ntoa(addr.sin_addr));
diff --git a/src/usocket.c b/src/usocket.c
index 202238b..b120d7b 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -83,10 +83,12 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
83 SA dummy_addr; 83 SA dummy_addr;
84 socklen_t dummy_len; 84 socklen_t dummy_len;
85 fd_set fds; 85 fd_set fds;
86 if (sock == SOCK_INVALID) return IO_CLOSED;
86 tv.tv_sec = timeout / 1000; 87 tv.tv_sec = timeout / 1000;
87 tv.tv_usec = (timeout % 1000) * 1000; 88 tv.tv_usec = (timeout % 1000) * 1000;
88 FD_ZERO(&fds); 89 FD_ZERO(&fds);
89 FD_SET(sock, &fds); 90 FD_SET(sock, &fds);
91 *pa = SOCK_INVALID;
90 if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) 92 if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0)
91 return IO_TIMEOUT; 93 return IO_TIMEOUT;
92 if (!addr) addr = &dummy_addr; 94 if (!addr) addr = &dummy_addr;
@@ -108,6 +110,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
108 ssize_t put = 0; 110 ssize_t put = 0;
109 int err; 111 int err;
110 int ret; 112 int ret;
113 if (sock == SOCK_INVALID) return IO_CLOSED;
111 tv.tv_sec = timeout / 1000; 114 tv.tv_sec = timeout / 1000;
112 tv.tv_usec = (timeout % 1000) * 1000; 115 tv.tv_usec = (timeout % 1000) * 1000;
113 FD_ZERO(&fds); 116 FD_ZERO(&fds);
@@ -145,6 +148,7 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
145 ssize_t put = 0; 148 ssize_t put = 0;
146 int err; 149 int err;
147 int ret; 150 int ret;
151 if (sock == SOCK_INVALID) return IO_CLOSED;
148 tv.tv_sec = timeout / 1000; 152 tv.tv_sec = timeout / 1000;
149 tv.tv_usec = (timeout % 1000) * 1000; 153 tv.tv_usec = (timeout % 1000) * 1000;
150 FD_ZERO(&fds); 154 FD_ZERO(&fds);
@@ -180,6 +184,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
180 fd_set fds; 184 fd_set fds;
181 int ret; 185 int ret;
182 ssize_t taken = 0; 186 ssize_t taken = 0;
187 if (sock == SOCK_INVALID) return IO_CLOSED;
183 tv.tv_sec = timeout / 1000; 188 tv.tv_sec = timeout / 1000;
184 tv.tv_usec = (timeout % 1000) * 1000; 189 tv.tv_usec = (timeout % 1000) * 1000;
185 FD_ZERO(&fds); 190 FD_ZERO(&fds);
@@ -210,6 +215,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
210 struct timeval tv; 215 struct timeval tv;
211 fd_set fds; 216 fd_set fds;
212 int ret; 217 int ret;
218 if (sock == SOCK_INVALID) return IO_CLOSED;
213 ssize_t taken = 0; 219 ssize_t taken = 0;
214 tv.tv_sec = timeout / 1000; 220 tv.tv_sec = timeout / 1000;
215 tv.tv_usec = (timeout % 1000) * 1000; 221 tv.tv_usec = (timeout % 1000) * 1000;
diff --git a/src/usocket.h b/src/usocket.h
index 85b7caa..b9255cb 100644
--- a/src/usocket.h
+++ b/src/usocket.h
@@ -34,11 +34,6 @@
34/* TCP options (nagle algorithm disable) */ 34/* TCP options (nagle algorithm disable) */
35#include <netinet/tcp.h> 35#include <netinet/tcp.h>
36 36
37#ifdef __APPLE__
38/* for some reason socklen_t is not defined in Mac Os X */
39typedef int socklen_t;
40#endif
41
42typedef int t_sock; 37typedef int t_sock;
43typedef t_sock *p_sock; 38typedef t_sock *p_sock;
44 39
diff --git a/src/wsocket.c b/src/wsocket.c
index f9e1084..1ba28b6 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -86,10 +86,12 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
86 SA dummy_addr; 86 SA dummy_addr;
87 socklen_t dummy_len; 87 socklen_t dummy_len;
88 fd_set fds; 88 fd_set fds;
89 if (sock == SOCK_INVALID) return IO_CLOSED;
89 tv.tv_sec = timeout / 1000; 90 tv.tv_sec = timeout / 1000;
90 tv.tv_usec = (timeout % 1000) * 1000; 91 tv.tv_usec = (timeout % 1000) * 1000;
91 FD_ZERO(&fds); 92 FD_ZERO(&fds);
92 FD_SET(sock, &fds); 93 FD_SET(sock, &fds);
94 *pa = SOCK_INVALID;
93 if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0) 95 if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0)
94 return IO_TIMEOUT; 96 return IO_TIMEOUT;
95 if (!addr) addr = &dummy_addr; 97 if (!addr) addr = &dummy_addr;
@@ -109,6 +111,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
109 struct timeval tv; 111 struct timeval tv;
110 fd_set fds; 112 fd_set fds;
111 ssize_t put = 0; 113 ssize_t put = 0;
114 if (sock == SOCK_INVALID) return IO_CLOSED;
112 int err; 115 int err;
113 int ret; 116 int ret;
114 tv.tv_sec = timeout / 1000; 117 tv.tv_sec = timeout / 1000;
@@ -148,6 +151,7 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
148 ssize_t put = 0; 151 ssize_t put = 0;
149 int err; 152 int err;
150 int ret; 153 int ret;
154 if (sock == SOCK_INVALID) return IO_CLOSED;
151 tv.tv_sec = timeout / 1000; 155 tv.tv_sec = timeout / 1000;
152 tv.tv_usec = (timeout % 1000) * 1000; 156 tv.tv_usec = (timeout % 1000) * 1000;
153 FD_ZERO(&fds); 157 FD_ZERO(&fds);
@@ -183,6 +187,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
183 fd_set fds; 187 fd_set fds;
184 int ret; 188 int ret;
185 ssize_t taken = 0; 189 ssize_t taken = 0;
190 if (sock == SOCK_INVALID) return IO_CLOSED;
186 tv.tv_sec = timeout / 1000; 191 tv.tv_sec = timeout / 1000;
187 tv.tv_usec = (timeout % 1000) * 1000; 192 tv.tv_usec = (timeout % 1000) * 1000;
188 FD_ZERO(&fds); 193 FD_ZERO(&fds);
@@ -214,6 +219,7 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
214 fd_set fds; 219 fd_set fds;
215 int ret; 220 int ret;
216 ssize_t taken = 0; 221 ssize_t taken = 0;
222 if (sock == SOCK_INVALID) return IO_CLOSED;
217 tv.tv_sec = timeout / 1000; 223 tv.tv_sec = timeout / 1000;
218 tv.tv_usec = (timeout % 1000) * 1000; 224 tv.tv_usec = (timeout % 1000) * 1000;
219 FD_ZERO(&fds); 225 FD_ZERO(&fds);