aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2001-03-12 20:04:25 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2001-03-12 20:04:25 +0000
commitf643710fa23c0d1f55a1ca3af432c3654da2e0da (patch)
tree1ef3cad0fba4734338e6584d097cff670ac95d25 /src
parent794418cd7b18a812c5b0b9b91eea2fecc2c6387d (diff)
downloadluasocket-f643710fa23c0d1f55a1ca3af432c3654da2e0da.tar.gz
luasocket-f643710fa23c0d1f55a1ca3af432c3654da2e0da.tar.bz2
luasocket-f643710fa23c0d1f55a1ca3af432c3654da2e0da.zip
Found a new way to define global version of table methods using only ~15
lines of code. So, they are back. Added '*w' word receive pattern.
Diffstat (limited to 'src')
-rw-r--r--src/luasocket.c366
1 files changed, 222 insertions, 144 deletions
diff --git a/src/luasocket.c b/src/luasocket.c
index c4f51bd..1f9780d 100644
--- a/src/luasocket.c
+++ b/src/luasocket.c
@@ -9,9 +9,9 @@
9* of the IPv4 Socket layer available to Lua scripts. 9* of the IPv4 Socket layer available to Lua scripts.
10* 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,
11* 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
12* and simple server connections. 12* and server connections.
13* The provided IO routines, send and receive, follow the Lua style, being 13* The provided IO routines, send and receive, follow the Lua style, being
14* very similar to the read and write functions found in that language. 14* very similar to the standard Lua read and write functions.
15* The module implements both a BSD bind and a Winsock2 bind, and has 15* The module implements both a BSD bind and a Winsock2 bind, and has
16* been tested on several Unix flavors, as well as Windows 98 and NT. 16* been tested on several Unix flavors, as well as Windows 98 and NT.
17\*=========================================================================*/ 17\*=========================================================================*/
@@ -19,16 +19,13 @@
19/*=========================================================================*\ 19/*=========================================================================*\
20* Common include files 20* Common include files
21\*=========================================================================*/ 21\*=========================================================================*/
22#include <assert.h>
23#include <errno.h> 22#include <errno.h>
24#include <signal.h> 23#include <signal.h>
25#include <stdio.h>
26#include <stdlib.h> 24#include <stdlib.h>
27#include <string.h> 25#include <ctype.h>
28 26
29#include <lauxlib.h> 27#include <lauxlib.h>
30#include <lua.h> 28#include <lua.h>
31#include <lualib.h>
32 29
33#include "luasocket.h" 30#include "luasocket.h"
34 31
@@ -161,6 +158,10 @@ static int global_toip(lua_State *L);
161static int global_tohostname(lua_State *L); 158static int global_tohostname(lua_State *L);
162static int global_udpsocket(lua_State *L); 159static int global_udpsocket(lua_State *L);
163 160
161#ifndef LUASOCKET_NOGLOBALS
162static int global_calltable(lua_State *L);
163#endif
164
164/* luasocket table method API functions */ 165/* luasocket table method API functions */
165static int table_tcpaccept(lua_State *L); 166static int table_tcpaccept(lua_State *L);
166static int table_tcpsend(lua_State *L); 167static int table_tcpsend(lua_State *L);
@@ -187,6 +188,7 @@ static void tm_markstart(p_sock sock);
187/* I/O */ 188/* I/O */
188static int send_raw(p_sock sock, const char *data, int wanted, int *err); 189static int send_raw(p_sock sock, const char *data, int wanted, int *err);
189static int receive_raw(lua_State *L, p_sock sock, int wanted); 190static int receive_raw(lua_State *L, p_sock sock, int wanted);
191static int receive_word(lua_State *L, p_sock sock);
190static int receive_dosline(lua_State *L, p_sock sock); 192static int receive_dosline(lua_State *L, p_sock sock);
191static int receive_unixline(lua_State *L, p_sock sock); 193static int receive_unixline(lua_State *L, p_sock sock);
192static int receive_all(lua_State *L, p_sock sock); 194static int receive_all(lua_State *L, p_sock sock);
@@ -537,6 +539,21 @@ static int table_udpsendto(lua_State *L)
537} 539}
538 540
539/*-------------------------------------------------------------------------*\ 541/*-------------------------------------------------------------------------*\
542* Global function that calls corresponding table method.
543\*-------------------------------------------------------------------------*/
544#ifndef LUASOCKET_NOGLOBALS
545int global_calltable(lua_State *L)
546{
547 p_tags tags = pop_tags(L);
548 if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object");
549 lua_gettable(L, 1);
550 lua_insert(L, 1);
551 lua_call(L, lua_gettop(L)-1, LUA_MULTRET);
552 return lua_gettop(L);
553}
554#endif
555
556/*-------------------------------------------------------------------------*\
540* Waits for a set of sockets until a condition is met or timeout. 557* Waits for a set of sockets until a condition is met or timeout.
541* Lua Input: {input}, {output} [, timeout] 558* Lua Input: {input}, {output} [, timeout]
542* {input}: table of sockets to be tested for input 559* {input}: table of sockets to be tested for input
@@ -549,103 +566,105 @@ static int table_udpsendto(lua_State *L)
549\*-------------------------------------------------------------------------*/ 566\*-------------------------------------------------------------------------*/
550int global_select(lua_State *L) 567int global_select(lua_State *L)
551{ 568{
552 p_tags tags = pop_tags(L); 569 p_tags tags = pop_tags(L);
553 int ms = lua_isnil(L, 3) ? -1 : (int) (luaL_opt_number(L, 3, -1) * 1000); 570 int ms = lua_isnil(L, 3) ? -1 : (int) (luaL_opt_number(L, 3, -1) * 1000);
554 fd_set readfds, *prfds = NULL, writefds, *pwfds = NULL; 571 fd_set readfds, *prfds = NULL, writefds, *pwfds = NULL;
555 struct timeval tm, *ptm = NULL; 572 struct timeval tm, *ptm = NULL;
556 int ret, s, max = -1; 573 int ret;
557 int byfds, canread, canwrite; 574 unsigned max = 0;
558 /* reset the file descriptor sets */ 575 SOCKET s;
576 int byfds, canread, canwrite;
577 /* reset the file descriptor sets */
559 FD_ZERO(&readfds); FD_ZERO(&writefds); 578 FD_ZERO(&readfds); FD_ZERO(&writefds);
560 /* all sockets, indexed by socket number, for internal use */ 579 /* all sockets, indexed by socket number, for internal use */
561 lua_newtable(L); byfds = lua_gettop(L); 580 lua_newtable(L); byfds = lua_gettop(L);
562 /* readable sockets table to be returned */ 581 /* readable sockets table to be returned */
563 lua_newtable(L); canread = lua_gettop(L); 582 lua_newtable(L); canread = lua_gettop(L);
564 /* writable sockets table to be returned */ 583 /* writable sockets table to be returned */
565 lua_newtable(L); canwrite = lua_gettop(L); 584 lua_newtable(L); canwrite = lua_gettop(L);
566 /* get sockets we will test for readability into fd_set */ 585 /* get sockets we will test for readability into fd_set */
567 if (!lua_isnil(L, 1)) { 586 if (!lua_isnil(L, 1)) {
568 lua_pushnil(L); 587 lua_pushnil(L);
569 while (lua_next(L, 1)) { 588 while (lua_next(L, 1)) {
570 if (lua_tag(L, -1) == tags->table) { 589 if (lua_tag(L, -1) == tags->table) {
571 p_sock sock = get_sock(L, -1, tags, NULL); 590 p_sock sock = get_sock(L, -1, tags, NULL);
572 lua_pushnumber(L, sock->sock); 591 lua_pushnumber(L, sock->sock);
573 lua_pushvalue(L, -2); 592 lua_pushvalue(L, -2);
574 lua_settable(L, byfds); 593 lua_settable(L, byfds);
575 if (sock->sock > max) max = sock->sock; 594 if (sock->sock > max) max = sock->sock;
576 /* a socket can have unread data in our internal buffer. in 595 /* a socket can have unread data in our internal buffer. in
577 * that case, we only call select to find out which of the 596 * that case, we only call select to find out which of the
578 * other sockets can be written to or read from immediately. */ 597 * other sockets can be written to or read from immediately. */
579 if (!bf_isempty(sock)) { 598 if (!bf_isempty(sock)) {
580 ms = 0; 599 ms = 0;
581 lua_pushnumber(L, lua_getn(L, canread) + 1); 600 lua_pushnumber(L, lua_getn(L, canread) + 1);
582 lua_pushvalue(L, -2); 601 lua_pushvalue(L, -2);
583 lua_settable(L, canread); 602 lua_settable(L, canread);
584 } else { 603 } else {
585 FD_SET(sock->sock, &readfds); 604 FD_SET(sock->sock, &readfds);
586 prfds = &readfds; 605 prfds = &readfds;
587 } 606 }
588 } 607 }
589 /* get rid of lua_next value and expose index */ 608 /* get rid of lua_next value and expose index */
590 lua_pop(L, 1); 609 lua_pop(L, 1);
591 } 610 }
592 } 611 }
593 /* get sockets we will test for writability into fd_set */ 612 /* get sockets we will test for writability into fd_set */
594 if (!lua_isnil(L, 2)) { 613 if (!lua_isnil(L, 2)) {
595 lua_pushnil(L); 614 lua_pushnil(L);
596 while (lua_next(L, 2)) { 615 while (lua_next(L, 2)) {
597 if (lua_tag(L, -1) == tags->table) { 616 if (lua_tag(L, -1) == tags->table) {
598 p_sock sock = get_sock(L, -1, tags, NULL); 617 p_sock sock = get_sock(L, -1, tags, NULL);
599 lua_pushnumber(L, sock->sock); 618 lua_pushnumber(L, sock->sock);
600 lua_pushvalue(L, -2); 619 lua_pushvalue(L, -2);
601 lua_settable(L, byfds); 620 lua_settable(L, byfds);
602 if (sock->sock > max) max = sock->sock; 621 if (sock->sock > max) max = sock->sock;
603 FD_SET(sock->sock, &writefds); 622 FD_SET(sock->sock, &writefds);
604 pwfds = &writefds; 623 pwfds = &writefds;
605 } 624 }
606 /* get rid of lua_next value and expose index */ 625 /* get rid of lua_next value and expose index */
607 lua_pop(L, 1); 626 lua_pop(L, 1);
608 } 627 }
609 } 628 }
610 max++; 629 max++;
611 /* configure timeout value */ 630 /* configure timeout value */
612 if (ms >= 0) { 631 if (ms >= 0) {
613 ptm = &tm; /* ptm == NULL when we don't have timeout */ 632 ptm = &tm; /* ptm == NULL when we don't have timeout */
614 /* fill timeval structure */ 633 /* fill timeval structure */
615 tm.tv_sec = ms / 1000; 634 tm.tv_sec = ms / 1000;
616 tm.tv_usec = (ms % 1000) * 1000; 635 tm.tv_usec = (ms % 1000) * 1000;
617 } 636 }
618 /* see if we can read, write or if we timedout */ 637 /* see if we can read, write or if we timedout */
619 ret = select(max, prfds, pwfds, NULL, ptm); 638 ret = select(max, prfds, pwfds, NULL, ptm);
620 /* did we timeout? */ 639 /* did we timeout? */
621 if (ret <= 0 && ms > 0) { 640 if (ret <= 0 && ms > 0) {
622 push_error(L, NET_TIMEOUT); 641 push_error(L, NET_TIMEOUT);
623 return 3; 642 return 3;
624 } 643 }
625 /* collect readable sockets */ 644 /* collect readable sockets */
626 if (prfds) { 645 if (prfds) {
627 for (s = 0; s < max; s++) { 646 for (s = 0; s < max; s++) {
628 if (FD_ISSET(s, prfds)) { 647 if (FD_ISSET(s, prfds)) {
629 lua_pushnumber(L, lua_getn(L, canread) + 1); 648 lua_pushnumber(L, lua_getn(L, canread) + 1);
630 lua_pushnumber(L, s); 649 lua_pushnumber(L, s);
631 lua_gettable(L, byfds); 650 lua_gettable(L, byfds);
632 lua_settable(L, canread); 651 lua_settable(L, canread);
633 } 652 }
634 } 653 }
635 } 654 }
636 /* collect writable sockets */ 655 /* collect writable sockets */
637 if (pwfds) { 656 if (pwfds) {
638 for (s = 0; s < max; s++) { 657 for (s = 0; s < max; s++) {
639 if (FD_ISSET(s, pwfds)) { 658 if (FD_ISSET(s, pwfds)) {
640 lua_pushnumber(L, lua_getn(L, canwrite) + 1); 659 lua_pushnumber(L, lua_getn(L, canwrite) + 1);
641 lua_pushnumber(L, s); 660 lua_pushnumber(L, s);
642 lua_gettable(L, byfds); 661 lua_gettable(L, byfds);
643 lua_settable(L, canwrite); 662 lua_settable(L, canwrite);
644 } 663 }
645 } 664 }
646 } 665 }
647 lua_pushnil(L); 666 lua_pushnil(L);
648 return 3; 667 return 3;
649} 668}
650 669
651/*-------------------------------------------------------------------------*\ 670/*-------------------------------------------------------------------------*\
@@ -821,7 +840,7 @@ static int table_udpreceive(lua_State *L)
821\*-------------------------------------------------------------------------*/ 840\*-------------------------------------------------------------------------*/
822static int table_tcpreceive(lua_State *L) 841static int table_tcpreceive(lua_State *L)
823{ 842{
824 static const char *const modenames[] = {"*l", "*lu", "*a", NULL}; 843 static const char *const modenames[] = {"*l", "*lu", "*a", "*w", NULL};
825 const char *mode; 844 const char *mode;
826 int err = NET_DONE; 845 int err = NET_DONE;
827 int arg; 846 int arg;
@@ -850,17 +869,13 @@ static int table_tcpreceive(lua_State *L)
850 /* get next pattern */ 869 /* get next pattern */
851 switch (luaL_findstring(mode, modenames)) { 870 switch (luaL_findstring(mode, modenames)) {
852 /* DOS line mode */ 871 /* DOS line mode */
853 case 0: 872 case 0: err = receive_dosline(L, sock); break;
854 err = receive_dosline(L, sock);
855 break;
856 /* Unix line mode */ 873 /* Unix line mode */
857 case 1: 874 case 1: err = receive_unixline(L, sock); break;
858 err = receive_unixline(L, sock);
859 break;
860 /* until closed mode */ 875 /* until closed mode */
861 case 2: 876 case 2: err = receive_all(L, sock); break;
862 err = receive_all(L, sock); 877 /* word */
863 break; 878 case 3: err = receive_word(L, sock); break;
864 /* else it is an error */ 879 /* else it is an error */
865 default: 880 default:
866 luaL_arg_check(L, 0, arg, "invalid receive pattern"); 881 luaL_arg_check(L, 0, arg, "invalid receive pattern");
@@ -1431,7 +1446,7 @@ static int receive_all(lua_State *L, p_sock sock)
1431\*-------------------------------------------------------------------------*/ 1446\*-------------------------------------------------------------------------*/
1432static int receive_dosline(lua_State *L, p_sock sock) 1447static int receive_dosline(lua_State *L, p_sock sock)
1433{ 1448{
1434 int got = 0; 1449 int got, pos;
1435 const unsigned char *buffer = NULL; 1450 const unsigned char *buffer = NULL;
1436 luaL_Buffer b; 1451 luaL_Buffer b;
1437 luaL_buffinit(L, &b); 1452 luaL_buffinit(L, &b);
@@ -1441,26 +1456,21 @@ static int receive_dosline(lua_State *L, p_sock sock)
1441 return NET_TIMEOUT; 1456 return NET_TIMEOUT;
1442 } 1457 }
1443 buffer = bf_receive(sock, &got); 1458 buffer = bf_receive(sock, &got);
1444 if (got > 0) { 1459 if (got <= 0) {
1445 int len = 0, end = 1; 1460 luaL_pushresult(&b);
1446 while (len < got) {
1447 if (buffer[len] == '\n') { /* found eol */
1448 if (len > 0 && buffer[len-1] == '\r') {
1449 end++; len--;
1450 }
1451 luaL_addlstring(&b, buffer, len);
1452 bf_skip(sock, len + end); /* skip '\r\n' in stream */
1453 luaL_pushresult(&b);
1454 return NET_DONE;
1455 }
1456 len++;
1457 }
1458 luaL_addlstring(&b, buffer, got);
1459 bf_skip(sock, got);
1460 } else {
1461 luaL_pushresult(&b);
1462 return NET_CLOSED; 1461 return NET_CLOSED;
1463 } 1462 }
1463 pos = 0;
1464 while (pos < got && buffer[pos] != '\n') {
1465 /* we ignore all \r's */
1466 if (buffer[pos] != '\r') luaL_putchar(&b, buffer[pos]);
1467 pos++;
1468 }
1469 if (pos < got) {
1470 luaL_pushresult(&b);
1471 bf_skip(sock, pos+1); /* skip '\n' too */
1472 return NET_DONE;
1473 } else bf_skip(sock, pos);
1464 } 1474 }
1465} 1475}
1466 1476
@@ -1475,7 +1485,7 @@ static int receive_dosline(lua_State *L, p_sock sock)
1475\*-------------------------------------------------------------------------*/ 1485\*-------------------------------------------------------------------------*/
1476static int receive_unixline(lua_State *L, p_sock sock) 1486static int receive_unixline(lua_State *L, p_sock sock)
1477{ 1487{
1478 int got = 0; 1488 int got, pos;
1479 const unsigned char *buffer = NULL; 1489 const unsigned char *buffer = NULL;
1480 luaL_Buffer b; 1490 luaL_Buffer b;
1481 luaL_buffinit(L, &b); 1491 luaL_buffinit(L, &b);
@@ -1485,23 +1495,75 @@ static int receive_unixline(lua_State *L, p_sock sock)
1485 return NET_TIMEOUT; 1495 return NET_TIMEOUT;
1486 } 1496 }
1487 buffer = bf_receive(sock, &got); 1497 buffer = bf_receive(sock, &got);
1488 if (got > 0) { 1498 if (got <= 0) {
1489 int len = 0; 1499 luaL_pushresult(&b);
1490 while (len < got) { 1500 return NET_CLOSED;
1491 if (buffer[len] == '\n') { /* found eol */ 1501 }
1492 luaL_addlstring(&b, buffer, len); 1502 pos = 0;
1493 bf_skip(sock, len + 1); /* skip '\n' in stream */ 1503 while (pos < got && buffer[pos] != '\n') pos++;
1494 luaL_pushresult(&b); 1504 luaL_addlstring(&b, buffer, pos);
1495 return NET_DONE; 1505 if (pos < got) {
1496 } 1506 luaL_pushresult(&b);
1497 len++; 1507 bf_skip(sock, pos+1); /* skip '\n' too */
1498 } 1508 return NET_DONE;
1499 luaL_addlstring(&b, buffer, got); 1509 } else bf_skip(sock, pos);
1500 bf_skip(sock, got); 1510 }
1501 } else { 1511}
1512
1513/*-------------------------------------------------------------------------*\
1514* Reads a word (maximal sequence of non--white-space characters), skipping
1515* white-spaces if needed.
1516* Input
1517* sock: socket structure being used in operation
1518* Result
1519* operation error code. NET_DONE, NET_TIMEOUT or NET_CLOSED
1520\*-------------------------------------------------------------------------*/
1521static int receive_word(lua_State *L, p_sock sock)
1522{
1523 int pos, got;
1524 const unsigned char *buffer = NULL;
1525 luaL_Buffer b;
1526 luaL_buffinit(L, &b);
1527 /* skip leading white-spaces */
1528 for ( ;; ) {
1529 if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) {
1530 lua_pushstring(L, "");
1531 return NET_TIMEOUT;
1532 }
1533 buffer = bf_receive(sock, &got);
1534 if (got <= 0) {
1535 lua_pushstring(L, "");
1536 return NET_CLOSED;
1537 }
1538 pos = 0;
1539 while (pos < got && isspace(buffer[pos])) pos++;
1540 bf_skip(sock, pos);
1541 if (pos < got) {
1542 buffer += pos;
1543 got -= pos;
1544 pos = 0;
1545 break;
1546 }
1547 }
1548 /* capture word */
1549 for ( ;; ) {
1550 while (pos < got && !isspace(buffer[pos])) pos++;
1551 luaL_addlstring(&b, buffer, pos);
1552 bf_skip(sock, pos);
1553 if (pos < got) {
1554 luaL_pushresult(&b);
1555 return NET_DONE;
1556 }
1557 if (bf_isempty(sock) && tm_timedout(sock, TM_RECEIVE)) {
1558 luaL_pushresult(&b);
1559 return NET_TIMEOUT;
1560 }
1561 buffer = bf_receive(sock, &got);
1562 if (got <= 0) {
1502 luaL_pushresult(&b); 1563 luaL_pushresult(&b);
1503 return NET_CLOSED; 1564 return NET_CLOSED;
1504 } 1565 }
1566 pos = 0;
1505 } 1567 }
1506} 1568}
1507 1569
@@ -1514,7 +1576,7 @@ static int receive_unixline(lua_State *L, p_sock sock)
1514\*-------------------------------------------------------------------------*/ 1576\*-------------------------------------------------------------------------*/
1515void lua_socketlibopen(lua_State *L) 1577void lua_socketlibopen(lua_State *L)
1516{ 1578{
1517 static struct luaL_reg funcs[] = { 1579 struct luaL_reg funcs[] = {
1518 {"bind", global_tcpbind}, 1580 {"bind", global_tcpbind},
1519 {"connect", global_tcpconnect}, 1581 {"connect", global_tcpconnect},
1520 {"select", global_select}, 1582 {"select", global_select},
@@ -1552,6 +1614,22 @@ void lua_socketlibopen(lua_State *L)
1552 lua_pushcfunction(L, global_sleep); lua_setglobal(L, "sleep"); 1614 lua_pushcfunction(L, global_sleep); lua_setglobal(L, "sleep");
1553 lua_pushcfunction(L, global_time); lua_setglobal(L, "time"); 1615 lua_pushcfunction(L, global_time); lua_setglobal(L, "time");
1554#endif 1616#endif
1617#ifndef LUASOCKET_NOGLOBALS
1618 {
1619 char *global[] = {
1620 "accept", "close", "getpeername",
1621 "getsockname", "receive", "send",
1622 "receivefrom", "sendto"
1623 };
1624 unsigned int i;
1625 for (i = 0; i < sizeof(global)/sizeof(char *); i++) {
1626 lua_pushstring(L, global[i]);
1627 lua_pushuserdata(L, tags);
1628 lua_pushcclosure(L, global_calltable, 2);
1629 lua_setglobal(L, global[i]);
1630 }
1631 }
1632#endif
1555} 1633}
1556 1634
1557/*=========================================================================*\ 1635/*=========================================================================*\
@@ -1583,7 +1661,7 @@ static p_sock push_clienttable(lua_State *L, p_tags tags)
1583 if (!sock) return NULL; 1661 if (!sock) return NULL;
1584 lua_settag(L, tags->client); 1662 lua_settag(L, tags->client);
1585 lua_settable(L, -3); 1663 lua_settable(L, -3);
1586 sock->sock = -1; 1664 sock->sock = INVALID_SOCKET;
1587 sock->is_connected = 0; 1665 sock->is_connected = 0;
1588 sock->tm_block = -1; 1666 sock->tm_block = -1;
1589 sock->tm_return = -1; 1667 sock->tm_return = -1;