diff options
author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2001-01-15 04:16:35 +0000 |
---|---|---|
committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2001-01-15 04:16:35 +0000 |
commit | 84baa83864b4832844151aef694465ddf96c28f3 (patch) | |
tree | 6d9f528b6f1b90b6660467cca329b6dc6ebff299 /src | |
parent | b40d2ba005034c36c6b7f4439e6d6df1ef08d5e4 (diff) | |
download | luasocket-84baa83864b4832844151aef694465ddf96c28f3.tar.gz luasocket-84baa83864b4832844151aef694465ddf96c28f3.tar.bz2 luasocket-84baa83864b4832844151aef694465ddf96c28f3.zip |
The actuall bind to the Lua language has been rewritten with
generalized use of closure values. Sockets are now real tables,
where each method receives a p_sock structure as a closure.
Global version of methods are now optional, and call the table
versions.
Included the toip function that converts from host name to ip address.
new implementation of '*a' was broken as has been fixed.
The windows code has been tested and is working.
Diffstat (limited to 'src')
-rw-r--r-- | src/luasocket.c | 899 |
1 files changed, 442 insertions, 457 deletions
diff --git a/src/luasocket.c b/src/luasocket.c index 4f03ad2..e6f423c 100644 --- a/src/luasocket.c +++ b/src/luasocket.c | |||
@@ -104,17 +104,10 @@ | |||
104 | #define TM_SEND 2 | 104 | #define TM_SEND 2 |
105 | 105 | ||
106 | /*-------------------------------------------------------------------------*\ | 106 | /*-------------------------------------------------------------------------*\ |
107 | * As far as a Lua script is concerned, there are two kind of objects | 107 | * Each socket is represented by a table with the supported methods and |
108 | * representing a socket. A client socket is an object created by the | 108 | * the p_sock structure as fields. |
109 | * function connect, and implementing the methods send, receive, timeout | ||
110 | * and close. A server socket is an object created by the function bind, | ||
111 | * and implementing the methods listen, accept and close. Lua tag values | ||
112 | * for these objects are created in the lua_socketlibopen function, and | ||
113 | * passed as closure values (last argumnents to every library function) | ||
114 | # because we can't have any global variables. | ||
115 | \*-------------------------------------------------------------------------*/ | 109 | \*-------------------------------------------------------------------------*/ |
116 | #define CLIENT_TAG -2 | 110 | #define P_SOCK "(p_sock)sock" |
117 | #define SERVER_TAG -1 | ||
118 | 111 | ||
119 | /*-------------------------------------------------------------------------*\ | 112 | /*-------------------------------------------------------------------------*\ |
120 | * Both socket types are stored in the same structure to simplify | 113 | * Both socket types are stored in the same structure to simplify |
@@ -126,20 +119,28 @@ typedef struct t_sock { | |||
126 | SOCKET sock; | 119 | SOCKET sock; |
127 | /* start time of the current operation */ | 120 | /* start time of the current operation */ |
128 | int tm_start; | 121 | int tm_start; |
129 | #ifdef _DEBUG | ||
130 | /* end time of current operation, for debug purposes */ | ||
131 | int tm_end; | ||
132 | #endif | ||
133 | /* return and blocking timeout values (-1 if no limit) */ | 122 | /* return and blocking timeout values (-1 if no limit) */ |
134 | int tm_return, tm_block; | 123 | int tm_return, tm_block; |
135 | /* buffered I/O storage */ | 124 | /* buffered I/O storage */ |
136 | unsigned char bf_buffer[LUASOCKET_BUFFERSIZE]; | 125 | unsigned char bf_buffer[LUASOCKET_BUFFERSIZE]; |
137 | /* first and last red bytes not yet passed to application */ | 126 | /* first and last red bytes not yet passed to application */ |
138 | int bf_first, bf_last; | 127 | int bf_first, bf_last; |
128 | #ifdef _DEBUG | ||
129 | /* end time of current operation, for debug purposes */ | ||
130 | int tm_end; | ||
131 | #endif | ||
139 | } t_sock; | 132 | } t_sock; |
140 | typedef t_sock *p_sock; | 133 | typedef t_sock *p_sock; |
141 | 134 | ||
142 | /*-------------------------------------------------------------------------*\ | 135 | /*-------------------------------------------------------------------------*\ |
136 | * Tags passed as closure values to global LuaSocket API functions | ||
137 | \*-------------------------------------------------------------------------*/ | ||
138 | typedef struct t_tags { | ||
139 | int client, server, table; | ||
140 | } t_tags; | ||
141 | typedef t_tags *p_tags; | ||
142 | |||
143 | /*-------------------------------------------------------------------------*\ | ||
143 | * Macros and internal declarations | 144 | * Macros and internal declarations |
144 | \*-------------------------------------------------------------------------*/ | 145 | \*-------------------------------------------------------------------------*/ |
145 | /* min and max macros */ | 146 | /* min and max macros */ |
@@ -154,14 +155,24 @@ typedef t_sock *p_sock; | |||
154 | * Internal function prototypes | 155 | * Internal function prototypes |
155 | \*=========================================================================*/ | 156 | \*=========================================================================*/ |
156 | /* luasocket API functions */ | 157 | /* luasocket API functions */ |
157 | static int net_connect(lua_State *L); | 158 | static int global_connect(lua_State *L); |
158 | static int net_bind(lua_State *L); | 159 | static int global_bind(lua_State *L); |
159 | static int net_listen(lua_State *L); | 160 | static int table_listen(lua_State *L); |
160 | static int net_accept(lua_State *L); | 161 | static int table_accept(lua_State *L); |
161 | static int net_send(lua_State *L); | 162 | static int table_send(lua_State *L); |
162 | static int net_receive(lua_State *L); | 163 | static int table_receive(lua_State *L); |
163 | static int net_timeout(lua_State *L); | 164 | static int table_timeout(lua_State *L); |
164 | static int net_close(lua_State *L); | 165 | static int table_close(lua_State *L); |
166 | #ifndef LUASOCKET_NOGLOBALS | ||
167 | static int global_listen(lua_State *L); | ||
168 | static int global_accept(lua_State *L); | ||
169 | static int global_send(lua_State *L); | ||
170 | static int global_receive(lua_State *L); | ||
171 | static int global_timeout(lua_State *L); | ||
172 | static int global_close(lua_State *L); | ||
173 | static p_sock get_selfclientsock(lua_State *L, p_tags tags); | ||
174 | static p_sock get_selfserversock(lua_State *L, p_tags tags); | ||
175 | #endif | ||
165 | 176 | ||
166 | /* buffered I/O management */ | 177 | /* buffered I/O management */ |
167 | static const unsigned char *bf_receive(p_sock sock, int *length); | 178 | static const unsigned char *bf_receive(p_sock sock, int *length); |
@@ -181,18 +192,14 @@ static int receive_dosline(lua_State *L, p_sock sock); | |||
181 | static int receive_unixline(lua_State *L, p_sock sock); | 192 | static int receive_unixline(lua_State *L, p_sock sock); |
182 | static int receive_all(lua_State *L, p_sock sock); | 193 | static int receive_all(lua_State *L, p_sock sock); |
183 | 194 | ||
184 | /* fallbacks */ | 195 | /* parameter manipulation functions */ |
185 | static int server_gettable(lua_State *L); | 196 | static p_tags pop_tags(lua_State *L); |
186 | static int client_gettable(lua_State *L); | 197 | static p_sock pop_sock(lua_State *L); |
187 | static int sock_gc(lua_State *L); | 198 | static p_sock get_selfsock(lua_State *L, p_tags tags); |
188 | 199 | static int gc_sock(lua_State *L); | |
189 | /* argument checking routines */ | 200 | static p_sock push_servertable(lua_State *L, p_tags tags); |
190 | static p_sock check_client(lua_State *L, int numArg, int client_tag); | 201 | static p_sock push_clienttable(lua_State *L, p_tags tags); |
191 | static p_sock check_server(lua_State *L, int numArg, int server_tag); | 202 | static void push_error(lua_State *L, int err); |
192 | static p_sock check_sock(lua_State *L, int numArg, int server_tag, | ||
193 | int client_tag); | ||
194 | static void pop_tags(lua_State *L, int *client_tag, int *server_tag); | ||
195 | static void push_tags(lua_State *L, int client_tag, int server_tag); | ||
196 | 203 | ||
197 | /* error code translations functions */ | 204 | /* error code translations functions */ |
198 | static char *host_strerror(void); | 205 | static char *host_strerror(void); |
@@ -200,20 +207,17 @@ static char *bind_strerror(void); | |||
200 | static char *sock_strerror(void); | 207 | static char *sock_strerror(void); |
201 | static char *connect_strerror(void); | 208 | static char *connect_strerror(void); |
202 | 209 | ||
203 | static void push_error(lua_State *L, int err); | 210 | /* auxiliary functions */ |
204 | static void push_client(lua_State *L, p_sock sock, int client_tag); | ||
205 | static void push_server(lua_State *L, p_sock sock, int server_tag); | ||
206 | |||
207 | /* plataform specific functions */ | ||
208 | static void set_blocking(p_sock sock); | 211 | static void set_blocking(p_sock sock); |
209 | static void set_nonblocking(p_sock sock); | 212 | static void set_nonblocking(p_sock sock); |
210 | 213 | static int create_tcpsocket(p_sock sock); | |
211 | /* auxiliary functions */ | ||
212 | static p_sock create_sock(void); | ||
213 | static p_sock create_tcpsock(void); | ||
214 | static int fill_sockaddr(struct sockaddr_in *server, const char *hostname, | 214 | static int fill_sockaddr(struct sockaddr_in *server, const char *hostname, |
215 | unsigned short port); | 215 | unsigned short port); |
216 | 216 | ||
217 | #ifdef WIN32 | ||
218 | static int winsock_open(void); | ||
219 | #endif | ||
220 | |||
217 | /*=========================================================================*\ | 221 | /*=========================================================================*\ |
218 | * Test support functions | 222 | * Test support functions |
219 | \*=========================================================================*/ | 223 | \*=========================================================================*/ |
@@ -221,8 +225,8 @@ static int fill_sockaddr(struct sockaddr_in *server, const char *hostname, | |||
221 | /*-------------------------------------------------------------------------*\ | 225 | /*-------------------------------------------------------------------------*\ |
222 | * Returns the time the system has been up, in secconds. | 226 | * Returns the time the system has been up, in secconds. |
223 | \*-------------------------------------------------------------------------*/ | 227 | \*-------------------------------------------------------------------------*/ |
224 | static int net_time(lua_State *L); | 228 | static int global_time(lua_State *L); |
225 | static int net_time(lua_State *L) | 229 | static int global_time(lua_State *L) |
226 | { | 230 | { |
227 | lua_pushnumber(L, tm_gettime()/1000.0); | 231 | lua_pushnumber(L, tm_gettime()/1000.0); |
228 | return 1; | 232 | return 1; |
@@ -231,8 +235,8 @@ static int net_time(lua_State *L) | |||
231 | /*-------------------------------------------------------------------------*\ | 235 | /*-------------------------------------------------------------------------*\ |
232 | * Causes a Lua script to sleep for the specified number of secconds | 236 | * Causes a Lua script to sleep for the specified number of secconds |
233 | \*-------------------------------------------------------------------------*/ | 237 | \*-------------------------------------------------------------------------*/ |
234 | static int net_sleep(lua_State *L); | 238 | static int global_sleep(lua_State *L); |
235 | static int net_sleep(lua_State *L) | 239 | static int global_sleep(lua_State *L) |
236 | { | 240 | { |
237 | int sec = (int) luaL_check_number(L, 1); | 241 | int sec = (int) luaL_check_number(L, 1); |
238 | #ifdef WIN32 | 242 | #ifdef WIN32 |
@@ -253,65 +257,87 @@ static int net_sleep(lua_State *L) | |||
253 | * Creates a client socket and returns it to the Lua script. The timeout | 257 | * Creates a client socket and returns it to the Lua script. The timeout |
254 | * values are initialized as -1 so that the socket will block at any | 258 | * values are initialized as -1 so that the socket will block at any |
255 | * IO operation. | 259 | * IO operation. |
256 | * Input | 260 | * Lua Input |
257 | * host: host name or ip address to connect to | 261 | * host: host name or ip address to connect to |
258 | * port: port number on host | 262 | * port: port number on host |
259 | * Returns | 263 | * Lua Returns |
260 | * On success: client socket | 264 | * On success: client socket |
261 | * On error: nil, followed by an error message | 265 | * On error: nil, followed by an error message |
262 | \*-------------------------------------------------------------------------*/ | 266 | \*-------------------------------------------------------------------------*/ |
263 | static int net_connect(lua_State *L) | 267 | static int global_connect(lua_State *L) |
264 | { | 268 | { |
269 | p_tags tags = pop_tags(L); | ||
265 | const char *hostname = luaL_check_string(L, 1); | 270 | const char *hostname = luaL_check_string(L, 1); |
266 | unsigned short port = (unsigned short) luaL_check_number(L, 2); | 271 | unsigned short port = (unsigned short) luaL_check_number(L, 2); |
267 | int client_tag, server_tag; | ||
268 | struct sockaddr_in server; | 272 | struct sockaddr_in server; |
269 | p_sock sock; | 273 | p_sock sock = push_clienttable(L, tags); |
270 | pop_tags(L, &client_tag, &server_tag); | ||
271 | sock = create_tcpsock(); | ||
272 | if (!sock) { | 274 | if (!sock) { |
273 | lua_pushnil(L); | 275 | lua_pushnil(L); |
276 | lua_pushstring(L, "out of memory"); | ||
277 | return 2; | ||
278 | } | ||
279 | if (!create_tcpsocket(sock)) { | ||
280 | lua_pushnil(L); | ||
274 | lua_pushstring(L, sock_strerror()); | 281 | lua_pushstring(L, sock_strerror()); |
275 | return 2; | 282 | return 2; |
276 | } | 283 | } |
277 | /* fills the sockaddr structure with the information needed to | 284 | /* fills the sockaddr structure with the information needed to |
278 | ** connect our socket with the remote host */ | 285 | ** connect our socket with the remote host */ |
279 | if (!fill_sockaddr(&server, hostname, port)) { | 286 | if (!fill_sockaddr(&server, hostname, port)) { |
280 | free(sock); | ||
281 | lua_pushnil(L); | 287 | lua_pushnil(L); |
282 | lua_pushstring(L, host_strerror()); | 288 | lua_pushstring(L, host_strerror()); |
283 | return 2; | 289 | return 2; |
284 | } | 290 | } |
285 | if (connect(sock->sock,(struct sockaddr *)&server,sizeof(server)) < 0) { | 291 | if (connect(sock->sock, (struct sockaddr *)&server, sizeof(server)) < 0) { |
286 | /* no connection? we close the socket to free the descriptor */ | 292 | /* no connection? we close the socket to free the descriptor */ |
287 | closesocket(sock->sock); | 293 | closesocket(sock->sock); |
288 | lua_pushnil(L); | 294 | lua_pushnil(L); |
289 | lua_pushstring(L, connect_strerror()); | 295 | lua_pushstring(L, connect_strerror()); |
290 | return 2; | 296 | return 2; |
291 | } | 297 | } |
298 | /* all operations on client sockets are non-blocking */ | ||
292 | set_nonblocking(sock); | 299 | set_nonblocking(sock); |
293 | push_client(L, sock, client_tag); | ||
294 | lua_pushnil(L); | 300 | lua_pushnil(L); |
295 | return 2; | 301 | return 2; |
296 | } | 302 | } |
297 | 303 | ||
298 | /*-------------------------------------------------------------------------*\ | 304 | /*-------------------------------------------------------------------------*\ |
305 | * Converts from ip number to host name | ||
306 | * Lua Input | ||
307 | * ip: ip number | ||
308 | * Lua Returns | ||
309 | * On success: domain name | ||
310 | * On error: nil, followed by an error message | ||
311 | \*-------------------------------------------------------------------------*/ | ||
312 | static int global_toip(lua_State *L) | ||
313 | { | ||
314 | struct hostent *host; | ||
315 | struct in_addr addr; | ||
316 | pop_tags(L); | ||
317 | host = gethostbyname(luaL_check_string(L, 1)); | ||
318 | if (!host) { | ||
319 | lua_pushnil(L); | ||
320 | lua_pushstring(L, host_strerror()); | ||
321 | return 2; | ||
322 | } | ||
323 | memcpy(&addr, host->h_addr, (unsigned) host->h_length); | ||
324 | lua_pushstring(L, inet_ntoa(addr)); | ||
325 | return 1; | ||
326 | } | ||
327 | |||
328 | /*-------------------------------------------------------------------------*\ | ||
299 | * Specifies the number of connections that can be queued on a server | 329 | * Specifies the number of connections that can be queued on a server |
300 | * socket. | 330 | * socket. |
301 | * Input | 331 | * Lua Input |
302 | * sock: server socket created by the bind function | 332 | * sock: server socket created by the bind function |
303 | * Returns | 333 | * Lua Returns |
304 | * On success: nil | 334 | * On success: nil |
305 | * On error: an error message | 335 | * On error: an error message |
306 | \*-------------------------------------------------------------------------*/ | 336 | \*-------------------------------------------------------------------------*/ |
307 | static int net_listen(lua_State *L) | 337 | static int table_listen(lua_State *L) |
308 | { | 338 | { |
309 | p_sock sock; | 339 | p_sock sock = pop_sock(L); |
310 | int client_tag, server_tag; | 340 | unsigned int backlog = (unsigned int) luaL_check_number(L, 2); |
311 | unsigned int backlog; | ||
312 | pop_tags(L, &client_tag, &server_tag); | ||
313 | sock = check_server(L, 1, server_tag); | ||
314 | backlog = (unsigned int) luaL_check_number(L, 2); | ||
315 | if (listen(sock->sock, backlog) < 0) { | 341 | if (listen(sock->sock, backlog) < 0) { |
316 | lua_pushstring(L, "listen error"); | 342 | lua_pushstring(L, "listen error"); |
317 | return 1; | 343 | return 1; |
@@ -324,39 +350,25 @@ static int net_listen(lua_State *L) | |||
324 | /*-------------------------------------------------------------------------*\ | 350 | /*-------------------------------------------------------------------------*\ |
325 | * Returns a client socket attempting to connect to a server socket. | 351 | * Returns a client socket attempting to connect to a server socket. |
326 | * The function blocks until a client shows up. | 352 | * The function blocks until a client shows up. |
327 | * Input | 353 | * Lua Input |
328 | * sock: server socket created by the bind function | 354 | * sock: server socket created by the bind function |
329 | * Returns | 355 | * Lua Returns |
330 | * On success: client socket attempting connection | 356 | * On success: client socket attempting connection |
331 | * On error: nil followed by an error message | 357 | * On error: nil followed by an error message |
332 | \*-------------------------------------------------------------------------*/ | 358 | \*-------------------------------------------------------------------------*/ |
333 | static int net_accept(lua_State *L) | 359 | static int table_accept(lua_State *L) |
334 | { | 360 | { |
335 | struct sockaddr_in client_addr; | 361 | struct sockaddr_in client_addr; |
336 | int client_tag, server_tag; | ||
337 | p_sock server; | ||
338 | int client_sock = -1; | ||
339 | size_t client_len = sizeof(client_addr); | 362 | size_t client_len = sizeof(client_addr); |
340 | p_sock client; | 363 | p_sock server = pop_sock(L); |
341 | pop_tags(L, &client_tag, &server_tag); | 364 | p_tags tags = pop_tags(L); |
342 | server = check_server(L, 1, server_tag); | 365 | p_sock client = push_clienttable(L, tags); |
343 | /* waits for a connection */ | 366 | SOCKET accepted = accept(server->sock, (struct sockaddr *) &client_addr, |
344 | client_sock = accept(server->sock, (struct sockaddr *) &client_addr, | ||
345 | &client_len); | 367 | &client_len); |
346 | /* we create and return a client socket object, passing the received | 368 | client->sock = accepted; |
347 | ** socket to Lua, as a client socket */ | 369 | set_nonblocking(client); |
348 | client = create_sock(); | 370 | lua_pushnil(L); |
349 | if (!client) { | 371 | return 2; |
350 | lua_pushnil(L); | ||
351 | lua_pushstring(L, "out of memory"); | ||
352 | return 2; | ||
353 | } else { | ||
354 | client->sock = client_sock; | ||
355 | set_nonblocking(client); | ||
356 | push_client(L, client, client_tag); | ||
357 | lua_pushnil(L); | ||
358 | return 2; | ||
359 | } | ||
360 | } | 372 | } |
361 | 373 | ||
362 | /*-------------------------------------------------------------------------*\ | 374 | /*-------------------------------------------------------------------------*\ |
@@ -370,16 +382,15 @@ static int net_accept(lua_State *L) | |||
370 | * On success: server socket bound to address, the ip address and port bound | 382 | * On success: server socket bound to address, the ip address and port bound |
371 | * On error: nil, followed by an error message | 383 | * On error: nil, followed by an error message |
372 | \*-------------------------------------------------------------------------*/ | 384 | \*-------------------------------------------------------------------------*/ |
373 | static int net_bind(lua_State *L) | 385 | static int global_bind(lua_State *L) |
374 | { | 386 | { |
387 | p_tags tags = pop_tags(L); | ||
375 | const char *hostname = luaL_check_string(L, 1); | 388 | const char *hostname = luaL_check_string(L, 1); |
376 | unsigned short port = (unsigned short) luaL_check_number(L, 2); | 389 | unsigned short port = (unsigned short) luaL_check_number(L, 2); |
377 | unsigned int backlog = (unsigned int) luaL_opt_number(L, 3, 1.0); | 390 | unsigned int backlog = (unsigned int) luaL_opt_number(L, 3, 1.0); |
378 | struct sockaddr_in server; | 391 | struct sockaddr_in server; |
379 | size_t server_size = sizeof(server); | 392 | size_t server_size = sizeof(server); |
380 | int client_tag, server_tag; | 393 | p_sock sock = push_servertable(L, tags); |
381 | p_sock sock = create_tcpsock(); | ||
382 | pop_tags(L, &client_tag, &server_tag); | ||
383 | if (!sock) { | 394 | if (!sock) { |
384 | lua_pushnil(L); | 395 | lua_pushnil(L); |
385 | lua_pushstring(L, sock_strerror()); | 396 | lua_pushstring(L, sock_strerror()); |
@@ -406,8 +417,6 @@ static int net_bind(lua_State *L) | |||
406 | } | 417 | } |
407 | /* pass the created socket to Lua, as a server socket */ | 418 | /* pass the created socket to Lua, as a server socket */ |
408 | else { | 419 | else { |
409 | /* pass server */ | ||
410 | push_server(L, sock, server_tag); | ||
411 | /* get used address and port */ | 420 | /* get used address and port */ |
412 | getsockname(sock->sock, (struct sockaddr *)&server, &server_size); | 421 | getsockname(sock->sock, (struct sockaddr *)&server, &server_size); |
413 | /* pass ip number */ | 422 | /* pass ip number */ |
@@ -421,26 +430,19 @@ static int net_bind(lua_State *L) | |||
421 | 430 | ||
422 | /*-------------------------------------------------------------------------*\ | 431 | /*-------------------------------------------------------------------------*\ |
423 | * Sets timeout values for IO operations on a client socket | 432 | * Sets timeout values for IO operations on a client socket |
424 | * Input | 433 | * Lua Input |
425 | * sock: client socket created by the connect function | 434 | * sock: client socket created by the connect function |
426 | * time: time out value in seconds | 435 | * time: time out value in seconds |
427 | * mode: optional timeout mode. "block" specifies the upper bound on | 436 | * mode: optional timeout mode. "block" specifies the upper bound on |
428 | * the time any IO operation on sock can cause the program to block. | 437 | * the time any IO operation on sock can cause the program to block. |
429 | * "return" specifies the upper bound on the time elapsed before the | 438 | * "return" specifies the upper bound on the time elapsed before the |
430 | * function returns control to the script. "block" is the default. | 439 | * function returns control to the script. "block" is the default. |
431 | * Returns | ||
432 | * no return value | ||
433 | \*-------------------------------------------------------------------------*/ | 440 | \*-------------------------------------------------------------------------*/ |
434 | static int net_timeout(lua_State *L) | 441 | static int table_timeout(lua_State *L) |
435 | { | 442 | { |
436 | int client_tag, server_tag; | 443 | p_sock sock = pop_sock(L); |
437 | p_sock sock; | 444 | int ms = (int) (luaL_check_number(L, 2)*1000.0); |
438 | int ms; | 445 | const char *mode = luaL_opt_string(L, 3, "b"); |
439 | const char *mode; | ||
440 | pop_tags(L, &client_tag, &server_tag); | ||
441 | sock = check_client(L, 1, client_tag); | ||
442 | ms = (int) (luaL_check_number(L, 2)*1000.0); | ||
443 | mode = luaL_opt_string(L, 3, "b"); | ||
444 | switch (*mode) { | 446 | switch (*mode) { |
445 | case 'b': | 447 | case 'b': |
446 | sock->tm_block = ms; | 448 | sock->tm_block = ms; |
@@ -457,34 +459,30 @@ static int net_timeout(lua_State *L) | |||
457 | 459 | ||
458 | /*-------------------------------------------------------------------------*\ | 460 | /*-------------------------------------------------------------------------*\ |
459 | * Send data through a socket | 461 | * Send data through a socket |
460 | * Input: sock, a_1 [, a_2, a_3 ... a_n] | 462 | * Lua Input: sock, a_1 [, a_2, a_3 ... a_n] |
461 | * sock: client socket created by the connect function | 463 | * sock: client socket created by the connect function |
462 | * a_i: strings to be sent. The strings will be sent on the order they | 464 | * a_i: strings to be sent. The strings will be sent on the order they |
463 | * appear as parameters | 465 | * appear as parameters |
464 | * Returns | 466 | * Lua Returns |
465 | * On success: nil, followed by the total number of bytes sent | 467 | * On success: nil, followed by the total number of bytes sent |
466 | * On error: NET_TIMEOUT if the connection timedout, or NET_CLOSED if | 468 | * On error: NET_TIMEOUT if the connection timedout, or NET_CLOSED if |
467 | * the connection has been closed, followed by the total number of | 469 | * the connection has been closed, followed by the total number of |
468 | * bytes sent | 470 | * bytes sent |
469 | \*-------------------------------------------------------------------------*/ | 471 | \*-------------------------------------------------------------------------*/ |
470 | static int net_send(lua_State *L) | 472 | static int table_send(lua_State *L) |
471 | { | 473 | { |
472 | p_sock sock; | ||
473 | const char *data; | ||
474 | int wanted; | ||
475 | long total = 0; | ||
476 | int arg; | 474 | int arg; |
475 | p_sock sock = pop_sock(L); | ||
476 | int top = lua_gettop(L); | ||
477 | int total = 0; | ||
477 | int err = NET_DONE; | 478 | int err = NET_DONE; |
478 | int top; | ||
479 | int client_tag, server_tag; | ||
480 | pop_tags(L, &client_tag, &server_tag); | ||
481 | top = lua_gettop(L); | ||
482 | sock = check_client(L, 1, client_tag); | ||
483 | tm_markstart(sock); | 479 | tm_markstart(sock); |
484 | for (arg = 2; arg <= top; arg++) { | 480 | for (arg = 2; arg <= top; arg++) { /* skip self table */ |
485 | data = luaL_opt_lstr(L, arg, NULL, &wanted); | 481 | int sent, wanted; |
482 | const char *data = luaL_opt_lstr(L, arg, NULL, &wanted); | ||
486 | if (!data || err != NET_DONE) break; | 483 | if (!data || err != NET_DONE) break; |
487 | total += send_raw(sock, data, wanted, &err); | 484 | err = send_raw(sock, data, wanted, &sent); |
485 | total += sent; | ||
488 | } | 486 | } |
489 | push_error(L, err); | 487 | push_error(L, err); |
490 | lua_pushnumber(L, (double) total); | 488 | lua_pushnumber(L, (double) total); |
@@ -497,7 +495,7 @@ static int net_send(lua_State *L) | |||
497 | 495 | ||
498 | /*-------------------------------------------------------------------------*\ | 496 | /*-------------------------------------------------------------------------*\ |
499 | * Receive data from a socket | 497 | * Receive data from a socket |
500 | * Input: sock [pat_1, pat_2 ... pat_n] | 498 | * Lua Input: sock [pat_1, pat_2 ... pat_n] |
501 | * sock: client socket created by the connect function | 499 | * sock: client socket created by the connect function |
502 | * pat_i: may be one of the following | 500 | * pat_i: may be one of the following |
503 | * "*l": reads a text line, defined as a string of caracters terminates | 501 | * "*l": reads a text line, defined as a string of caracters terminates |
@@ -506,24 +504,21 @@ static int net_send(lua_State *L) | |||
506 | * "*lu": reads a text line, terminanted by a CR character only. (Unix mode) | 504 | * "*lu": reads a text line, terminanted by a CR character only. (Unix mode) |
507 | * "*a": reads until connection closed | 505 | * "*a": reads until connection closed |
508 | * number: reads 'number' characters from the socket | 506 | * number: reads 'number' characters from the socket |
509 | * Returns | 507 | * Lua Returns |
510 | * On success: one string for each pattern | 508 | * On success: one string for each pattern |
511 | * On error: all strings for which there was no error, followed by one | 509 | * On error: all strings for which there was no error, followed by one |
512 | * nil value for the remaining strings, followed by an error code | 510 | * nil value for the remaining strings, followed by an error code |
513 | \*-------------------------------------------------------------------------*/ | 511 | \*-------------------------------------------------------------------------*/ |
514 | static int net_receive(lua_State *L) | 512 | static int table_receive(lua_State *L) |
515 | { | 513 | { |
516 | static const char *const modenames[] = {"*l", "*lu", "*a", NULL}; | 514 | static const char *const modenames[] = {"*l", "*lu", "*a", NULL}; |
517 | int err = NET_DONE, arg = 2; | ||
518 | const char *mode; | 515 | const char *mode; |
519 | int client_tag, server_tag; | 516 | int err = NET_DONE; |
520 | int top; | 517 | int arg; |
521 | p_sock sock; | 518 | p_sock sock = pop_sock(L); |
522 | pop_tags(L, &client_tag, &server_tag); | 519 | int top = lua_gettop(L); |
523 | sock = check_client(L, 1, client_tag); | ||
524 | tm_markstart(sock); | 520 | tm_markstart(sock); |
525 | /* push default pattern */ | 521 | /* push default pattern if need be */ |
526 | top = lua_gettop(L); | ||
527 | if (top < 2) { | 522 | if (top < 2) { |
528 | lua_pushstring(L, "*l"); | 523 | lua_pushstring(L, "*l"); |
529 | top++; | 524 | top++; |
@@ -536,7 +531,7 @@ static int net_receive(lua_State *L) | |||
536 | continue; | 531 | continue; |
537 | } | 532 | } |
538 | if (lua_isnumber(L, arg)) { | 533 | if (lua_isnumber(L, arg)) { |
539 | long size = (long) lua_tonumber(L, arg); | 534 | int size = (int) lua_tonumber(L, arg); |
540 | err = receive_raw(L, sock, size); | 535 | err = receive_raw(L, sock, size); |
541 | } else { | 536 | } else { |
542 | mode = luaL_opt_string(L, arg, NULL); | 537 | mode = luaL_opt_string(L, arg, NULL); |
@@ -572,104 +567,30 @@ static int net_receive(lua_State *L) | |||
572 | 567 | ||
573 | /*-------------------------------------------------------------------------*\ | 568 | /*-------------------------------------------------------------------------*\ |
574 | * Closes a socket. | 569 | * Closes a socket. |
575 | * Input | 570 | * Lua Input |
576 | * sock: socket to be closed | 571 | * sock: socket to be closed |
577 | \*-------------------------------------------------------------------------*/ | 572 | \*-------------------------------------------------------------------------*/ |
578 | static int net_close(lua_State *L) | 573 | static int table_close(lua_State *L) |
579 | { | 574 | { |
580 | int client_tag, server_tag; | 575 | /* close socket and set value to -1 so that pop_socket can later |
581 | p_sock sock; | 576 | ** detect the use of a closed socket */ |
582 | pop_tags(L, &client_tag, &server_tag); | 577 | p_sock sock = pop_sock(L); |
583 | sock = check_sock(L, 1, client_tag, server_tag); | ||
584 | closesocket(sock->sock); | 578 | closesocket(sock->sock); |
585 | /* set value to -1 so that we can later detect the use of a | ||
586 | ** closed socket */ | ||
587 | sock->sock = -1; | 579 | sock->sock = -1; |
588 | return 0; | 580 | return 0; |
589 | } | 581 | } |
590 | 582 | ||
591 | /*-------------------------------------------------------------------------*\ | 583 | /*-------------------------------------------------------------------------*\ |
592 | * Gettable fallback for the client socket. This function provides the | ||
593 | * alternative interface client:receive, client:send etc for the client | ||
594 | * socket methods. | ||
595 | \*-------------------------------------------------------------------------*/ | ||
596 | static int client_gettable(lua_State *L) | ||
597 | { | ||
598 | static const char *const net_api[] = | ||
599 | {"receive","send","timeout","close", "connect", NULL}; | ||
600 | const char *idx = luaL_check_string(L, 2); | ||
601 | int server_tag, client_tag; | ||
602 | pop_tags(L, &client_tag, &server_tag); | ||
603 | switch (luaL_findstring(idx, net_api)) { | ||
604 | case 0: | ||
605 | push_tags(L, client_tag, server_tag); | ||
606 | lua_pushcclosure(L, net_receive, 2); | ||
607 | break; | ||
608 | case 1: | ||
609 | push_tags(L, client_tag, server_tag); | ||
610 | lua_pushcclosure(L, net_send, 2); | ||
611 | break; | ||
612 | case 2: | ||
613 | push_tags(L, client_tag, server_tag); | ||
614 | lua_pushcclosure(L, net_timeout, 2); | ||
615 | break; | ||
616 | case 3: | ||
617 | push_tags(L, client_tag, server_tag); | ||
618 | lua_pushcclosure(L, net_close, 2); | ||
619 | break; | ||
620 | default: | ||
621 | lua_pushnil(L); | ||
622 | break; | ||
623 | } | ||
624 | return 1; | ||
625 | } | ||
626 | |||
627 | /*-------------------------------------------------------------------------*\ | ||
628 | * Gettable fallback for the server socket. This function provides the | ||
629 | * alternative interface server:listen, server:accept etc for the server | ||
630 | * socket methods. | ||
631 | \*-------------------------------------------------------------------------*/ | ||
632 | static int server_gettable(lua_State *L) | ||
633 | { | ||
634 | static const char *const net_api[] = {"listen","accept","close", NULL}; | ||
635 | const char *idx = luaL_check_string(L, 2); | ||
636 | int server_tag, client_tag; | ||
637 | pop_tags(L, &client_tag, &server_tag); | ||
638 | switch (luaL_findstring(idx, net_api)) { | ||
639 | case 0: | ||
640 | push_tags(L, client_tag, server_tag); | ||
641 | lua_pushcclosure(L, net_listen, 2); | ||
642 | break; | ||
643 | case 1: | ||
644 | push_tags(L, client_tag, server_tag); | ||
645 | lua_pushcclosure(L, net_accept, 2); | ||
646 | break; | ||
647 | case 2: | ||
648 | push_tags(L, client_tag, server_tag); | ||
649 | lua_pushcclosure(L, net_close, 2); | ||
650 | break; | ||
651 | default: | ||
652 | lua_pushnil(L); | ||
653 | break; | ||
654 | } | ||
655 | return 1; | ||
656 | } | ||
657 | |||
658 | /*-------------------------------------------------------------------------*\ | ||
659 | * Garbage collection fallback for the socket objects. This function | 584 | * Garbage collection fallback for the socket objects. This function |
660 | * makes sure that all collected sockets are closed and that the memory | 585 | * makes sure that all collected sockets are closed. |
661 | * used by the C structure t_sock is properly released. | ||
662 | \*-------------------------------------------------------------------------*/ | 586 | \*-------------------------------------------------------------------------*/ |
663 | static int sock_gc(lua_State *L) | 587 | static int gc_sock(lua_State *L) |
664 | { | 588 | { |
665 | int server_tag, client_tag; | 589 | p_tags tags = pop_tags(L); |
666 | p_sock sock; | 590 | p_sock sock = get_selfsock(L, tags); |
667 | pop_tags(L, &client_tag, &server_tag); | 591 | /* sock might have been closed */ |
668 | sock = check_sock(L, 1, client_tag, server_tag); | 592 | if (sock->sock >= 0) closesocket(sock->sock); |
669 | if (sock->sock >= 0) | 593 | return 0; |
670 | closesocket(sock->sock); | ||
671 | free(sock); | ||
672 | return 1; | ||
673 | } | 594 | } |
674 | 595 | ||
675 | /*=========================================================================*\ | 596 | /*=========================================================================*\ |
@@ -692,34 +613,16 @@ static void handle_sigpipe(void) | |||
692 | #endif | 613 | #endif |
693 | 614 | ||
694 | /*-------------------------------------------------------------------------*\ | 615 | /*-------------------------------------------------------------------------*\ |
695 | * Creates a t_sock structure with default values. | ||
696 | \*-------------------------------------------------------------------------*/ | ||
697 | static p_sock create_sock(void) | ||
698 | { | ||
699 | p_sock sock = (p_sock) malloc(sizeof(t_sock)); | ||
700 | if (!sock) return NULL; | ||
701 | sock->sock = -1; | ||
702 | sock->tm_block = -1; | ||
703 | sock->tm_return = -1; | ||
704 | sock->bf_first = sock->bf_last = 0; | ||
705 | return sock; | ||
706 | } | ||
707 | |||
708 | /*-------------------------------------------------------------------------*\ | ||
709 | * Creates a TCP/IP socket. | 616 | * Creates a TCP/IP socket. |
617 | * Input | ||
618 | * sock: structure to receive new socket | ||
710 | * Returns | 619 | * Returns |
711 | * A pointer to a t_sock structure or NULL in case of error | 620 | * 1 if successfull, 0 in case or error |
712 | \*-------------------------------------------------------------------------*/ | 621 | \*-------------------------------------------------------------------------*/ |
713 | static p_sock create_tcpsock(void) | 622 | static int create_tcpsocket(p_sock sock) |
714 | { | 623 | { |
715 | p_sock sock = create_sock(); | ||
716 | if (!sock) | ||
717 | return NULL; | ||
718 | sock->sock = socket(AF_INET, SOCK_STREAM, 0); | 624 | sock->sock = socket(AF_INET, SOCK_STREAM, 0); |
719 | if (sock->sock < 0) { | 625 | if (sock->sock < 0) return 0; |
720 | free(sock); | ||
721 | sock = NULL; | ||
722 | } | ||
723 | #ifdef _DEBUG | 626 | #ifdef _DEBUG |
724 | /* this allow us to re-bind onto an address even if there is still | 627 | /* this allow us to re-bind onto an address even if there is still |
725 | ** a TIME_WAIT condition. debugging is much more confortable, because | 628 | ** a TIME_WAIT condition. debugging is much more confortable, because |
@@ -733,7 +636,7 @@ static p_sock create_tcpsock(void) | |||
733 | sizeof(val)); | 636 | sizeof(val)); |
734 | } | 637 | } |
735 | #endif | 638 | #endif |
736 | return sock; | 639 | return 1; |
737 | } | 640 | } |
738 | 641 | ||
739 | /*-------------------------------------------------------------------------*\ | 642 | /*-------------------------------------------------------------------------*\ |
@@ -756,10 +659,8 @@ static int fill_sockaddr(struct sockaddr_in *address, const char *hostname, | |||
756 | /* BSD says we could have used gethostbyname even if the hostname is | 659 | /* BSD says we could have used gethostbyname even if the hostname is |
757 | ** in ip address form, but WinSock2 says we can't. Therefore we | 660 | ** in ip address form, but WinSock2 says we can't. Therefore we |
758 | ** choose a method that works on both plataforms */ | 661 | ** choose a method that works on both plataforms */ |
759 | if (addr == INADDR_NONE) | 662 | if (addr == INADDR_NONE) host = gethostbyname(hostname); |
760 | host = gethostbyname(hostname); | 663 | else host = gethostbyaddr((char * ) &addr, sizeof(unsigned long), |
761 | else | ||
762 | host = gethostbyaddr((char * ) &addr, sizeof(unsigned long), | ||
763 | AF_INET); | 664 | AF_INET); |
764 | if (!host) | 665 | if (!host) |
765 | return 0; | 666 | return 0; |
@@ -773,6 +674,87 @@ static int fill_sockaddr(struct sockaddr_in *address, const char *hostname, | |||
773 | } | 674 | } |
774 | 675 | ||
775 | /*-------------------------------------------------------------------------*\ | 676 | /*-------------------------------------------------------------------------*\ |
677 | * Creates a t_sock structure with default values for a client sock. | ||
678 | * Pushes the Lua table with sock fields and appropriate methods | ||
679 | * Input | ||
680 | * tags: tags structure | ||
681 | * Returns | ||
682 | * pointer to allocated t_sock structure, NULL in case of error | ||
683 | \*-------------------------------------------------------------------------*/ | ||
684 | static p_sock push_clienttable(lua_State *L, p_tags tags) | ||
685 | { | ||
686 | static struct luaL_reg funcs[] = { | ||
687 | {"send", table_send}, | ||
688 | {"receive", table_receive}, | ||
689 | {"close", table_close}, | ||
690 | {"timeout", table_timeout}, | ||
691 | }; | ||
692 | int i; | ||
693 | p_sock sock; | ||
694 | lua_newtable(L); lua_settag(L, tags->table); | ||
695 | lua_pushstring(L, P_SOCK); | ||
696 | sock = (p_sock) lua_newuserdata(L, sizeof(t_sock)); | ||
697 | if (!sock) lua_error(L, "out of memory"); | ||
698 | lua_settag(L, tags->client); | ||
699 | lua_settable(L, -3); | ||
700 | sock->sock = -1; | ||
701 | sock->tm_block = -1; | ||
702 | sock->tm_return = -1; | ||
703 | sock->bf_first = sock->bf_last = 0; | ||
704 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
705 | lua_pushstring(L, funcs[i].name); | ||
706 | lua_pushusertag(L, sock, tags->client); | ||
707 | lua_pushcclosure(L, funcs[i].func, 1); | ||
708 | lua_settable(L, -3); | ||
709 | } | ||
710 | return sock; | ||
711 | } | ||
712 | |||
713 | /*-------------------------------------------------------------------------*\ | ||
714 | * Creates a t_sock structure with default values for a server sock. | ||
715 | * Pushes the Lua table with sock fields and appropriate methods | ||
716 | * Input | ||
717 | * tags: tags structure | ||
718 | * Returns | ||
719 | * pointer to allocated t_sock structure, NULL in case of error | ||
720 | \*-------------------------------------------------------------------------*/ | ||
721 | static p_sock push_servertable(lua_State *L, p_tags tags) | ||
722 | { | ||
723 | static struct luaL_reg funcs[] = { | ||
724 | {"listen", table_listen}, | ||
725 | {"close", table_close}, | ||
726 | }; | ||
727 | int i; | ||
728 | p_sock sock; | ||
729 | lua_newtable(L); lua_settag(L, tags->table); | ||
730 | lua_pushstring(L, P_SOCK); | ||
731 | sock = (p_sock) lua_newuserdata(L, sizeof(t_sock)); | ||
732 | if (!sock) lua_error(L, "out of memory"); | ||
733 | lua_settag(L, tags->server); | ||
734 | lua_settable(L, -3); | ||
735 | if (!create_tcpsocket(sock)) return NULL; | ||
736 | sock->tm_block = -1; | ||
737 | sock->tm_return = -1; | ||
738 | sock->bf_first = sock->bf_last = 0; | ||
739 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
740 | lua_pushstring(L, funcs[i].name); | ||
741 | lua_pushusertag(L, sock, tags->client); | ||
742 | lua_pushcclosure(L, funcs[i].func, 1); | ||
743 | lua_settable(L, -3); | ||
744 | } | ||
745 | /* the accept method is different, it needs the tags closure too */ | ||
746 | lua_pushstring(L, "accept"); | ||
747 | lua_pushuserdata(L, tags); | ||
748 | lua_pushusertag(L, sock, tags->client); | ||
749 | lua_pushcclosure(L, table_accept, 2); | ||
750 | lua_settable(L, -3); | ||
751 | return sock; | ||
752 | } | ||
753 | |||
754 | /*=========================================================================*\ | ||
755 | * Timeout management functions | ||
756 | \*=========================================================================*/ | ||
757 | /*-------------------------------------------------------------------------*\ | ||
776 | * Determines how much time we have left for the current io operation | 758 | * Determines how much time we have left for the current io operation |
777 | * an IO write operation. | 759 | * an IO write operation. |
778 | * Input | 760 | * Input |
@@ -827,7 +809,7 @@ static int tm_timedout(p_sock sock, int mode) | |||
827 | /* see if we can read or write or if we timedout */ | 809 | /* see if we can read or write or if we timedout */ |
828 | ret = select(sock->sock+1, preadfds, pwritefds, NULL, ptm); | 810 | ret = select(sock->sock+1, preadfds, pwritefds, NULL, ptm); |
829 | #ifdef _DEBUG | 811 | #ifdef _DEBUG |
830 | /* store end time for this operation before calling select */ | 812 | /* store end time for this operation next call to OS */ |
831 | sock->tm_end = tm_gettime(); | 813 | sock->tm_end = tm_gettime(); |
832 | #endif | 814 | #endif |
833 | return ret <= 0; | 815 | return ret <= 0; |
@@ -847,6 +829,24 @@ static void tm_markstart(p_sock sock) | |||
847 | } | 829 | } |
848 | 830 | ||
849 | /*-------------------------------------------------------------------------*\ | 831 | /*-------------------------------------------------------------------------*\ |
832 | * Gets time in ms, relative to system startup. | ||
833 | * Returns | ||
834 | * time in ms. | ||
835 | \*-------------------------------------------------------------------------*/ | ||
836 | static int tm_gettime(void) | ||
837 | { | ||
838 | #ifdef _WIN32 | ||
839 | return GetTickCount(); | ||
840 | #else | ||
841 | struct tms t; | ||
842 | return (times(&t)*1000)/CLK_TCK; | ||
843 | #endif | ||
844 | } | ||
845 | |||
846 | /*=========================================================================*\ | ||
847 | * Buffered I/O management functions | ||
848 | \*=========================================================================*/ | ||
849 | /*-------------------------------------------------------------------------*\ | ||
850 | * Determines of there is any data in the read buffer | 850 | * Determines of there is any data in the read buffer |
851 | * Input | 851 | * Input |
852 | * sock: socket structure being used in operation | 852 | * sock: socket structure being used in operation |
@@ -892,21 +892,9 @@ static const unsigned char *bf_receive(p_sock sock, int *length) | |||
892 | return sock->bf_buffer + sock->bf_first; | 892 | return sock->bf_buffer + sock->bf_first; |
893 | } | 893 | } |
894 | 894 | ||
895 | /*-------------------------------------------------------------------------*\ | 895 | /*=========================================================================*\ |
896 | * Gets time in ms, relative to system startup. | 896 | * These are the function that are called for each I/O pattern |
897 | * Returns | 897 | \*=========================================================================*/ |
898 | * time in ms. | ||
899 | \*-------------------------------------------------------------------------*/ | ||
900 | static int tm_gettime(void) | ||
901 | { | ||
902 | #ifdef _WIN32 | ||
903 | return GetTickCount(); | ||
904 | #else | ||
905 | struct tms t; | ||
906 | return (times(&t)*1000)/CLK_TCK; | ||
907 | #endif | ||
908 | } | ||
909 | |||
910 | /*-------------------------------------------------------------------------*\ | 898 | /*-------------------------------------------------------------------------*\ |
911 | * Sends a raw block of data through a socket. The operations are all | 899 | * Sends a raw block of data through a socket. The operations are all |
912 | * non-blocking and the function respects the timeout values in sock. | 900 | * non-blocking and the function respects the timeout values in sock. |
@@ -915,29 +903,32 @@ static int tm_gettime(void) | |||
915 | * data: buffer to be sent | 903 | * data: buffer to be sent |
916 | * wanted: number of bytes in buffer | 904 | * wanted: number of bytes in buffer |
917 | * Output | 905 | * Output |
918 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | 906 | * total: Number of bytes written |
919 | * Returns | 907 | * Returns |
920 | * Number of bytes written | 908 | * operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED |
921 | \*-------------------------------------------------------------------------*/ | 909 | \*-------------------------------------------------------------------------*/ |
922 | static int send_raw(p_sock sock, const char *data, int wanted, int *err) | 910 | static int send_raw(p_sock sock, const char *data, int wanted, int *total) |
923 | { | 911 | { |
924 | int put = 0, total = 0; | 912 | int put = 0; |
913 | *total = 0; | ||
925 | while (wanted > 0) { | 914 | while (wanted > 0) { |
926 | if (tm_timedout(sock, TM_SEND)) { | 915 | if (tm_timedout(sock, TM_SEND)) return NET_TIMEOUT; |
927 | *err = NET_TIMEOUT; | ||
928 | return total; | ||
929 | } | ||
930 | put = send(sock->sock, data, wanted, 0); | 916 | put = send(sock->sock, data, wanted, 0); |
931 | if (put <= 0) { | 917 | if (put <= 0) { |
932 | *err = NET_CLOSED; | 918 | #ifdef WIN32 |
933 | return total; | 919 | /* a bug in WinSock forces us to do a busy wait until we manage |
920 | ** to write, because select returns immediately even though it | ||
921 | ** should have blocked us */ | ||
922 | if (WSAGetLastError() == WSAEWOULDBLOCK) | ||
923 | continue; | ||
924 | #endif | ||
925 | return NET_CLOSED; | ||
934 | } | 926 | } |
935 | wanted -= put; | 927 | wanted -= put; |
936 | data += put; | 928 | data += put; |
937 | total += put; | 929 | *total += put; |
938 | } | 930 | } |
939 | *err = NET_DONE; | 931 | return NET_DONE; |
940 | return total; | ||
941 | } | 932 | } |
942 | 933 | ||
943 | /*-------------------------------------------------------------------------*\ | 934 | /*-------------------------------------------------------------------------*\ |
@@ -989,16 +980,16 @@ static int receive_all(lua_State *L, p_sock sock) | |||
989 | luaL_buffinit(L, &b); | 980 | luaL_buffinit(L, &b); |
990 | for ( ;; ) { | 981 | for ( ;; ) { |
991 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { | 982 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { |
992 | buffer = bf_receive(sock, &got); | ||
993 | if (got <= 0) { | ||
994 | luaL_pushresult(&b); | ||
995 | return NET_DONE; | ||
996 | } | ||
997 | luaL_addlstring(&b, buffer, got); | ||
998 | } else { | ||
999 | luaL_pushresult(&b); | 983 | luaL_pushresult(&b); |
1000 | return NET_TIMEOUT; | 984 | return NET_TIMEOUT; |
985 | } | ||
986 | buffer = bf_receive(sock, &got); | ||
987 | if (got <= 0) { | ||
988 | luaL_pushresult(&b); | ||
989 | return NET_DONE; | ||
1001 | } | 990 | } |
991 | luaL_addlstring(&b, buffer, got); | ||
992 | bf_skip(sock, got); | ||
1002 | } | 993 | } |
1003 | } | 994 | } |
1004 | 995 | ||
@@ -1088,18 +1079,125 @@ static int receive_unixline(lua_State *L, p_sock sock) | |||
1088 | } | 1079 | } |
1089 | } | 1080 | } |
1090 | 1081 | ||
1082 | /*=========================================================================*\ | ||
1083 | * Module exported functions | ||
1084 | \*=========================================================================*/ | ||
1091 | /*-------------------------------------------------------------------------*\ | 1085 | /*-------------------------------------------------------------------------*\ |
1092 | * Pops tags from closures | 1086 | * Initializes the library interface with Lua and the socket library. |
1093 | * Input | 1087 | * Defines the symbols exported to Lua. |
1094 | * L: lua environment | ||
1095 | \*-------------------------------------------------------------------------*/ | 1088 | \*-------------------------------------------------------------------------*/ |
1096 | static void pop_tags(lua_State *L, int *client_tag, int *server_tag) | 1089 | void lua_socketlibopen(lua_State *L) |
1097 | { | 1090 | { |
1098 | *client_tag = (int) lua_tonumber(L, CLIENT_TAG); | 1091 | static struct luaL_reg funcs[] = { |
1099 | *server_tag = (int) lua_tonumber(L, SERVER_TAG); | 1092 | {"connect", global_connect}, |
1100 | lua_pop(L, 2); | 1093 | {"bind", global_bind}, |
1094 | {"toip", global_toip}, | ||
1095 | }; | ||
1096 | int i; | ||
1097 | /* declare new Lua tags for used userdata values */ | ||
1098 | p_tags tags = (p_tags) lua_newuserdata(L, sizeof(t_tags)); | ||
1099 | if (!tags) lua_error(L, "out of memory"); | ||
1100 | tags->client = lua_newtag(L); | ||
1101 | tags->server = lua_newtag(L); | ||
1102 | tags->table = lua_newtag(L); | ||
1103 | /* global functions exported */ | ||
1104 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
1105 | lua_pushuserdata(L, tags); | ||
1106 | lua_pushcclosure(L, funcs[i].func, 1); | ||
1107 | lua_setglobal(L, funcs[i].name); | ||
1108 | } | ||
1109 | /* socket garbage collection */ | ||
1110 | lua_pushuserdata(L, tags); | ||
1111 | lua_pushcclosure(L, gc_sock, 1); | ||
1112 | lua_settagmethod(L, tags->table, "gc"); | ||
1113 | |||
1114 | #ifndef LUASOCKET_NOGLOBALS | ||
1115 | /* global version of socket table functions */ | ||
1116 | { static struct luaL_reg opt_funcs[] = { | ||
1117 | {"send", global_send}, | ||
1118 | {"receive", global_receive}, | ||
1119 | {"accept", global_accept}, | ||
1120 | {"close", global_close}, | ||
1121 | {"timeout", global_timeout}, | ||
1122 | {"listen", global_listen}, | ||
1123 | }; | ||
1124 | for (i = 0; i < sizeof(opt_funcs)/sizeof(opt_funcs[0]); i++) { | ||
1125 | lua_pushuserdata(L, tags); | ||
1126 | lua_pushcclosure(L, opt_funcs[i].func, 1); | ||
1127 | lua_setglobal(L, opt_funcs[i].name); | ||
1128 | } | ||
1129 | } | ||
1130 | #endif | ||
1131 | #ifdef WIN32 | ||
1132 | /* WinSock needs special initialization */ | ||
1133 | winsock_open(); | ||
1134 | #else | ||
1135 | /* avoid getting killed by a SIGPIPE signal thrown by send */ | ||
1136 | handle_sigpipe(); | ||
1137 | #endif | ||
1138 | #ifdef _DEBUG | ||
1139 | /* test support functions */ | ||
1140 | lua_pushcfunction(L, global_sleep); lua_setglobal(L, "sleep"); | ||
1141 | lua_pushcfunction(L, global_time); lua_setglobal(L, "time"); | ||
1142 | #endif | ||
1143 | /* avoid stupid compiler warnings */ | ||
1144 | (void) set_blocking; | ||
1145 | } | ||
1146 | |||
1147 | /*=========================================================================*\ | ||
1148 | * Optional global version of socket table methods | ||
1149 | \*=========================================================================*/ | ||
1150 | #ifndef LUASOCKET_NOGLOBALS | ||
1151 | int global_accept(lua_State *L) | ||
1152 | { | ||
1153 | p_tags tags = pop_tags(L); | ||
1154 | p_sock sock = get_selfserversock(L, tags); | ||
1155 | lua_pushuserdata(L, tags); | ||
1156 | lua_pushusertag(L, sock, tags->server); | ||
1157 | return table_accept(L); | ||
1101 | } | 1158 | } |
1102 | 1159 | ||
1160 | int global_listen(lua_State *L) | ||
1161 | { | ||
1162 | p_tags tags = pop_tags(L); | ||
1163 | p_sock sock = get_selfserversock(L, tags); | ||
1164 | lua_pushusertag(L, sock, tags->server); | ||
1165 | return table_listen(L); | ||
1166 | } | ||
1167 | |||
1168 | int global_send(lua_State *L) | ||
1169 | { | ||
1170 | p_tags tags = pop_tags(L); | ||
1171 | p_sock sock = get_selfclientsock(L, tags); | ||
1172 | lua_pushusertag(L, sock, tags->client); | ||
1173 | return table_send(L); | ||
1174 | } | ||
1175 | |||
1176 | int global_receive(lua_State *L) | ||
1177 | { | ||
1178 | p_tags tags = pop_tags(L); | ||
1179 | p_sock sock = get_selfclientsock(L, tags); | ||
1180 | lua_pushusertag(L, sock, tags->client); | ||
1181 | return table_receive(L); | ||
1182 | } | ||
1183 | |||
1184 | int global_timeout(lua_State *L) | ||
1185 | { | ||
1186 | p_tags tags = pop_tags(L); | ||
1187 | p_sock sock = get_selfclientsock(L, tags); | ||
1188 | lua_pushusertag(L, sock, tags->client); | ||
1189 | return table_timeout(L); | ||
1190 | } | ||
1191 | |||
1192 | int global_close(lua_State *L) | ||
1193 | { | ||
1194 | return gc_sock(L); | ||
1195 | } | ||
1196 | #endif | ||
1197 | |||
1198 | /*=========================================================================*\ | ||
1199 | * Parameter manipulation functions | ||
1200 | \*=========================================================================*/ | ||
1103 | /*-------------------------------------------------------------------------*\ | 1201 | /*-------------------------------------------------------------------------*\ |
1104 | * Passes an error code to Lua. The NET_DONE error is translated to nil. | 1202 | * Passes an error code to Lua. The NET_DONE error is translated to nil. |
1105 | * Input | 1203 | * Input |
@@ -1120,43 +1218,63 @@ static void push_error(lua_State *L, int err) | |||
1120 | } | 1218 | } |
1121 | } | 1219 | } |
1122 | 1220 | ||
1123 | /*-------------------------------------------------------------------------*\ | 1221 | static p_tags pop_tags(lua_State *L) |
1124 | * Passes socket tags to lua in correct order | ||
1125 | * Input: | ||
1126 | * client_tag, server_tag | ||
1127 | \*-------------------------------------------------------------------------*/ | ||
1128 | static void push_tags(lua_State *L, int client_tag, int server_tag) | ||
1129 | { | 1222 | { |
1130 | lua_pushnumber(L, client_tag); | 1223 | p_tags tags = (p_tags) lua_touserdata(L, -1); |
1131 | lua_pushnumber(L, server_tag); | 1224 | if (!tags) lua_error(L, "invalid closure! (probably misuse of library)"); |
1225 | lua_pop(L, 1); | ||
1226 | return tags; | ||
1132 | } | 1227 | } |
1133 | 1228 | ||
1134 | /*-------------------------------------------------------------------------*\ | 1229 | static p_sock pop_sock(lua_State *L) |
1135 | * Passes a client socket to Lua. | ||
1136 | * Must be called from a closure receiving the socket tags as its | ||
1137 | * parameters. | ||
1138 | * Input | ||
1139 | * L: lua environment | ||
1140 | * sock: pointer to socket structure to be used | ||
1141 | \*-------------------------------------------------------------------------*/ | ||
1142 | static void push_client(lua_State *L, p_sock sock, int client_tag) | ||
1143 | { | 1230 | { |
1144 | lua_pushusertag(L, (void *) sock, client_tag); | 1231 | p_sock sock = (p_sock) lua_touserdata(L, -1); |
1232 | if (!sock) lua_error(L, "invalid socket object"); | ||
1233 | if (sock->sock < 0) lua_error(L, "operation on closed socket"); | ||
1234 | lua_pop(L, 1); | ||
1235 | return sock; | ||
1145 | } | 1236 | } |
1146 | 1237 | ||
1147 | /*-------------------------------------------------------------------------*\ | 1238 | static p_sock get_selfsock(lua_State *L, p_tags tags) |
1148 | * Passes a server socket to Lua. | ||
1149 | * Must be called from a closure receiving the socket tags as its | ||
1150 | * parameters. | ||
1151 | * Input | ||
1152 | * L: lua environment | ||
1153 | * sock: pointer to socket structure to be used | ||
1154 | \*-------------------------------------------------------------------------*/ | ||
1155 | static void push_server(lua_State *L, p_sock sock, int server_tag) | ||
1156 | { | 1239 | { |
1157 | lua_pushusertag(L, (void *) sock, server_tag); | 1240 | p_sock sock; |
1241 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); | ||
1242 | lua_pushstring(L, P_SOCK); | ||
1243 | lua_gettable(L, 1); | ||
1244 | sock = lua_touserdata(L, -1); | ||
1245 | if (!sock) lua_error(L, "invalid socket object"); | ||
1246 | lua_pop(L, 1); | ||
1247 | return sock; | ||
1158 | } | 1248 | } |
1159 | 1249 | ||
1250 | #ifndef LUASOCKET_NOGLOBALS | ||
1251 | static p_sock get_selfclientsock(lua_State *L, p_tags tags) | ||
1252 | { | ||
1253 | p_sock sock; | ||
1254 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); | ||
1255 | lua_pushstring(L, P_SOCK); | ||
1256 | lua_gettable(L, 1); | ||
1257 | sock = lua_touserdata(L, -1); | ||
1258 | if (!sock || lua_tag(L, -1) != tags->client) | ||
1259 | lua_error(L, "client socket expected"); | ||
1260 | lua_pop(L, 1); | ||
1261 | return sock; | ||
1262 | } | ||
1263 | |||
1264 | static p_sock get_selfserversock(lua_State *L, p_tags tags) | ||
1265 | { | ||
1266 | p_sock sock; | ||
1267 | if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); | ||
1268 | lua_pushstring(L, P_SOCK); | ||
1269 | lua_gettable(L, 1); | ||
1270 | sock = lua_touserdata(L, -1); | ||
1271 | if (!sock || lua_tag(L, -1) != tags->server) | ||
1272 | lua_error(L, "server socket expected"); | ||
1273 | lua_pop(L, 1); | ||
1274 | return sock; | ||
1275 | } | ||
1276 | #endif | ||
1277 | |||
1160 | /*=========================================================================*\ | 1278 | /*=========================================================================*\ |
1161 | * WinSock2 specific functions. | 1279 | * WinSock2 specific functions. |
1162 | \*=========================================================================*/ | 1280 | \*=========================================================================*/ |
@@ -1166,7 +1284,7 @@ static void push_server(lua_State *L, p_sock sock, int server_tag) | |||
1166 | * Returns | 1284 | * Returns |
1167 | * 1 in case of success. 0 in case of error. | 1285 | * 1 in case of success. 0 in case of error. |
1168 | \*-------------------------------------------------------------------------*/ | 1286 | \*-------------------------------------------------------------------------*/ |
1169 | static int wsock_open(void) | 1287 | static int winsock_open(void) |
1170 | { | 1288 | { |
1171 | WORD wVersionRequested;WSADATA wsaData;int err; | 1289 | WORD wVersionRequested;WSADATA wsaData;int err; |
1172 | wVersionRequested = MAKEWORD( 2, 0 ); | 1290 | wVersionRequested = MAKEWORD( 2, 0 ); |
@@ -1181,7 +1299,6 @@ static int wsock_open(void) | |||
1181 | } | 1299 | } |
1182 | return 1; | 1300 | return 1; |
1183 | } | 1301 | } |
1184 | |||
1185 | 1302 | ||
1186 | /*-------------------------------------------------------------------------*\ | 1303 | /*-------------------------------------------------------------------------*\ |
1187 | * Put socket into blocking mode. | 1304 | * Put socket into blocking mode. |
@@ -1189,10 +1306,7 @@ static int wsock_open(void) | |||
1189 | static void set_blocking(p_sock sock) | 1306 | static void set_blocking(p_sock sock) |
1190 | { | 1307 | { |
1191 | u_long argp = 0; | 1308 | u_long argp = 0; |
1192 | if (!sock->blocking) { | 1309 | ioctlsocket(sock->sock, FIONBIO, &argp); |
1193 | ioctlsocket(sock->sock, FIONBIO, &argp); | ||
1194 | sock->blocking = 1; | ||
1195 | } | ||
1196 | } | 1310 | } |
1197 | 1311 | ||
1198 | /*-------------------------------------------------------------------------*\ | 1312 | /*-------------------------------------------------------------------------*\ |
@@ -1201,10 +1315,7 @@ static void set_blocking(p_sock sock) | |||
1201 | static void set_nonblocking(p_sock sock) | 1315 | static void set_nonblocking(p_sock sock) |
1202 | { | 1316 | { |
1203 | u_long argp = 1; | 1317 | u_long argp = 1; |
1204 | if (sock->blocking) { | 1318 | ioctlsocket(sock->sock, FIONBIO, &argp); |
1205 | ioctlsocket(sock->sock, FIONBIO, &argp); | ||
1206 | sock->blocking = 0; | ||
1207 | } | ||
1208 | } | 1319 | } |
1209 | 1320 | ||
1210 | /*-------------------------------------------------------------------------*\ | 1321 | /*-------------------------------------------------------------------------*\ |
@@ -1354,130 +1465,4 @@ static char *connect_strerror(void) | |||
1354 | default: return "unknown error"; | 1465 | default: return "unknown error"; |
1355 | } | 1466 | } |
1356 | } | 1467 | } |
1357 | |||
1358 | #endif | ||
1359 | |||
1360 | /*=========================================================================*\ | ||
1361 | * Module exported functions | ||
1362 | \*=========================================================================*/ | ||
1363 | /*-------------------------------------------------------------------------*\ | ||
1364 | * Initializes the library interface with Lua and the socket library. | ||
1365 | * Defines the symbols exported to Lua. | ||
1366 | \*-------------------------------------------------------------------------*/ | ||
1367 | void lua_socketlibopen(lua_State *L) | ||
1368 | { | ||
1369 | int client_tag, server_tag; | ||
1370 | static struct luaL_reg funcs[] = { | ||
1371 | {"connect", net_connect}, | ||
1372 | {"bind", net_bind}, | ||
1373 | {"listen", net_listen}, | ||
1374 | {"accept", net_accept}, | ||
1375 | {"close", net_close}, | ||
1376 | {"send", net_send}, | ||
1377 | {"receive", net_receive}, | ||
1378 | {"timeout", net_timeout} | ||
1379 | }; | ||
1380 | int i; | ||
1381 | |||
1382 | #ifdef WIN32 | ||
1383 | wsock_open(); | ||
1384 | #endif | ||
1385 | /* declare new Lua tags for used userdata values */ | ||
1386 | client_tag = lua_newtag(L); | ||
1387 | server_tag = lua_newtag(L); | ||
1388 | /* Lua exported functions */ | ||
1389 | for (i = 0; i < sizeof(funcs)/sizeof(funcs[0]); i++) { | ||
1390 | push_tags(L, client_tag, server_tag); | ||
1391 | lua_pushcclosure(L, funcs[i].func, 2); | ||
1392 | lua_setglobal(L, funcs[i].name); | ||
1393 | } | ||
1394 | /* fallbacks */ | ||
1395 | push_tags(L, client_tag, server_tag); | ||
1396 | lua_pushcclosure(L, client_gettable, 2); | ||
1397 | lua_settagmethod(L, client_tag, "gettable"); | ||
1398 | |||
1399 | push_tags(L, client_tag, server_tag); | ||
1400 | lua_pushcclosure(L, server_gettable, 2); | ||
1401 | lua_settagmethod(L, server_tag, "gettable"); | ||
1402 | |||
1403 | push_tags(L, client_tag, server_tag); | ||
1404 | lua_pushcclosure(L, sock_gc, 2); | ||
1405 | lua_settagmethod(L, client_tag, "gc"); | ||
1406 | |||
1407 | push_tags(L, client_tag, server_tag); | ||
1408 | lua_pushcclosure(L, sock_gc, 2); | ||
1409 | lua_settagmethod(L, server_tag, "gc"); | ||
1410 | |||
1411 | /* avoid stupid compiler warnings */ | ||
1412 | (void) set_blocking; | ||
1413 | |||
1414 | #ifndef WIN32 | ||
1415 | /* avoid getting killed by a SIGPIPE signal */ | ||
1416 | handle_sigpipe(); | ||
1417 | #endif | ||
1418 | |||
1419 | #ifdef _DEBUG | ||
1420 | /* test support functions */ | ||
1421 | lua_pushcfunction(L, net_sleep); lua_setglobal(L, "sleep"); | ||
1422 | lua_pushcfunction(L, net_time); lua_setglobal(L, "time"); | ||
1423 | #endif | 1468 | #endif |
1424 | } | ||
1425 | |||
1426 | /*=========================================================================*\ | ||
1427 | * Lua2c and c2lua stack auxiliary functions | ||
1428 | \*=========================================================================*/ | ||
1429 | /*-------------------------------------------------------------------------*\ | ||
1430 | * Checks if argument is a client socket, printing an error message in | ||
1431 | * case of error | ||
1432 | * Input | ||
1433 | * numArg: argument position in lua2c stack | ||
1434 | * Returns | ||
1435 | * pointer to client socket, or doesn't return in case of error | ||
1436 | \*-------------------------------------------------------------------------*/ | ||
1437 | static p_sock check_client(lua_State *L, int numArg, int client_tag) | ||
1438 | { | ||
1439 | p_sock sock; | ||
1440 | luaL_arg_check(L, lua_tag(L, numArg) == client_tag, | ||
1441 | numArg, "client socket expected"); | ||
1442 | sock = (p_sock) lua_touserdata(L, numArg); | ||
1443 | if (sock->sock < 0) | ||
1444 | lua_error(L, "operation on closed socket"); | ||
1445 | return sock; | ||
1446 | } | ||
1447 | |||
1448 | /*-------------------------------------------------------------------------*\ | ||
1449 | * Checks if argument is a server socket, printing an error message in | ||
1450 | * case of error | ||
1451 | * Input | ||
1452 | * numArg: argument position in lua2c stack | ||
1453 | * Returns | ||
1454 | * pointer to server socket, or doesn't return in case of error | ||
1455 | \*-------------------------------------------------------------------------*/ | ||
1456 | static p_sock check_server(lua_State *L, int numArg, int server_tag) | ||
1457 | { | ||
1458 | p_sock sock; | ||
1459 | luaL_arg_check(L, lua_tag(L, numArg) == server_tag, | ||
1460 | numArg, "server socket expected"); | ||
1461 | sock = (p_sock) lua_touserdata(L, numArg); | ||
1462 | if (sock->sock < 0) | ||
1463 | lua_error(L, "operation on closed socket"); | ||
1464 | return sock; | ||
1465 | } | ||
1466 | |||
1467 | /*-------------------------------------------------------------------------*\ | ||
1468 | * Checks if argument is a socket, printing an error message in | ||
1469 | * case of error | ||
1470 | * Input | ||
1471 | * numArg: argument position in lua2c stack | ||
1472 | * Returns | ||
1473 | * pointer to socket, or doesn't return in case of error | ||
1474 | \*-------------------------------------------------------------------------*/ | ||
1475 | static p_sock check_sock(lua_State *L, int numArg, int client_tag, | ||
1476 | int server_tag) | ||
1477 | { | ||
1478 | p_sock sock; | ||
1479 | luaL_arg_check(L, (lua_tag(L, numArg) == client_tag) || | ||
1480 | (lua_tag(L, numArg) == server_tag), numArg, "socket expected"); | ||
1481 | sock = lua_touserdata(L, numArg); | ||
1482 | return sock; | ||
1483 | } | ||