aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2001-01-13 07:10:00 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2001-01-13 07:10:00 +0000
commit41643c2643751de17125da4c23b616840dc0f1e3 (patch)
tree1fc50142e5fcab1dae39e1c91418276961019840 /src
parent17c4d1c30544f0ed638879835f179ada96249868 (diff)
downloadluasocket-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.c582
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\*-------------------------------------------------------------------------*/
125typedef struct t_sock { 124typedef 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;
131typedef t_sock *p_sock; 140typedef 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);
157static int net_timeout(lua_State *L); 163static int net_timeout(lua_State *L);
158static int net_close(lua_State *L); 164static int net_close(lua_State *L);
159 165
166/* buffered I/O management */
167static const unsigned char *bf_receive(p_sock sock, int *length);
168static void bf_skip(p_sock sock, int length);
169static int bf_isempty(p_sock sock);
170
171/* timeout management */
172static int tm_timedout(p_sock sock, int mode);
173static int tm_gettimeleft(p_sock sock);
174static int tm_gettime(void);
175static void tm_markstart(p_sock sock);
176
177/* I/O */
178static int send_raw(p_sock sock, const char *data, int wanted, int *err);
179static int receive_raw(lua_State *L, p_sock sock, int wanted);
180static int receive_dosline(lua_State *L, p_sock sock);
181static int receive_unixline(lua_State *L, p_sock sock);
182static int receive_all(lua_State *L, p_sock sock);
183
160/* fallbacks */ 184/* fallbacks */
161static int server_gettable(lua_State *L); 185static int server_gettable(lua_State *L);
162static int client_gettable(lua_State *L); 186static int client_gettable(lua_State *L);
@@ -170,7 +194,7 @@ static p_sock check_sock(lua_State *L, int numArg, int server_tag,
170static void pop_tags(lua_State *L, int *client_tag, int *server_tag); 194static void pop_tags(lua_State *L, int *client_tag, int *server_tag);
171static void push_tags(lua_State *L, int client_tag, int server_tag); 195static void push_tags(lua_State *L, int client_tag, int server_tag);
172 196
173/* result handling routines */ 197/* error code translations functions */
174static char *host_strerror(void); 198static char *host_strerror(void);
175static char *bind_strerror(void); 199static char *bind_strerror(void);
176static char *sock_strerror(void); 200static char *sock_strerror(void);
@@ -181,7 +205,6 @@ static void push_client(lua_State *L, p_sock sock, int client_tag);
181static void push_server(lua_State *L, p_sock sock, int server_tag); 205static void push_server(lua_State *L, p_sock sock, int server_tag);
182 206
183/* plataform specific functions */ 207/* plataform specific functions */
184static int get_time(void);
185static void set_blocking(p_sock sock); 208static void set_blocking(p_sock sock);
186static void set_nonblocking(p_sock sock); 209static void set_nonblocking(p_sock sock);
187 210
@@ -190,19 +213,6 @@ static p_sock create_sock(void);
190static p_sock create_tcpsock(void); 213static p_sock create_tcpsock(void);
191static int fill_sockaddr(struct sockaddr_in *server, const char *hostname, 214static int fill_sockaddr(struct sockaddr_in *server, const char *hostname,
192 unsigned short port); 215 unsigned short port);
193static int get_timeout(p_sock sock, int elapsed);
194static int read_or_timeout(p_sock sock, int elapsed);
195static int write_or_timeout(p_sock sock, int elapsed);
196static int send_raw(p_sock sock, const char *data, int wanted,
197 int start, int *err, int *end);
198static void receive_raw(lua_State *L, p_sock sock, int wanted,
199 int start, int *err, int *end);
200static void receive_dosline(lua_State *L, p_sock sock, int start,
201 int *err, int *end);
202static void receive_unixline(lua_State *L, p_sock sock, int start,
203 int *err, int *end);
204static 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,
214static int net_time(lua_State *L); 224static int net_time(lua_State *L);
215static int net_time(lua_State *L) 225static 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);
474printf("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
485printf("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);
490lua_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\*-------------------------------------------------------------------------*/
510static int net_receive(lua_State *L) 514static 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);
523printf("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
566printf("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);
571lua_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\*-------------------------------------------------------------------------*/
599static int client_gettable(lua_State *L) 596static 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)
700static p_sock create_sock(void) 697static 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\*-------------------------------------------------------------------------*/
789static int get_timeout(p_sock sock, int elapsed) 783static 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\*-------------------------------------------------------------------------*/
814static int read_or_timeout(p_sock sock, int elapsed) 808static 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\*-------------------------------------------------------------------------*/
841static 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\*-------------------------------------------------------------------------*/
848static int write_or_timeout(p_sock sock, int elapsed) 856static 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 */ 867static 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\*-------------------------------------------------------------------------*/
883static 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\*-------------------------------------------------------------------------*/
900static 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\*-------------------------------------------------------------------------*/
886static int send_raw(p_sock sock, const char *data, int wanted, 922static 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
921printf("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)) 952static int receive_raw(lua_State *L, p_sock sock, int wanted)
944static 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
967printf("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\*-------------------------------------------------------------------------*/
991static void receive_all(lua_State *L, p_sock sock, int start, 984static 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\*-------------------------------------------------------------------------*/
1033static void receive_dosline(lua_State *L, p_sock sock, int start, 1015static 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\*-------------------------------------------------------------------------*/
1079static void receive_unixline(lua_State *L, p_sock sock, int start, 1059static 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\*-------------------------------------------------------------------------*/
1212static 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\*-------------------------------------------------------------------------*/
1311static 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\*-------------------------------------------------------------------------*/
1320static void set_blocking(p_sock sock) 1278static 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\*-------------------------------------------------------------------------*/
1333static void set_nonblocking(p_sock sock) 1288static 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/*-------------------------------------------------------------------------*\