diff options
| author | Diego Nehab <diego@tecgraf.puc-rio.br> | 2001-01-13 07:10:00 +0000 |
|---|---|---|
| committer | Diego Nehab <diego@tecgraf.puc-rio.br> | 2001-01-13 07:10:00 +0000 |
| commit | 41643c2643751de17125da4c23b616840dc0f1e3 (patch) | |
| tree | 1fc50142e5fcab1dae39e1c91418276961019840 /src | |
| parent | 17c4d1c30544f0ed638879835f179ada96249868 (diff) | |
| download | luasocket-41643c2643751de17125da4c23b616840dc0f1e3.tar.gz luasocket-41643c2643751de17125da4c23b616840dc0f1e3.tar.bz2 luasocket-41643c2643751de17125da4c23b616840dc0f1e3.zip | |
All input from sockets is now buffered. This has drastically
improved line I/O. The code is much simpler now, too. All
timeout management has been rewritten.
Diffstat (limited to 'src')
| -rw-r--r-- | src/luasocket.c | 582 |
1 files changed, 267 insertions, 315 deletions
diff --git a/src/luasocket.c b/src/luasocket.c index 2216b90..4f03ad2 100644 --- a/src/luasocket.c +++ b/src/luasocket.c | |||
| @@ -6,9 +6,7 @@ | |||
| 6 | * Module: LUASOCKET.C | 6 | * Module: LUASOCKET.C |
| 7 | * | 7 | * |
| 8 | * This module is part of an effort to make the most important features | 8 | * This module is part of an effort to make the most important features |
| 9 | * of the TCP/IP protocol available for Lua scripts. | 9 | * of the TCP/IP protocol available to Lua scripts. |
| 10 | * The main intent of the project was the distribution with the CGILua | ||
| 11 | * toolkit, in which is is used to implement the SMTP client functions. | ||
| 12 | * The Lua interface to TCP/IP follows the BSD TCP/IP API closely, | 10 | * The Lua interface to TCP/IP follows the BSD TCP/IP API closely, |
| 13 | * trying to simplify all tasks involved in setting up a client connection | 11 | * trying to simplify all tasks involved in setting up a client connection |
| 14 | * and simple server connections. | 12 | * and simple server connections. |
| @@ -21,16 +19,15 @@ | |||
| 21 | /*=========================================================================*\ | 19 | /*=========================================================================*\ |
| 22 | * Common include files | 20 | * Common include files |
| 23 | \*=========================================================================*/ | 21 | \*=========================================================================*/ |
| 22 | #include <assert.h> | ||
| 23 | #include <errno.h> | ||
| 24 | #include <signal.h> | ||
| 24 | #include <stdio.h> | 25 | #include <stdio.h> |
| 25 | #include <stdlib.h> | 26 | #include <stdlib.h> |
| 26 | #include <errno.h> | ||
| 27 | #include <string.h> | 27 | #include <string.h> |
| 28 | #include <signal.h> | ||
| 29 | 28 | ||
| 30 | #include <assert.h> | ||
| 31 | |||
| 32 | #include <lua.h> | ||
| 33 | #include <lauxlib.h> | 29 | #include <lauxlib.h> |
| 30 | #include <lua.h> | ||
| 34 | #include <lualib.h> | 31 | #include <lualib.h> |
| 35 | 32 | ||
| 36 | #include "luasocket.h" | 33 | #include "luasocket.h" |
| @@ -41,11 +38,11 @@ | |||
| 41 | #ifdef WIN32 | 38 | #ifdef WIN32 |
| 42 | #include <winsock2.h> | 39 | #include <winsock2.h> |
| 43 | #include <winbase.h> | 40 | #include <winbase.h> |
| 41 | #else | ||
| 44 | 42 | ||
| 45 | /*=========================================================================*\ | 43 | /*=========================================================================*\ |
| 46 | * BSD include files | 44 | * BSD include files |
| 47 | \*=========================================================================*/ | 45 | \*=========================================================================*/ |
| 48 | #else | ||
| 49 | /* close function */ | 46 | /* close function */ |
| 50 | #include <unistd.h> | 47 | #include <unistd.h> |
| 51 | /* fnctnl function and associated constants */ | 48 | /* fnctnl function and associated constants */ |
| @@ -101,13 +98,19 @@ | |||
| 101 | #define NET_CLOSED 1 /* the connection has been closed */ | 98 | #define NET_CLOSED 1 /* the connection has been closed */ |
| 102 | 99 | ||
| 103 | /*-------------------------------------------------------------------------*\ | 100 | /*-------------------------------------------------------------------------*\ |
| 101 | * Time out mode to be checked | ||
| 102 | \*-------------------------------------------------------------------------*/ | ||
| 103 | #define TM_RECEIVE 1 | ||
| 104 | #define TM_SEND 2 | ||
| 105 | |||
| 106 | /*-------------------------------------------------------------------------*\ | ||
| 104 | * As far as a Lua script is concerned, there are two kind of objects | 107 | * As far as a Lua script is concerned, there are two kind of objects |
| 105 | * representing a socket. A client socket is an object created by the | 108 | * representing a socket. A client socket is an object created by the |
| 106 | * function connect, and implementing the methods send, receive, timeout | 109 | * function connect, and implementing the methods send, receive, timeout |
| 107 | * and close. A server socket is an object created by the function bind, | 110 | * and close. A server socket is an object created by the function bind, |
| 108 | * and implementing the methods listen, accept and close. Lua tag values | 111 | * and implementing the methods listen, accept and close. Lua tag values |
| 109 | * for these objects are created in the lua_socketlibopen function, and | 112 | * for these objects are created in the lua_socketlibopen function, and |
| 110 | * passed as closure values (first argumnents to every library function, | 113 | * passed as closure values (last argumnents to every library function) |
| 111 | # because we can't have any global variables. | 114 | # because we can't have any global variables. |
| 112 | \*-------------------------------------------------------------------------*/ | 115 | \*-------------------------------------------------------------------------*/ |
| 113 | #define CLIENT_TAG -2 | 116 | #define CLIENT_TAG -2 |
| @@ -115,27 +118,30 @@ | |||
| 115 | 118 | ||
| 116 | /*-------------------------------------------------------------------------*\ | 119 | /*-------------------------------------------------------------------------*\ |
| 117 | * Both socket types are stored in the same structure to simplify | 120 | * Both socket types are stored in the same structure to simplify |
| 118 | * implementation. The tag value used is different, though. The timeout | 121 | * implementation. The tag value used is different, though. |
| 119 | * fields are not used for the server socket object. | 122 | * The timeout and buffer parameters are not used by server sockets. |
| 120 | * There are two timeout values. The block timeout specifies the maximum | ||
| 121 | * time the any IO operation performed by luasocket can be blocked waiting | ||
| 122 | * for completion. The return timeout specifies the maximum time a Lua script | ||
| 123 | * can be blocked waiting for an luasocket IO operation to complete. | ||
| 124 | \*-------------------------------------------------------------------------*/ | 123 | \*-------------------------------------------------------------------------*/ |
| 125 | typedef struct t_sock { | 124 | typedef struct t_sock { |
| 126 | SOCKET sock; /* operating system socket object */ | 125 | /* operating system socket object */ |
| 127 | int b; /* block timeout in ms */ | 126 | SOCKET sock; |
| 128 | int r; /* return timeout in ms */ | 127 | /* start time of the current operation */ |
| 129 | int blocking; /* is this socket in blocking mode? */ | 128 | 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) */ | ||
| 134 | int tm_return, tm_block; | ||
| 135 | /* buffered I/O storage */ | ||
| 136 | unsigned char bf_buffer[LUASOCKET_BUFFERSIZE]; | ||
| 137 | /* first and last red bytes not yet passed to application */ | ||
| 138 | int bf_first, bf_last; | ||
| 130 | } t_sock; | 139 | } t_sock; |
| 131 | typedef t_sock *p_sock; | 140 | typedef t_sock *p_sock; |
| 132 | 141 | ||
| 133 | /*-------------------------------------------------------------------------*\ | 142 | /*-------------------------------------------------------------------------*\ |
| 134 | * Macros and internal declarations | 143 | * Macros and internal declarations |
| 135 | \*-------------------------------------------------------------------------*/ | 144 | \*-------------------------------------------------------------------------*/ |
| 136 | /* return time since marked start in ms */ | ||
| 137 | #define time_since(start) (get_time()-start) | ||
| 138 | |||
| 139 | /* min and max macros */ | 145 | /* min and max macros */ |
| 140 | #ifndef min | 146 | #ifndef min |
| 141 | #define min(x, y) ((x) < (y) ? x : y) | 147 | #define min(x, y) ((x) < (y) ? x : y) |
| @@ -157,6 +163,24 @@ static int net_receive(lua_State *L); | |||
| 157 | static int net_timeout(lua_State *L); | 163 | static int net_timeout(lua_State *L); |
| 158 | static int net_close(lua_State *L); | 164 | static int net_close(lua_State *L); |
| 159 | 165 | ||
| 166 | /* buffered I/O management */ | ||
| 167 | static const unsigned char *bf_receive(p_sock sock, int *length); | ||
| 168 | static void bf_skip(p_sock sock, int length); | ||
| 169 | static int bf_isempty(p_sock sock); | ||
| 170 | |||
| 171 | /* timeout management */ | ||
| 172 | static int tm_timedout(p_sock sock, int mode); | ||
| 173 | static int tm_gettimeleft(p_sock sock); | ||
| 174 | static int tm_gettime(void); | ||
| 175 | static void tm_markstart(p_sock sock); | ||
| 176 | |||
| 177 | /* I/O */ | ||
| 178 | static int send_raw(p_sock sock, const char *data, int wanted, int *err); | ||
| 179 | static int receive_raw(lua_State *L, p_sock sock, int wanted); | ||
| 180 | static int receive_dosline(lua_State *L, p_sock sock); | ||
| 181 | static int receive_unixline(lua_State *L, p_sock sock); | ||
| 182 | static int receive_all(lua_State *L, p_sock sock); | ||
| 183 | |||
| 160 | /* fallbacks */ | 184 | /* fallbacks */ |
| 161 | static int server_gettable(lua_State *L); | 185 | static int server_gettable(lua_State *L); |
| 162 | static int client_gettable(lua_State *L); | 186 | static int client_gettable(lua_State *L); |
| @@ -170,7 +194,7 @@ static p_sock check_sock(lua_State *L, int numArg, int server_tag, | |||
| 170 | static void pop_tags(lua_State *L, int *client_tag, int *server_tag); | 194 | static void pop_tags(lua_State *L, int *client_tag, int *server_tag); |
| 171 | static void push_tags(lua_State *L, int client_tag, int server_tag); | 195 | static void push_tags(lua_State *L, int client_tag, int server_tag); |
| 172 | 196 | ||
| 173 | /* result handling routines */ | 197 | /* error code translations functions */ |
| 174 | static char *host_strerror(void); | 198 | static char *host_strerror(void); |
| 175 | static char *bind_strerror(void); | 199 | static char *bind_strerror(void); |
| 176 | static char *sock_strerror(void); | 200 | static char *sock_strerror(void); |
| @@ -181,7 +205,6 @@ static void push_client(lua_State *L, p_sock sock, int client_tag); | |||
| 181 | static void push_server(lua_State *L, p_sock sock, int server_tag); | 205 | static void push_server(lua_State *L, p_sock sock, int server_tag); |
| 182 | 206 | ||
| 183 | /* plataform specific functions */ | 207 | /* plataform specific functions */ |
| 184 | static int get_time(void); | ||
| 185 | static void set_blocking(p_sock sock); | 208 | static void set_blocking(p_sock sock); |
| 186 | static void set_nonblocking(p_sock sock); | 209 | static void set_nonblocking(p_sock sock); |
| 187 | 210 | ||
| @@ -190,19 +213,6 @@ static p_sock create_sock(void); | |||
| 190 | static p_sock create_tcpsock(void); | 213 | static p_sock create_tcpsock(void); |
| 191 | static int fill_sockaddr(struct sockaddr_in *server, const char *hostname, | 214 | static int fill_sockaddr(struct sockaddr_in *server, const char *hostname, |
| 192 | unsigned short port); | 215 | unsigned short port); |
| 193 | static int get_timeout(p_sock sock, int elapsed); | ||
| 194 | static int read_or_timeout(p_sock sock, int elapsed); | ||
| 195 | static int write_or_timeout(p_sock sock, int elapsed); | ||
| 196 | static int send_raw(p_sock sock, const char *data, int wanted, | ||
| 197 | int start, int *err, int *end); | ||
| 198 | static void receive_raw(lua_State *L, p_sock sock, int wanted, | ||
| 199 | int start, int *err, int *end); | ||
| 200 | static void receive_dosline(lua_State *L, p_sock sock, int start, | ||
| 201 | int *err, int *end); | ||
| 202 | static void receive_unixline(lua_State *L, p_sock sock, int start, | ||
| 203 | int *err, int *end); | ||
| 204 | static void receive_all(lua_State *L, p_sock sock, int start, | ||
| 205 | int *err, int *end); | ||
| 206 | 216 | ||
| 207 | /*=========================================================================*\ | 217 | /*=========================================================================*\ |
| 208 | * Test support functions | 218 | * Test support functions |
| @@ -214,7 +224,7 @@ static void receive_all(lua_State *L, p_sock sock, int start, | |||
| 214 | static int net_time(lua_State *L); | 224 | static int net_time(lua_State *L); |
| 215 | static int net_time(lua_State *L) | 225 | static int net_time(lua_State *L) |
| 216 | { | 226 | { |
| 217 | lua_pushnumber(L, get_time()/1000.0); | 227 | lua_pushnumber(L, tm_gettime()/1000.0); |
| 218 | return 1; | 228 | return 1; |
| 219 | } | 229 | } |
| 220 | 230 | ||
| @@ -279,6 +289,7 @@ static int net_connect(lua_State *L) | |||
| 279 | lua_pushstring(L, connect_strerror()); | 289 | lua_pushstring(L, connect_strerror()); |
| 280 | return 2; | 290 | return 2; |
| 281 | } | 291 | } |
| 292 | set_nonblocking(sock); | ||
| 282 | push_client(L, sock, client_tag); | 293 | push_client(L, sock, client_tag); |
| 283 | lua_pushnil(L); | 294 | lua_pushnil(L); |
| 284 | return 2; | 295 | return 2; |
| @@ -341,6 +352,7 @@ static int net_accept(lua_State *L) | |||
| 341 | return 2; | 352 | return 2; |
| 342 | } else { | 353 | } else { |
| 343 | client->sock = client_sock; | 354 | client->sock = client_sock; |
| 355 | set_nonblocking(client); | ||
| 344 | push_client(L, client, client_tag); | 356 | push_client(L, client, client_tag); |
| 345 | lua_pushnil(L); | 357 | lua_pushnil(L); |
| 346 | return 2; | 358 | return 2; |
| @@ -431,10 +443,10 @@ static int net_timeout(lua_State *L) | |||
| 431 | mode = luaL_opt_string(L, 3, "b"); | 443 | mode = luaL_opt_string(L, 3, "b"); |
| 432 | switch (*mode) { | 444 | switch (*mode) { |
| 433 | case 'b': | 445 | case 'b': |
| 434 | sock->b = ms; | 446 | sock->tm_block = ms; |
| 435 | break; | 447 | break; |
| 436 | case 'r': | 448 | case 'r': |
| 437 | sock->r = ms; | 449 | sock->tm_return = ms; |
| 438 | break; | 450 | break; |
| 439 | default: | 451 | default: |
| 440 | luaL_arg_check(L, 0, 3, "invalid timeout mode"); | 452 | luaL_arg_check(L, 0, 3, "invalid timeout mode"); |
| @@ -459,35 +471,26 @@ static int net_send(lua_State *L) | |||
| 459 | { | 471 | { |
| 460 | p_sock sock; | 472 | p_sock sock; |
| 461 | const char *data; | 473 | const char *data; |
| 462 | size_t size; | 474 | int wanted; |
| 463 | int start = get_time(); | ||
| 464 | long total = 0; | 475 | long total = 0; |
| 465 | int arg; | 476 | int arg; |
| 466 | int err = NET_DONE; | 477 | int err = NET_DONE; |
| 467 | int end; | ||
| 468 | int top; | 478 | int top; |
| 469 | int client_tag, server_tag; | 479 | int client_tag, server_tag; |
| 470 | pop_tags(L, &client_tag, &server_tag); | 480 | pop_tags(L, &client_tag, &server_tag); |
| 471 | top = lua_gettop(L); | 481 | top = lua_gettop(L); |
| 472 | sock = check_client(L, 1, client_tag); | 482 | sock = check_client(L, 1, client_tag); |
| 473 | #ifdef _DEBUG_BLOCK | 483 | tm_markstart(sock); |
| 474 | printf("luasocket: send start\n"); | ||
| 475 | #endif | ||
| 476 | for (arg = 2; arg <= top; arg++) { | 484 | for (arg = 2; arg <= top; arg++) { |
| 477 | data = luaL_opt_lstr(L, arg, NULL, &size); | 485 | data = luaL_opt_lstr(L, arg, NULL, &wanted); |
| 478 | if (!data || err != NET_DONE) | 486 | if (!data || err != NET_DONE) break; |
| 479 | break; | 487 | total += send_raw(sock, data, wanted, &err); |
| 480 | total += send_raw(sock, data, size, start, &err, &end); | ||
| 481 | } | 488 | } |
| 482 | push_error(L, err); | 489 | push_error(L, err); |
| 483 | lua_pushnumber(L, (double) total); | 490 | lua_pushnumber(L, (double) total); |
| 484 | #ifdef _DEBUG_BLOCK | ||
| 485 | printf("luasocket: send end\n"); | ||
| 486 | #endif | ||
| 487 | #ifdef _DEBUG | 491 | #ifdef _DEBUG |
| 488 | /* pass the time elapsed during function execution to Lua, so that | 492 | /* push time elapsed during operation as the last return value */ |
| 489 | ** the test script can make sure we respected the timeouts */ | 493 | lua_pushnumber(L, (sock->tm_end - sock->tm_start)/1000.0); |
| 490 | lua_pushnumber(L, (end-start)/1000.0); | ||
| 491 | #endif | 494 | #endif |
| 492 | return lua_gettop(L) - top; | 495 | return lua_gettop(L) - top; |
| 493 | } | 496 | } |
| @@ -501,33 +504,31 @@ lua_pushnumber(L, (end-start)/1000.0); | |||
| 501 | * by a LF character, preceded or not by a CR character. This is | 504 | * by a LF character, preceded or not by a CR character. This is |
| 502 | * the default pattern | 505 | * the default pattern |
| 503 | * "*lu": reads a text line, terminanted by a CR character only. (Unix mode) | 506 | * "*lu": reads a text line, terminanted by a CR character only. (Unix mode) |
| 507 | * "*a": reads until connection closed | ||
| 504 | * number: reads 'number' characters from the socket | 508 | * number: reads 'number' characters from the socket |
| 505 | * Returns | 509 | * Returns |
| 506 | * On success: one string for each pattern | 510 | * On success: one string for each pattern |
| 507 | * On error: all strings for which there was no error, followed by one | 511 | * On error: all strings for which there was no error, followed by one |
| 508 | * nil value for each failed string, followed by an error code | 512 | * nil value for the remaining strings, followed by an error code |
| 509 | \*-------------------------------------------------------------------------*/ | 513 | \*-------------------------------------------------------------------------*/ |
| 510 | static int net_receive(lua_State *L) | 514 | static int net_receive(lua_State *L) |
| 511 | { | 515 | { |
| 512 | static const char *const modenames[] = {"*l", "*lu", "*a", NULL}; | 516 | static const char *const modenames[] = {"*l", "*lu", "*a", NULL}; |
| 513 | int err = NET_DONE, arg = 2; | 517 | int err = NET_DONE, arg = 2; |
| 514 | int start = get_time(); | 518 | const char *mode; |
| 515 | int end; | ||
| 516 | int client_tag, server_tag; | 519 | int client_tag, server_tag; |
| 517 | int top; | 520 | int top; |
| 518 | p_sock sock; | 521 | p_sock sock; |
| 519 | const char *mode; | ||
| 520 | pop_tags(L, &client_tag, &server_tag); | 522 | pop_tags(L, &client_tag, &server_tag); |
| 521 | sock = check_client(L, 1, client_tag); | 523 | sock = check_client(L, 1, client_tag); |
| 522 | #ifdef _DEBUG_BLOCK | 524 | tm_markstart(sock); |
| 523 | printf("luasocket: receive start\n"); | ||
| 524 | #endif | ||
| 525 | /* push default pattern */ | 525 | /* push default pattern */ |
| 526 | top = lua_gettop(L); | 526 | top = lua_gettop(L); |
| 527 | if (top < 2) { | 527 | if (top < 2) { |
| 528 | lua_pushstring(L, "*l"); | 528 | lua_pushstring(L, "*l"); |
| 529 | top++; | 529 | top++; |
| 530 | } | 530 | } |
| 531 | /* receive all patterns */ | ||
| 531 | for (arg = 2; arg <= top; arg++) { | 532 | for (arg = 2; arg <= top; arg++) { |
| 532 | /* if one pattern failed, we just skip all other patterns */ | 533 | /* if one pattern failed, we just skip all other patterns */ |
| 533 | if (err != NET_DONE) { | 534 | if (err != NET_DONE) { |
| @@ -536,24 +537,24 @@ printf("luasocket: receive start\n"); | |||
| 536 | } | 537 | } |
| 537 | if (lua_isnumber(L, arg)) { | 538 | if (lua_isnumber(L, arg)) { |
| 538 | long size = (long) lua_tonumber(L, arg); | 539 | long size = (long) lua_tonumber(L, arg); |
| 539 | receive_raw(L, sock, size, start, &err, &end); | 540 | err = receive_raw(L, sock, size); |
| 540 | } else { | 541 | } else { |
| 541 | mode = luaL_opt_string(L, arg, NULL); | 542 | mode = luaL_opt_string(L, arg, NULL); |
| 542 | /* get next pattern */ | 543 | /* get next pattern */ |
| 543 | switch (luaL_findstring(mode, modenames)) { | 544 | switch (luaL_findstring(mode, modenames)) { |
| 544 | /* DOS line mode */ | 545 | /* DOS line mode */ |
| 545 | case 0: | 546 | case 0: |
| 546 | receive_dosline(L, sock, start, &err, &end); | 547 | err = receive_dosline(L, sock); |
| 547 | break; | 548 | break; |
| 548 | /* Unix line mode */ | 549 | /* Unix line mode */ |
| 549 | case 1: | 550 | case 1: |
| 550 | receive_unixline(L, sock, start, &err, &end); | 551 | err = receive_unixline(L, sock); |
| 551 | break; | 552 | break; |
| 552 | /* 'Til closed mode */ | 553 | /* until closed mode */ |
| 553 | case 2: | 554 | case 2: |
| 554 | receive_all(L, sock, start, &err, &end); | 555 | err = receive_all(L, sock); |
| 555 | break; | 556 | break; |
| 556 | /* else it must be a number, raw mode */ | 557 | /* else it is an error */ |
| 557 | default: | 558 | default: |
| 558 | luaL_arg_check(L, 0, arg, "invalid receive pattern"); | 559 | luaL_arg_check(L, 0, arg, "invalid receive pattern"); |
| 559 | break; | 560 | break; |
| @@ -562,13 +563,9 @@ printf("luasocket: receive start\n"); | |||
| 562 | } | 563 | } |
| 563 | /* last return is an error code */ | 564 | /* last return is an error code */ |
| 564 | push_error(L, err); | 565 | push_error(L, err); |
| 565 | #ifdef _DEBUG_BLOCK | ||
| 566 | printf("luasocket: receive end\n"); | ||
| 567 | #endif | ||
| 568 | #ifdef _DEBUG | 566 | #ifdef _DEBUG |
| 569 | /* pass the time elapsed during function execution to Lua, so that | 567 | /* push time elapsed during operation as the last return value */ |
| 570 | ** the test script can make sure we respected the timeouts */ | 568 | lua_pushnumber(L, (sock->tm_end - sock->tm_start)/1000.0); |
| 571 | lua_pushnumber(L, (end-start)/1000.0); | ||
| 572 | #endif | 569 | #endif |
| 573 | return lua_gettop(L) - top; | 570 | return lua_gettop(L) - top; |
| 574 | } | 571 | } |
| @@ -598,8 +595,8 @@ static int net_close(lua_State *L) | |||
| 598 | \*-------------------------------------------------------------------------*/ | 595 | \*-------------------------------------------------------------------------*/ |
| 599 | static int client_gettable(lua_State *L) | 596 | static int client_gettable(lua_State *L) |
| 600 | { | 597 | { |
| 601 | static const char *const net_api[] = {"receive","send","timeout","close", | 598 | static const char *const net_api[] = |
| 602 | "connect", NULL}; | 599 | {"receive","send","timeout","close", "connect", NULL}; |
| 603 | const char *idx = luaL_check_string(L, 2); | 600 | const char *idx = luaL_check_string(L, 2); |
| 604 | int server_tag, client_tag; | 601 | int server_tag, client_tag; |
| 605 | pop_tags(L, &client_tag, &server_tag); | 602 | pop_tags(L, &client_tag, &server_tag); |
| @@ -700,12 +697,11 @@ static void handle_sigpipe(void) | |||
| 700 | static p_sock create_sock(void) | 697 | static p_sock create_sock(void) |
| 701 | { | 698 | { |
| 702 | p_sock sock = (p_sock) malloc(sizeof(t_sock)); | 699 | p_sock sock = (p_sock) malloc(sizeof(t_sock)); |
| 703 | if (!sock) | 700 | if (!sock) return NULL; |
| 704 | return NULL; | ||
| 705 | sock->sock = -1; | 701 | sock->sock = -1; |
| 706 | sock->r = -1; | 702 | sock->tm_block = -1; |
| 707 | sock->b = -1; | 703 | sock->tm_return = -1; |
| 708 | sock->blocking = 1; | 704 | sock->bf_first = sock->bf_last = 0; |
| 709 | return sock; | 705 | return sock; |
| 710 | } | 706 | } |
| 711 | 707 | ||
| @@ -777,97 +773,138 @@ static int fill_sockaddr(struct sockaddr_in *address, const char *hostname, | |||
| 777 | } | 773 | } |
| 778 | 774 | ||
| 779 | /*-------------------------------------------------------------------------*\ | 775 | /*-------------------------------------------------------------------------*\ |
| 780 | * Determine the time limit to be passed to the select function, given | 776 | * Determines how much time we have left for the current io operation |
| 781 | * the time elapsed since the beginning of the operation. | 777 | * an IO write operation. |
| 782 | * Input | 778 | * Input |
| 783 | * sock: socket structure being used in operation | 779 | * sock: socket structure being used in operation |
| 784 | * elapsed: time elapsed since operation started | ||
| 785 | * Returns | 780 | * Returns |
| 786 | * time limit before function return in ms or -1 in case there is no | 781 | * the number of ms left or -1 if there is no time limit |
| 787 | * time limit | ||
| 788 | \*-------------------------------------------------------------------------*/ | 782 | \*-------------------------------------------------------------------------*/ |
| 789 | static int get_timeout(p_sock sock, int elapsed) | 783 | static int tm_gettimeleft(p_sock sock) |
| 790 | { | 784 | { |
| 791 | /* no timeout */ | 785 | /* no timeout */ |
| 792 | if (sock->b < 0 && sock->r < 0) | 786 | if (sock->tm_block < 0 && sock->tm_return < 0) |
| 793 | return -1; | 787 | return -1; |
| 794 | /* there is no block timeout, we use the return timeout */ | 788 | /* there is no block timeout, we use the return timeout */ |
| 795 | if (sock->b < 0) | 789 | else if (sock->tm_block < 0) |
| 796 | return max(0, sock->r - elapsed); | 790 | return max(sock->tm_return - tm_gettime() + sock->tm_start, 0); |
| 797 | /* there is no return timeout, we use the block timeout */ | 791 | /* there is no return timeout, we use the block timeout */ |
| 798 | else if (sock->r < 0) | 792 | else if (sock->tm_return < 0) |
| 799 | return sock->b; | 793 | return sock->tm_block; |
| 800 | /* both timeouts are specified */ | 794 | /* both timeouts are specified */ |
| 801 | else | 795 | else return min(sock->tm_block, |
| 802 | return min(sock->b, max(0, sock->r - elapsed)); | 796 | max(sock->tm_return - tm_gettime() + sock->tm_start, 0)); |
| 803 | } | 797 | } |
| 804 | 798 | ||
| 805 | /*-------------------------------------------------------------------------*\ | 799 | /*-------------------------------------------------------------------------*\ |
| 806 | * Determines if we have a timeout condition or if we can proceed with | 800 | * Determines if we have a timeout condition or if we can proceed with |
| 807 | * an IO read operation. | 801 | * an IO write operation. |
| 808 | * Input | 802 | * Input |
| 809 | * sock: socket structure being used in operation | 803 | * sock: socket structure being used in operation |
| 810 | * elapsed: time elapsed since operation started | 804 | * mode: TM_RECEIVE or TM_SEND |
| 811 | * Returns | 805 | * Returns |
| 812 | * 1 if we can proceed, 0 if a timeou has occured | 806 | * 1 if we can proceed, 0 if a timeout has occured |
| 813 | \*-------------------------------------------------------------------------*/ | 807 | \*-------------------------------------------------------------------------*/ |
| 814 | static int read_or_timeout(p_sock sock, int elapsed) | 808 | static int tm_timedout(p_sock sock, int mode) |
| 815 | { | 809 | { |
| 816 | fd_set set; /* file descriptor set */ | 810 | fd_set fds; |
| 817 | struct timeval to; /* timeout structure */ | 811 | int ret, delta; |
| 818 | int ms = get_timeout(sock, elapsed); | 812 | fd_set *preadfds = NULL, *pwritefds = NULL; |
| 819 | int err; | 813 | struct timeval tm; |
| 820 | /* got timeout */ | 814 | struct timeval *ptm = NULL; |
| 821 | if (ms == 0) | 815 | /* find out how much time we have left, in ms */ |
| 822 | return 0; | 816 | int ms = tm_gettimeleft(sock); |
| 823 | FD_ZERO(&set); | 817 | /* fill file descriptor set */ |
| 824 | FD_SET(sock->sock, &set); | 818 | FD_ZERO(&fds); FD_SET(sock->sock, &fds); |
| 825 | /* we have a limit on the time we can wait */ | 819 | /* fill timeval structure */ |
| 826 | if (ms > 0) { | 820 | tm.tv_sec = ms / 1000; |
| 827 | to.tv_sec = ms / 1000; | 821 | tm.tv_usec = (ms % 1000) * 1000; |
| 828 | to.tv_usec = (ms % 1000) * 1000; | 822 | /* define function parameters */ |
| 829 | err = select(sock->sock+1, &set, NULL, NULL, &to); | 823 | if (ms > 0) ptm = &tm; /* ptm == NULL when we don't have timeout */ |
| 830 | set_nonblocking(sock); | 824 | if (mode == TM_RECEIVE) preadfds = &fds; |
| 831 | /* we can wait forever */ | 825 | else pwritefds = &fds; |
| 832 | } else { | 826 | delta = tm_gettime(); |
| 833 | err = select(sock->sock+1, &set, NULL, NULL, NULL); | 827 | /* see if we can read or write or if we timedout */ |
| 834 | set_blocking(sock); | 828 | ret = select(sock->sock+1, preadfds, pwritefds, NULL, ptm); |
| 835 | } | 829 | #ifdef _DEBUG |
| 836 | return (err > 0); | 830 | /* store end time for this operation before calling select */ |
| 831 | sock->tm_end = tm_gettime(); | ||
| 832 | #endif | ||
| 833 | return ret <= 0; | ||
| 837 | } | 834 | } |
| 838 | 835 | ||
| 839 | /*-------------------------------------------------------------------------*\ | 836 | /*-------------------------------------------------------------------------*\ |
| 840 | * Determines if we have a timeout condition or if we can proceed with | 837 | * Marks the operation start time in sock structure |
| 841 | * an IO write operation. | 838 | * Input |
| 839 | * sock: socket structure being used in operation | ||
| 840 | \*-------------------------------------------------------------------------*/ | ||
| 841 | static void tm_markstart(p_sock sock) | ||
| 842 | { | ||
| 843 | sock->tm_start = tm_gettime(); | ||
| 844 | #ifdef _DEBUG | ||
| 845 | sock->tm_end = sock->tm_start; | ||
| 846 | #endif | ||
| 847 | } | ||
| 848 | |||
| 849 | /*-------------------------------------------------------------------------*\ | ||
| 850 | * Determines of there is any data in the read buffer | ||
| 842 | * Input | 851 | * Input |
| 843 | * sock: socket structure being used in operation | 852 | * sock: socket structure being used in operation |
| 844 | * elapsed: time elapsed since operation started | ||
| 845 | * Returns | 853 | * Returns |
| 846 | * 1 if we can proceed, 0 if a timeou has occured | 854 | * 1 if empty, 0 if there is data |
| 847 | \*-------------------------------------------------------------------------*/ | 855 | \*-------------------------------------------------------------------------*/ |
| 848 | static int write_or_timeout(p_sock sock, int elapsed) | 856 | static int bf_isempty(p_sock sock) |
| 849 | { | 857 | { |
| 850 | fd_set set; /* file descriptor set */ | 858 | return sock->bf_first >= sock->bf_last; |
| 851 | struct timeval to; /* timeout structure */ | 859 | } |
| 852 | int ms = get_timeout(sock, elapsed); | 860 | |
| 853 | int err; | 861 | /*-------------------------------------------------------------------------*\ |
| 854 | /* got timeout */ | 862 | * Skip a given number of bytes in read buffer |
| 855 | if (ms == 0) | 863 | * Input |
| 856 | return 0; | 864 | * sock: socket structure being used in operation |
| 857 | FD_ZERO(&set); | 865 | * length: number of bytes to skip |
| 858 | FD_SET(sock->sock, &set); | 866 | \*-------------------------------------------------------------------------*/ |
| 859 | /* we have a limit on the time we can wait */ | 867 | static void bf_skip(p_sock sock, int length) |
| 860 | if (ms > 0) { | 868 | { |
| 861 | to.tv_sec = ms / 1000; | 869 | sock->bf_first += length; |
| 862 | to.tv_usec = (ms % 1000) * 1000; | 870 | if (bf_isempty(sock)) sock->bf_first = sock->bf_last = 0; |
| 863 | err = select(sock->sock+1, NULL, &set, NULL, &to); | 871 | } |
| 864 | set_nonblocking(sock); | 872 | |
| 865 | /* we can wait forever */ | 873 | /*-------------------------------------------------------------------------*\ |
| 866 | } else { | 874 | * Return any data avilable in buffer, or get more data from transport layer |
| 867 | err = select(sock->sock+1, NULL, &set, NULL, NULL); | 875 | * if there is none. |
| 868 | set_blocking(sock); | 876 | * Input |
| 877 | * sock: socket structure being used in operation | ||
| 878 | * Output | ||
| 879 | * length: number of bytes available in buffer | ||
| 880 | * Returns | ||
| 881 | * pointer to start of data | ||
| 882 | \*-------------------------------------------------------------------------*/ | ||
| 883 | static const unsigned char *bf_receive(p_sock sock, int *length) | ||
| 884 | { | ||
| 885 | if (bf_isempty(sock)) { | ||
| 886 | int got = recv(sock->sock, sock->bf_buffer, LUASOCKET_BUFFERSIZE, 0); | ||
| 887 | sock->bf_first = 0; | ||
| 888 | if (got >= 0) sock->bf_last = got; | ||
| 889 | else sock->bf_last = 0; | ||
| 869 | } | 890 | } |
| 870 | return (err > 0); | 891 | *length = sock->bf_last - sock->bf_first; |
| 892 | return sock->bf_buffer + sock->bf_first; | ||
| 893 | } | ||
| 894 | |||
| 895 | /*-------------------------------------------------------------------------*\ | ||
| 896 | * Gets time in ms, relative to system startup. | ||
| 897 | * Returns | ||
| 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 | ||
| 871 | } | 908 | } |
| 872 | 909 | ||
| 873 | /*-------------------------------------------------------------------------*\ | 910 | /*-------------------------------------------------------------------------*\ |
| @@ -877,49 +914,24 @@ static int write_or_timeout(p_sock sock, int elapsed) | |||
| 877 | * sock: socket structure being used in operation | 914 | * sock: socket structure being used in operation |
| 878 | * data: buffer to be sent | 915 | * data: buffer to be sent |
| 879 | * wanted: number of bytes in buffer | 916 | * wanted: number of bytes in buffer |
| 880 | * start: time the operation started, in ms | ||
| 881 | * Output | 917 | * Output |
| 882 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | 918 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED |
| 883 | * Returns | 919 | * Returns |
| 884 | * Number of bytes written | 920 | * Number of bytes written |
| 885 | \*-------------------------------------------------------------------------*/ | 921 | \*-------------------------------------------------------------------------*/ |
| 886 | static int send_raw(p_sock sock, const char *data, int wanted, | 922 | static int send_raw(p_sock sock, const char *data, int wanted, int *err) |
| 887 | int start, int *err, int *end) | ||
| 888 | { | 923 | { |
| 889 | int put = 0, total = 0; | 924 | int put = 0, total = 0; |
| 890 | *end = start; | ||
| 891 | while (wanted > 0) { | 925 | while (wanted > 0) { |
| 892 | if(!write_or_timeout(sock, time_since(start))) { | 926 | if (tm_timedout(sock, TM_SEND)) { |
| 893 | #ifdef _DEBUG | ||
| 894 | *end = get_time(); | ||
| 895 | #endif | ||
| 896 | *err = NET_TIMEOUT; | 927 | *err = NET_TIMEOUT; |
| 897 | return total; | 928 | return total; |
| 898 | } | 929 | } |
| 899 | #ifdef _DEBUG | ||
| 900 | /* the lua_pushlstring function can take a long time to pass a large block | ||
| 901 | ** to Lua, therefore, we mark the time before passing the result. | ||
| 902 | ** also, the call to write or read might take longer then the time we had | ||
| 903 | ** left, so that the end of the operation is marked before the last call | ||
| 904 | ** to the OS */ | ||
| 905 | *end = get_time(); | ||
| 906 | #endif | ||
| 907 | put = send(sock->sock, data, wanted, 0); | 930 | put = send(sock->sock, data, wanted, 0); |
| 908 | if (put <= 0) { | 931 | if (put <= 0) { |
| 909 | #ifdef WIN32 | ||
| 910 | /* on WinSock, a select over a socket on which there is a | ||
| 911 | ** non-blocking operation pending returns immediately, even | ||
| 912 | ** if the call would block. therefore, we have to do a busy | ||
| 913 | ** wait here. */ | ||
| 914 | if (WSAGetLastError() == WSAEWOULDBLOCK) | ||
| 915 | continue; | ||
| 916 | #endif | ||
| 917 | *err = NET_CLOSED; | 932 | *err = NET_CLOSED; |
| 918 | return total; | 933 | return total; |
| 919 | } | 934 | } |
| 920 | #ifdef _DEBUG_BLOCK | ||
| 921 | printf("luasocket: sent %d, wanted %d, %dms elapsed\n", put, wanted, time_since(start)); | ||
| 922 | #endif | ||
| 923 | wanted -= put; | 935 | wanted -= put; |
| 924 | data += put; | 936 | data += put; |
| 925 | total += put; | 937 | total += put; |
| @@ -934,180 +946,146 @@ printf("luasocket: sent %d, wanted %d, %dms elapsed\n", put, wanted, time_since( | |||
| 934 | * Input | 946 | * Input |
| 935 | * sock: socket structure being used in operation | 947 | * sock: socket structure being used in operation |
| 936 | * wanted: number of bytes to be read | 948 | * wanted: number of bytes to be read |
| 937 | * start: time the operation started, in ms | ||
| 938 | * Output | ||
| 939 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | ||
| 940 | * Returns | 949 | * Returns |
| 941 | * Number of bytes read | 950 | * operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED |
| 942 | \*-------------------------------------------------------------------------*/ | 951 | \*-------------------------------------------------------------------------*/ |
| 943 | #define MIN(x,y) ((x)<(y)?(x):(y)) | 952 | static int receive_raw(lua_State *L, p_sock sock, int wanted) |
| 944 | static void receive_raw(lua_State *L, p_sock sock, int wanted, int start, | ||
| 945 | int *err, int *end) | ||
| 946 | { | 953 | { |
| 947 | int got = 0; | 954 | int got = 0; |
| 948 | char *buffer = NULL; | 955 | const unsigned char *buffer = NULL; |
| 949 | luaL_Buffer b; | 956 | luaL_Buffer b; |
| 950 | *end = start; | ||
| 951 | luaL_buffinit(L, &b); | 957 | luaL_buffinit(L, &b); |
| 952 | while (wanted > 0) { | 958 | while (wanted > 0) { |
| 953 | if(!read_or_timeout(sock, time_since(start))) { | 959 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { |
| 954 | #ifdef _DEBUG | ||
| 955 | *end = get_time(); | ||
| 956 | #endif | ||
| 957 | *err = NET_TIMEOUT; | ||
| 958 | luaL_pushresult(&b); | 960 | luaL_pushresult(&b); |
| 959 | return; | 961 | return NET_TIMEOUT; |
| 960 | } | 962 | } |
| 961 | #ifdef _DEBUG | 963 | buffer = bf_receive(sock, &got); |
| 962 | *end = get_time(); | ||
| 963 | #endif | ||
| 964 | buffer = luaL_prepbuffer(&b); | ||
| 965 | got = recv(sock->sock, buffer, MIN(wanted, LUAL_BUFFERSIZE), 0); | ||
| 966 | #ifdef _DEBUG_BLOCK | ||
| 967 | printf("luasocket: wanted %d, got %d, %dms elapsed\n", wanted, got, time_since(start)); | ||
| 968 | #endif | ||
| 969 | if (got <= 0) { | 964 | if (got <= 0) { |
| 970 | *err = NET_CLOSED; | ||
| 971 | luaL_pushresult(&b); | 965 | luaL_pushresult(&b); |
| 972 | return; | 966 | return NET_CLOSED; |
| 973 | } | 967 | } |
| 968 | got = min(got, wanted); | ||
| 969 | luaL_addlstring(&b, buffer, got); | ||
| 970 | bf_skip(sock, got); | ||
| 974 | wanted -= got; | 971 | wanted -= got; |
| 975 | luaL_addsize(&b, got); | ||
| 976 | } | 972 | } |
| 977 | *err = NET_DONE; | ||
| 978 | luaL_pushresult(&b); | 973 | luaL_pushresult(&b); |
| 974 | return NET_DONE; | ||
| 979 | } | 975 | } |
| 980 | 976 | ||
| 981 | /*-------------------------------------------------------------------------*\ | 977 | /*-------------------------------------------------------------------------*\ |
| 982 | * Reads everything until the connection is closed | 978 | * Reads everything until the connection is closed |
| 983 | * Input | 979 | * Input |
| 984 | * sock: socket structure being used in operation | 980 | * sock: socket structure being used in operation |
| 985 | * start: time the operation started, in ms | ||
| 986 | * Output | ||
| 987 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | ||
| 988 | * Result | 981 | * Result |
| 989 | * a string is pushed into the Lua stack with the line just read | 982 | * operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED |
| 990 | \*-------------------------------------------------------------------------*/ | 983 | \*-------------------------------------------------------------------------*/ |
| 991 | static void receive_all(lua_State *L, p_sock sock, int start, | 984 | static int receive_all(lua_State *L, p_sock sock) |
| 992 | int *err, int *end) | ||
| 993 | { | 985 | { |
| 994 | int got; | 986 | int got = 0; |
| 995 | char *buffer; | 987 | const unsigned char *buffer = NULL; |
| 996 | luaL_Buffer b; | 988 | luaL_Buffer b; |
| 997 | *end = start; | ||
| 998 | luaL_buffinit(L, &b); | 989 | luaL_buffinit(L, &b); |
| 999 | for ( ;; ) { | 990 | for ( ;; ) { |
| 1000 | buffer = luaL_prepbuffer(&b); | 991 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { |
| 1001 | if (read_or_timeout(sock, time_since(start))) { | 992 | buffer = bf_receive(sock, &got); |
| 1002 | #ifdef _DEBUG | ||
| 1003 | *end = get_time(); | ||
| 1004 | #endif | ||
| 1005 | got = recv(sock->sock, buffer, LUAL_BUFFERSIZE, 0); | ||
| 1006 | if (got <= 0) { | 993 | if (got <= 0) { |
| 1007 | *err = NET_DONE; | 994 | luaL_pushresult(&b); |
| 1008 | break; | 995 | return NET_DONE; |
| 1009 | } | 996 | } |
| 1010 | luaL_addsize(&b, got); | 997 | luaL_addlstring(&b, buffer, got); |
| 1011 | } else { | 998 | } else { |
| 1012 | *err = NET_TIMEOUT; | 999 | luaL_pushresult(&b); |
| 1013 | break; | 1000 | return NET_TIMEOUT; |
| 1014 | } | 1001 | } |
| 1015 | } | 1002 | } |
| 1016 | luaL_pushresult(&b); | ||
| 1017 | } | 1003 | } |
| 1018 | 1004 | ||
| 1019 | /*-------------------------------------------------------------------------*\ | 1005 | /*-------------------------------------------------------------------------*\ |
| 1020 | * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF | 1006 | * Reads a line terminated by a CR LF pair or just by a LF. The CR and LF |
| 1021 | * are not returned by the function. All operations are non-blocking and the | 1007 | * are not returned by the function and are discarded from the stream. All |
| 1022 | * function respects the timeout values in sock. | 1008 | * operations are non-blocking and the function respects the timeout |
| 1009 | * values in sock. | ||
| 1023 | * Input | 1010 | * Input |
| 1024 | * sock: socket structure being used in operation | 1011 | * sock: socket structure being used in operation |
| 1025 | * wanted: number of bytes in buffer | ||
| 1026 | * start: time the operation started, in ms | ||
| 1027 | * Output | ||
| 1028 | * data: pointer to an internal buffer containing the data read | ||
| 1029 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | ||
| 1030 | * Result | 1012 | * Result |
| 1031 | * a string is pushed into the Lua stack with the line just read | 1013 | * operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED |
| 1032 | \*-------------------------------------------------------------------------*/ | 1014 | \*-------------------------------------------------------------------------*/ |
| 1033 | static void receive_dosline(lua_State *L, p_sock sock, int start, | 1015 | static int receive_dosline(lua_State *L, p_sock sock) |
| 1034 | int *err, int *end) | ||
| 1035 | { | 1016 | { |
| 1036 | char c = ' '; | 1017 | int got = 0; |
| 1037 | long got = 0; | 1018 | const unsigned char *buffer = NULL; |
| 1038 | luaL_Buffer b; | 1019 | luaL_Buffer b; |
| 1039 | *end = start; | ||
| 1040 | luaL_buffinit(L, &b); | 1020 | luaL_buffinit(L, &b); |
| 1041 | for ( ;; ) { | 1021 | for ( ;; ) { |
| 1042 | if (read_or_timeout(sock, time_since(start))) { | 1022 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { |
| 1043 | #ifdef _DEBUG | 1023 | luaL_pushresult(&b); |
| 1044 | *end = get_time(); | 1024 | return NET_TIMEOUT; |
| 1045 | #endif | 1025 | } |
| 1046 | got = recv(sock->sock, &c, 1, 0); | 1026 | buffer = bf_receive(sock, &got); |
| 1047 | if (got <= 0) { | 1027 | if (got > 0) { |
| 1048 | *err = NET_CLOSED; | 1028 | int len = 0, end = 1; |
| 1049 | break; | 1029 | while (len < got) { |
| 1050 | } | 1030 | if (buffer[len] == '\n') { /* found eol */ |
| 1051 | if (c != '\n') { | 1031 | if (len > 0 && buffer[len-1] == '\r') { |
| 1052 | if (c != '\r') luaL_putchar(&b, c); | 1032 | end++; len--; |
| 1053 | } else { | 1033 | } |
| 1054 | *err = NET_DONE; | 1034 | luaL_addlstring(&b, buffer, len); |
| 1055 | break; | 1035 | bf_skip(sock, len + end); /* skip '\r\n' in stream */ |
| 1036 | luaL_pushresult(&b); | ||
| 1037 | return NET_DONE; | ||
| 1038 | } | ||
| 1039 | len++; | ||
| 1056 | } | 1040 | } |
| 1041 | luaL_addlstring(&b, buffer, got); | ||
| 1042 | bf_skip(sock, got); | ||
| 1057 | } else { | 1043 | } else { |
| 1058 | *err = NET_TIMEOUT; | 1044 | luaL_pushresult(&b); |
| 1059 | break; | 1045 | return NET_CLOSED; |
| 1060 | } | 1046 | } |
| 1061 | } | 1047 | } |
| 1062 | luaL_pushresult(&b); | ||
| 1063 | } | 1048 | } |
| 1064 | 1049 | ||
| 1065 | /*-------------------------------------------------------------------------*\ | 1050 | /*-------------------------------------------------------------------------*\ |
| 1066 | * Reads a line terminated by a LF character, which is not returned by | 1051 | * Reads a line terminated by a LF character, which is not returned by |
| 1067 | * the function. All operations are non-blocking and the function respects | 1052 | * the function, and is skipped in the stream. All operations are |
| 1068 | * the timeout values in sock. | 1053 | * non-blocking and the function respects the timeout values in sock. |
| 1069 | * Input | 1054 | * Input |
| 1070 | * sock: socket structure being used in operation | 1055 | * sock: socket structure being used in operation |
| 1071 | * wanted: number of bytes in buffer | ||
| 1072 | * start: time the operation started, in ms | ||
| 1073 | * Output | ||
| 1074 | * data: pointer to an internal buffer containing the data read | ||
| 1075 | * err: operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED | ||
| 1076 | * Returns | 1056 | * Returns |
| 1077 | * Number of bytes read | 1057 | * operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED |
| 1078 | \*-------------------------------------------------------------------------*/ | 1058 | \*-------------------------------------------------------------------------*/ |
| 1079 | static void receive_unixline(lua_State *L, p_sock sock, int start, | 1059 | static int receive_unixline(lua_State *L, p_sock sock) |
| 1080 | int *err, int *end) | ||
| 1081 | { | 1060 | { |
| 1082 | char c = ' '; | 1061 | int got = 0; |
| 1083 | long got = 0; | 1062 | const unsigned char *buffer = NULL; |
| 1084 | long size = 0; | ||
| 1085 | luaL_Buffer b; | 1063 | luaL_Buffer b; |
| 1086 | *end = start; | ||
| 1087 | luaL_buffinit(L, &b); | 1064 | luaL_buffinit(L, &b); |
| 1088 | for ( ;; ) { | 1065 | for ( ;; ) { |
| 1089 | if (read_or_timeout(sock, time_since(start))) { | 1066 | if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) { |
| 1090 | #ifdef _DEBUG | 1067 | luaL_pushresult(&b); |
| 1091 | *end = get_time(); | 1068 | return NET_TIMEOUT; |
| 1092 | #endif | 1069 | } |
| 1093 | got = recv(sock->sock, &c, 1, 0); | 1070 | buffer = bf_receive(sock, &got); |
| 1094 | if (got <= 0) { | 1071 | if (got > 0) { |
| 1095 | *err = NET_CLOSED; | 1072 | int len = 0; |
| 1096 | break; | 1073 | while (len < got) { |
| 1097 | } | 1074 | if (buffer[len] == '\n') { /* found eol */ |
| 1098 | if (c != '\n') { | 1075 | luaL_addlstring(&b, buffer, len); |
| 1099 | luaL_putchar(&b, c); | 1076 | bf_skip(sock, len + 1); /* skip '\n' in stream */ |
| 1100 | size++; | 1077 | luaL_pushresult(&b); |
| 1101 | } else { | 1078 | return NET_DONE; |
| 1102 | *err = NET_DONE; | 1079 | } |
| 1103 | break; | 1080 | len++; |
| 1104 | } | 1081 | } |
| 1082 | luaL_addlstring(&b, buffer, got); | ||
| 1083 | bf_skip(sock, got); | ||
| 1105 | } else { | 1084 | } else { |
| 1106 | *err = NET_TIMEOUT; | 1085 | luaL_pushresult(&b); |
| 1107 | break; | 1086 | return NET_CLOSED; |
| 1108 | } | 1087 | } |
| 1109 | } | 1088 | } |
| 1110 | luaL_pushresult(&b); | ||
| 1111 | } | 1089 | } |
| 1112 | 1090 | ||
| 1113 | /*-------------------------------------------------------------------------*\ | 1091 | /*-------------------------------------------------------------------------*\ |
| @@ -1204,15 +1182,6 @@ static int wsock_open(void) | |||
| 1204 | return 1; | 1182 | return 1; |
| 1205 | } | 1183 | } |
| 1206 | 1184 | ||
| 1207 | /*-------------------------------------------------------------------------*\ | ||
| 1208 | * Gets time in ms, relative to system startup. | ||
| 1209 | * Returns | ||
| 1210 | * time in ms. | ||
| 1211 | \*-------------------------------------------------------------------------*/ | ||
| 1212 | static int get_time(void) | ||
| 1213 | { | ||
| 1214 | return GetTickCount(); | ||
| 1215 | } | ||
| 1216 | 1185 | ||
| 1217 | /*-------------------------------------------------------------------------*\ | 1186 | /*-------------------------------------------------------------------------*\ |
| 1218 | * Put socket into blocking mode. | 1187 | * Put socket into blocking mode. |
| @@ -1304,27 +1273,13 @@ static char *connect_strerror(void) | |||
| 1304 | * BSD specific functions. | 1273 | * BSD specific functions. |
| 1305 | \*=========================================================================*/ | 1274 | \*=========================================================================*/ |
| 1306 | /*-------------------------------------------------------------------------*\ | 1275 | /*-------------------------------------------------------------------------*\ |
| 1307 | * Gets time in ms, relative to system startup. | ||
| 1308 | * Returns | ||
| 1309 | * time in ms. | ||
| 1310 | \*-------------------------------------------------------------------------*/ | ||
| 1311 | static int get_time(void) | ||
| 1312 | { | ||
| 1313 | struct tms t; | ||
| 1314 | return (times(&t)*1000)/CLK_TCK; | ||
| 1315 | } | ||
| 1316 | |||
| 1317 | /*-------------------------------------------------------------------------*\ | ||
| 1318 | * Put socket into blocking mode. | 1276 | * Put socket into blocking mode. |
| 1319 | \*-------------------------------------------------------------------------*/ | 1277 | \*-------------------------------------------------------------------------*/ |
| 1320 | static void set_blocking(p_sock sock) | 1278 | static void set_blocking(p_sock sock) |
| 1321 | { | 1279 | { |
| 1322 | if (!sock->blocking) { | 1280 | int flags = fcntl(sock->sock, F_GETFL, 0); |
| 1323 | int flags = fcntl(sock->sock, F_GETFL, 0); | 1281 | flags &= (~(O_NONBLOCK)); |
| 1324 | flags &= (~(O_NONBLOCK)); | 1282 | fcntl(sock->sock, F_SETFL, flags); |
| 1325 | fcntl(sock->sock, F_SETFL, flags); | ||
| 1326 | sock->blocking = 1; | ||
| 1327 | } | ||
| 1328 | } | 1283 | } |
| 1329 | 1284 | ||
| 1330 | /*-------------------------------------------------------------------------*\ | 1285 | /*-------------------------------------------------------------------------*\ |
| @@ -1332,12 +1287,9 @@ static void set_blocking(p_sock sock) | |||
| 1332 | \*-------------------------------------------------------------------------*/ | 1287 | \*-------------------------------------------------------------------------*/ |
| 1333 | static void set_nonblocking(p_sock sock) | 1288 | static void set_nonblocking(p_sock sock) |
| 1334 | { | 1289 | { |
| 1335 | if (sock->blocking) { | 1290 | int flags = fcntl(sock->sock, F_GETFL, 0); |
| 1336 | int flags = fcntl(sock->sock, F_GETFL, 0); | 1291 | flags |= O_NONBLOCK; |
| 1337 | flags |= O_NONBLOCK; | 1292 | fcntl(sock->sock, F_SETFL, flags); |
| 1338 | fcntl(sock->sock, F_SETFL, flags); | ||
| 1339 | sock->blocking = 0; | ||
| 1340 | } | ||
| 1341 | } | 1293 | } |
| 1342 | 1294 | ||
| 1343 | /*-------------------------------------------------------------------------*\ | 1295 | /*-------------------------------------------------------------------------*\ |
