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 | /*-------------------------------------------------------------------------*\ |