aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2001-04-23 22:37:55 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2001-04-23 22:37:55 +0000
commit8c6473577da993fb95ccd705214aa9dc11e8ca82 (patch)
tree5e435e89f715c9399b6944bbc5097556907a2996
parent561177a1dd111f05aa3edc4d0b89bf1341627027 (diff)
downloadluasocket-8c6473577da993fb95ccd705214aa9dc11e8ca82.tar.gz
luasocket-8c6473577da993fb95ccd705214aa9dc11e8ca82.tar.bz2
luasocket-8c6473577da993fb95ccd705214aa9dc11e8ca82.zip
Added support to UDP socket options.
-rw-r--r--src/luasocket.c216
1 files changed, 139 insertions, 77 deletions
diff --git a/src/luasocket.c b/src/luasocket.c
index 6512108..f144fce 100644
--- a/src/luasocket.c
+++ b/src/luasocket.c
@@ -159,7 +159,7 @@ static int global_tohostname(lua_State *L);
159static int global_udpsocket(lua_State *L); 159static int global_udpsocket(lua_State *L);
160 160
161#ifndef LUASOCKET_NOGLOBALS 161#ifndef LUASOCKET_NOGLOBALS
162static int global_calltable(lua_State *L); 162static int global_callfromtable(lua_State *L);
163#endif 163#endif
164 164
165/* luasocket table method API functions */ 165/* luasocket table method API functions */
@@ -219,6 +219,7 @@ static const char *udp_setpeername(p_sock sock, const char *address,
219 unsigned short port); 219 unsigned short port);
220static const char *udp_setsockname(p_sock sock, const char *address, 220static const char *udp_setsockname(p_sock sock, const char *address,
221 unsigned short port); 221 unsigned short port);
222static int set_option(lua_State *L, p_sock sock);
222static void set_reuseaddr(p_sock sock); 223static void set_reuseaddr(p_sock sock);
223static void set_blocking(p_sock sock); 224static void set_blocking(p_sock sock);
224static void set_nonblocking(p_sock sock); 225static void set_nonblocking(p_sock sock);
@@ -305,8 +306,6 @@ static int global_tcpconnect(lua_State *L)
305 306
306/*-------------------------------------------------------------------------*\ 307/*-------------------------------------------------------------------------*\
307* Creates a udp socket object and returns it to the Lua script. 308* Creates a udp socket object and returns it to the Lua script.
308* The timeout values are initialized as -1 so that the socket will block
309* at any IO operation.
310* Lua Returns 309* Lua Returns
311* On success: udp socket 310* On success: udp socket
312* On error: nil, followed by an error message 311* On error: nil, followed by an error message
@@ -314,8 +313,16 @@ static int global_tcpconnect(lua_State *L)
314static int global_udpsocket(lua_State *L) 313static int global_udpsocket(lua_State *L)
315{ 314{
316 p_tags tags = pop_tags(L); 315 p_tags tags = pop_tags(L);
316 int top = lua_gettop(L);
317 p_sock sock = push_udptable(L, tags); 317 p_sock sock = push_udptable(L, tags);
318 if (!sock) return 2; 318 if (!sock) return 2;
319 if (top >= 1 && lua_istable(L, 1)) {
320 lua_pushnil(L);
321 while (lua_next(L, 1)) {
322 if (!set_option(L, sock)) lua_error(L, "invalid socket option");
323 lua_pop(L, 1);
324 }
325 }
319 return 1; 326 return 1;
320} 327}
321 328
@@ -483,8 +490,8 @@ static int table_tcpsend(lua_State *L)
483 for (arg = 2; arg <= top; arg++) { /* skip self table */ 490 for (arg = 2; arg <= top; arg++) { /* skip self table */
484 int sent; 491 int sent;
485 size_t wanted; 492 size_t wanted;
486 const char *data = luaL_opt_lstr(L, arg, NULL, &wanted); 493 const char *data = luaL_opt_lstr(L, arg, NULL, &wanted);
487 if (!data || err != NET_DONE) break; 494 if (!data || err != NET_DONE) break;
488 err = send_raw(sock, data, wanted, &sent); 495 err = send_raw(sock, data, wanted, &sent);
489 total += sent; 496 total += sent;
490 } 497 }
@@ -542,14 +549,14 @@ static int table_udpsendto(lua_State *L)
542* Global function that calls corresponding table method. 549* Global function that calls corresponding table method.
543\*-------------------------------------------------------------------------*/ 550\*-------------------------------------------------------------------------*/
544#ifndef LUASOCKET_NOGLOBALS 551#ifndef LUASOCKET_NOGLOBALS
545int global_calltable(lua_State *L) 552int global_callfromtable(lua_State *L)
546{ 553{
547 p_tags tags = pop_tags(L); 554 p_tags tags = pop_tags(L);
548 if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object"); 555 if (lua_tag(L, 1) != tags->table) lua_error(L, "invalid socket object");
549 lua_gettable(L, 1); 556 lua_gettable(L, 1);
550 lua_insert(L, 1); 557 lua_insert(L, 1);
551 lua_call(L, lua_gettop(L)-1, LUA_MULTRET); 558 lua_call(L, lua_gettop(L)-1, LUA_MULTRET);
552 return lua_gettop(L); 559 return lua_gettop(L);
553} 560}
554#endif 561#endif
555 562
@@ -571,8 +578,8 @@ int global_select(lua_State *L)
571 fd_set readfds, *prfds = NULL, writefds, *pwfds = NULL; 578 fd_set readfds, *prfds = NULL, writefds, *pwfds = NULL;
572 struct timeval tm, *ptm = NULL; 579 struct timeval tm, *ptm = NULL;
573 int ret; 580 int ret;
574 unsigned max = 0; 581 unsigned max = 0;
575 SOCKET s; 582 SOCKET s;
576 int byfds, canread, canwrite; 583 int byfds, canread, canwrite;
577 /* reset the file descriptor sets */ 584 /* reset the file descriptor sets */
578 FD_ZERO(&readfds); FD_ZERO(&writefds); 585 FD_ZERO(&readfds); FD_ZERO(&writefds);
@@ -588,25 +595,25 @@ int global_select(lua_State *L)
588 while (lua_next(L, 1)) { 595 while (lua_next(L, 1)) {
589 if (lua_tag(L, -1) == tags->table) { /* skip strange fields */ 596 if (lua_tag(L, -1) == tags->table) { /* skip strange fields */
590 p_sock sock = get_sock(L, -1, tags, NULL); 597 p_sock sock = get_sock(L, -1, tags, NULL);
591 if (sock->sock != INVALID_SOCKET) { /* skip closed sockets */ 598 if (sock->sock != INVALID_SOCKET) { /* skip closed sockets */
592 lua_pushnumber(L, sock->sock); 599 lua_pushnumber(L, sock->sock);
593 lua_pushvalue(L, -2); 600 lua_pushvalue(L, -2);
594 lua_settable(L, byfds); 601 lua_settable(L, byfds);
595 if (sock->sock > max) max = sock->sock; 602 if (sock->sock > max) max = sock->sock;
596 /* a socket can have unread data in our internal 603 /* a socket can have unread data in our internal
597 buffer. in that case, we only call select to find 604 buffer. in that case, we only call select to find
598 out which of the other sockets can be written to 605 out which of the other sockets can be written to
599 or read from immediately. */ 606 or read from immediately. */
600 if (!bf_isempty(sock)) { 607 if (!bf_isempty(sock)) {
601 ms = 0; 608 ms = 0;
602 lua_pushnumber(L, lua_getn(L, canread) + 1); 609 lua_pushnumber(L, lua_getn(L, canread) + 1);
603 lua_pushvalue(L, -2); 610 lua_pushvalue(L, -2);
604 lua_settable(L, canread); 611 lua_settable(L, canread);
605 } else { 612 } else {
606 FD_SET(sock->sock, &readfds); 613 FD_SET(sock->sock, &readfds);
607 prfds = &readfds; 614 prfds = &readfds;
608 } 615 }
609 } 616 }
610 } 617 }
611 /* get rid of lua_next value and expose index */ 618 /* get rid of lua_next value and expose index */
612 lua_pop(L, 1); 619 lua_pop(L, 1);
@@ -618,14 +625,14 @@ int global_select(lua_State *L)
618 while (lua_next(L, 2)) { 625 while (lua_next(L, 2)) {
619 if (lua_tag(L, -1) == tags->table) { /* skip strange fields */ 626 if (lua_tag(L, -1) == tags->table) { /* skip strange fields */
620 p_sock sock = get_sock(L, -1, tags, NULL); 627 p_sock sock = get_sock(L, -1, tags, NULL);
621 if (sock->sock != INVALID_SOCKET) { /* skip closed sockets */ 628 if (sock->sock != INVALID_SOCKET) { /* skip closed sockets */
622 lua_pushnumber(L, sock->sock); 629 lua_pushnumber(L, sock->sock);
623 lua_pushvalue(L, -2); 630 lua_pushvalue(L, -2);
624 lua_settable(L, byfds); 631 lua_settable(L, byfds);
625 if (sock->sock > max) max = sock->sock; 632 if (sock->sock > max) max = sock->sock;
626 FD_SET(sock->sock, &writefds); 633 FD_SET(sock->sock, &writefds);
627 pwfds = &writefds; 634 pwfds = &writefds;
628 } 635 }
629 } 636 }
630 /* get rid of lua_next value and expose index */ 637 /* get rid of lua_next value and expose index */
631 lua_pop(L, 1); 638 lua_pop(L, 1);
@@ -1050,6 +1057,61 @@ void set_reuseaddr(p_sock sock)
1050} 1057}
1051 1058
1052/*-------------------------------------------------------------------------*\ 1059/*-------------------------------------------------------------------------*\
1060* Set socket options from a table on top of Lua stack.
1061* Supports SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST, and SO_LINGER options.
1062* Input
1063* L: Lua state to use
1064* sock: socket to set option
1065* Returns
1066* 1 if successful, 0 otherwise
1067\*-------------------------------------------------------------------------*/
1068static int set_option(lua_State *L, p_sock sock)
1069{
1070 static const char *const optionnames[] = {
1071 "SO_KEEPALIVE", "SO_DONTROUTE", "SO_BROADCAST", "SO_LINGER", NULL
1072 };
1073 const char *option = lua_tostring(L, -2);
1074 int err;
1075 switch (luaL_findstring(option, optionnames)) {
1076 case 0: {
1077 int bool = (int) lua_tonumber(L, -1);
1078 err = setsockopt(sock->sock, SOL_SOCKET, SO_KEEPALIVE, &bool,
1079 sizeof(bool));
1080 return err >= 0;
1081 }
1082 case 1: {
1083 int bool = (int) lua_tonumber(L, -1);
1084 err = setsockopt(sock->sock, SOL_SOCKET, SO_DONTROUTE, &bool,
1085 sizeof(bool));
1086 return err >= 0;
1087 }
1088 case 2: {
1089 int bool = (int) lua_tonumber(L, -1);
1090 err = setsockopt(sock->sock, SOL_SOCKET, SO_BROADCAST, &bool,
1091 sizeof(bool));
1092 return err >= 0;
1093 }
1094 case 3: {
1095 struct linger linger;
1096 if (!lua_istable(L, -1)) return 0;
1097 lua_pushstring(L, "l_onoff");
1098 lua_gettable(L, -2);
1099 linger.l_onoff = lua_tonumber(L, -1);
1100 lua_pop(L, 1);
1101 lua_pushstring(L, "l_linger");
1102 lua_gettable(L, -2);
1103 linger.l_linger = lua_tonumber(L, -1);
1104 lua_pop(L, 1);
1105 err = setsockopt(sock->sock, SOL_SOCKET, SO_LINGER, &linger,
1106 sizeof(linger));
1107 return err >= 0;
1108 }
1109 default: return 0;
1110 }
1111}
1112
1113
1114/*-------------------------------------------------------------------------*\
1053* Tries to create a TCP socket and bind it to (address, port) 1115* Tries to create a TCP socket and bind it to (address, port)
1054* Input 1116* Input
1055* address: host name or ip address 1117* address: host name or ip address
@@ -1462,20 +1524,20 @@ static int receive_dosline(lua_State *L, p_sock sock)
1462 } 1524 }
1463 buffer = bf_receive(sock, &got); 1525 buffer = bf_receive(sock, &got);
1464 if (got <= 0) { 1526 if (got <= 0) {
1465 luaL_pushresult(&b); 1527 luaL_pushresult(&b);
1466 return NET_CLOSED; 1528 return NET_CLOSED;
1467 } 1529 }
1468 pos = 0; 1530 pos = 0;
1469 while (pos < got && buffer[pos] != '\n') { 1531 while (pos < got && buffer[pos] != '\n') {
1470 /* we ignore all \r's */ 1532 /* we ignore all \r's */
1471 if (buffer[pos] != '\r') luaL_putchar(&b, buffer[pos]); 1533 if (buffer[pos] != '\r') luaL_putchar(&b, buffer[pos]);
1472 pos++; 1534 pos++;
1473 } 1535 }
1474 if (pos < got) { 1536 if (pos < got) {
1475 luaL_pushresult(&b); 1537 luaL_pushresult(&b);
1476 bf_skip(sock, pos+1); /* skip '\n' too */ 1538 bf_skip(sock, pos+1); /* skip '\n' too */
1477 return NET_DONE; 1539 return NET_DONE;
1478 } else bf_skip(sock, pos); 1540 } else bf_skip(sock, pos);
1479 } 1541 }
1480} 1542}
1481 1543
@@ -1501,17 +1563,17 @@ static int receive_unixline(lua_State *L, p_sock sock)
1501 } 1563 }
1502 buffer = bf_receive(sock, &got); 1564 buffer = bf_receive(sock, &got);
1503 if (got <= 0) { 1565 if (got <= 0) {
1504 luaL_pushresult(&b); 1566 luaL_pushresult(&b);
1505 return NET_CLOSED; 1567 return NET_CLOSED;
1506 } 1568 }
1507 pos = 0; 1569 pos = 0;
1508 while (pos < got && buffer[pos] != '\n') pos++; 1570 while (pos < got && buffer[pos] != '\n') pos++;
1509 luaL_addlstring(&b, buffer, pos); 1571 luaL_addlstring(&b, buffer, pos);
1510 if (pos < got) { 1572 if (pos < got) {
1511 luaL_pushresult(&b); 1573 luaL_pushresult(&b);
1512 bf_skip(sock, pos+1); /* skip '\n' too */ 1574 bf_skip(sock, pos+1); /* skip '\n' too */
1513 return NET_DONE; 1575 return NET_DONE;
1514 } else bf_skip(sock, pos); 1576 } else bf_skip(sock, pos);
1515 } 1577 }
1516} 1578}
1517 1579
@@ -1545,7 +1607,7 @@ static int receive_word(lua_State *L, p_sock sock)
1545 bf_skip(sock, pos); 1607 bf_skip(sock, pos);
1546 if (pos < got) { 1608 if (pos < got) {
1547 buffer += pos; 1609 buffer += pos;
1548 got -= pos; 1610 got -= pos;
1549 pos = 0; 1611 pos = 0;
1550 break; 1612 break;
1551 } 1613 }
@@ -1620,20 +1682,20 @@ void lua_socketlibopen(lua_State *L)
1620 lua_pushcfunction(L, global_time); lua_setglobal(L, "time"); 1682 lua_pushcfunction(L, global_time); lua_setglobal(L, "time");
1621#endif 1683#endif
1622#ifndef LUASOCKET_NOGLOBALS 1684#ifndef LUASOCKET_NOGLOBALS
1623 { 1685 {
1624 char *global[] = { 1686 char *global[] = {
1625 "accept", "close", "getpeername", 1687 "accept", "close", "getpeername",
1626 "getsockname", "receive", "send", 1688 "getsockname", "receive", "send",
1627 "receivefrom", "sendto" 1689 "receivefrom", "sendto"
1628 }; 1690 };
1629 unsigned int i; 1691 unsigned int i;
1630 for (i = 0; i < sizeof(global)/sizeof(char *); i++) { 1692 for (i = 0; i < sizeof(global)/sizeof(char *); i++) {
1631 lua_pushstring(L, global[i]); 1693 lua_pushstring(L, global[i]);
1632 lua_pushuserdata(L, tags); 1694 lua_pushuserdata(L, tags);
1633 lua_pushcclosure(L, global_calltable, 2); 1695 lua_pushcclosure(L, global_callfromtable, 2);
1634 lua_setglobal(L, global[i]); 1696 lua_setglobal(L, global[i]);
1635 } 1697 }
1636 } 1698 }
1637#endif 1699#endif
1638} 1700}
1639 1701