aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2003-06-09 18:23:40 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2003-06-09 18:23:40 +0000
commit58bdb658aaa1c30a8f3bed46eef880d308fae582 (patch)
tree5bf880c715daff79c1a2062f2f3ae8336858c83f
parentb2724ad2d1cc3768a04270ed3f8014ec65ad133b (diff)
downloadluasocket-58bdb658aaa1c30a8f3bed46eef880d308fae582.tar.gz
luasocket-58bdb658aaa1c30a8f3bed46eef880d308fae582.tar.bz2
luasocket-58bdb658aaa1c30a8f3bed46eef880d308fae582.zip
Select re-implemented in a nicer way.
Few changes in internal class and group registration. Lua modules are compiled and built into library. Dynamic library tested in Linux and Mac OS X.
-rw-r--r--etc/check-links.lua2
-rw-r--r--etc/dict.lua2
-rw-r--r--etc/get.lua2
-rw-r--r--makefile.dist79
-rw-r--r--samples/daytimeclnt.lua6
-rw-r--r--samples/echoclnt.lua6
-rw-r--r--samples/echosrvr.lua6
-rw-r--r--samples/listener.lua4
-rw-r--r--samples/talker.lua6
-rw-r--r--samples/tinyirc.lua90
-rw-r--r--src/auxiliar.c75
-rw-r--r--src/auxiliar.h2
-rw-r--r--src/buffer.c4
-rw-r--r--src/buffer.h2
-rw-r--r--src/inet.c5
-rw-r--r--src/inet.h2
-rw-r--r--src/io.h12
-rw-r--r--src/luasocket.c31
-rw-r--r--src/select.c191
-rw-r--r--src/select.h7
-rw-r--r--src/socket.h23
-rw-r--r--src/tcp.c97
-rw-r--r--src/tcp.h6
-rw-r--r--src/timeout.c5
-rw-r--r--src/udp.c98
-rw-r--r--src/udp.h4
-rw-r--r--src/usocket.c119
-rw-r--r--src/usocket.h5
28 files changed, 495 insertions, 396 deletions
diff --git a/etc/check-links.lua b/etc/check-links.lua
index 705c0ce..4c96fdc 100644
--- a/etc/check-links.lua
+++ b/etc/check-links.lua
@@ -1,6 +1,8 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- Little program that checks links in HTML files 2-- Little program that checks links in HTML files
3-- LuaSocket 1.5 sample files. 3-- LuaSocket 1.5 sample files.
4-- Author: Diego Nehab
5-- RCS ID: $Id$
4----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
5socket.http.TIMEOUT = 10 7socket.http.TIMEOUT = 10
6 8
diff --git a/etc/dict.lua b/etc/dict.lua
index 6790cab..89bdb4f 100644
--- a/etc/dict.lua
+++ b/etc/dict.lua
@@ -1,6 +1,8 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- Little program to download DICT word definitions 2-- Little program to download DICT word definitions
3-- LuaSocket 1.5 sample files 3-- LuaSocket 1.5 sample files
4-- Author: Diego Nehab
5-- RCS ID: $Id$
4----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
5function get_status(sock, valid) 7function get_status(sock, valid)
6 local line, err = sock:receive() 8 local line, err = sock:receive()
diff --git a/etc/get.lua b/etc/get.lua
index af46c16..e972d16 100644
--- a/etc/get.lua
+++ b/etc/get.lua
@@ -1,6 +1,8 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- Little program to download files from URLs 2-- Little program to download files from URLs
3-- LuaSocket 1.5 sample files 3-- LuaSocket 1.5 sample files
4-- Author: Diego Nehab
5-- RCS ID: $Id$
4----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
5-- formats a number of seconds into human readable form 7-- formats a number of seconds into human readable form
6function nicetime(s) 8function nicetime(s)
diff --git a/makefile.dist b/makefile.dist
index 90ef7c2..e493305 100644
--- a/makefile.dist
+++ b/makefile.dist
@@ -2,22 +2,81 @@
2# Distribution makefile 2# Distribution makefile
3#-------------------------------------------------------------------------- 3#--------------------------------------------------------------------------
4 4
5DIST = luasocket-1.5-work 5DIST = luasocket-1.5-alpha
6 6
7LUA = concat.lua code.lua url.lua http.lua smtp.lua ftp.lua lsselect.lua \ 7LUA = \
8 cl-compat.lua 8 concat.lua \
9 code.lua \
10 url.lua \
11 http.lua \
12 smtp.lua \
13 ftp.lua \
14 select.lua \
15 luasocket.lua
9 16
10TESTS = testclnt.lua testsrvr.lua testcmd.lua codetest.lua \ 17TESTS = \
11 urltest.lua concattest.lua 18 testclnt.lua \
19 testsrvr.lua \
20 testcmd.lua \
21 codetest.lua \
22 urltest.lua \
23 concattest.lua \
24 ftptest.lua \
25 httptest.lua \
26 smtptest.lua \
27 mbox.lua \
28 udptest.lua
12 29
13EXAMPLES = check-links.lua daytimeclnt.lua dict.lua echoclnt.lua \ 30EXAMPLES = \
14 echosrvr.lua get.lua listener.lua talker.lua tinyirc.lua tftpclnt.lua 31 check-links.lua \
32 daytimeclnt.lua \
33 echoclnt.lua \
34 echosrvr.lua \
35 get.lua \
36 listener.lua \
37 talker.lua \
38 tinyirc.lua
39
40ETC = \
41 cl-compat.lua \
42 tftp.lua \
43 dict.lua
44
45MAIN = \
46 auxiliar.c \
47 auxiliar.h \
48 buffer.c \
49 buffer.h \
50 error.c \
51 error.h \
52 inet.c \
53 inet.h \
54 io.c \
55 io.h \
56 lua.c \
57 luasocket.c \
58 luasocket.h \
59 makefile \
60 select.c \
61 select.h \
62 socket.h \
63 tcp.c \
64 tcp.h \
65 timeout.c \
66 timeout.h \
67 udp.c \
68 udp.h \
69 usocket.c \
70 usocket.h \
71 wsocket.c \
72 wsocket.h \
15 73
16dist: 74dist:
17 mkdir -p $(DIST)/examples 75 mkdir -p $(DIST)/examples
18 mkdir -p $(DIST)/tests 76 mkdir -p $(DIST)/tests
19 cp -vf *.c $(DIST) 77 mkdir -p $(DIST)/etc
20 cp -vf *.h $(DIST) 78 mkdir -p $(DIST)/lua
79 cp -vf $(MAIN) $(DIST)
21 cp -vf $(LUA) $(DIST) 80 cp -vf $(LUA) $(DIST)
22 cp -vf makefile $(DIST) 81 cp -vf makefile $(DIST)
23 cp -vf README $(DIST) 82 cp -vf README $(DIST)
@@ -25,6 +84,8 @@ dist:
25 cp -vf README.examples $(DIST)/examples/README 84 cp -vf README.examples $(DIST)/examples/README
26 cp -vf $(TESTS) $(DIST)/tests 85 cp -vf $(TESTS) $(DIST)/tests
27 cp -vf README.tests $(DIST)/tests/README 86 cp -vf README.tests $(DIST)/tests/README
87 cp -vf $(ETC) $(DIST)/etc
88 cp -vf README.etc $(DIST)/etc/README
28 tar -zcvf $(DIST).tar.gz $(DIST) 89 tar -zcvf $(DIST).tar.gz $(DIST)
29 zip -r $(DIST).zip $(DIST) 90 zip -r $(DIST).zip $(DIST)
30 91
diff --git a/samples/daytimeclnt.lua b/samples/daytimeclnt.lua
index 4debc81..85ddca1 100644
--- a/samples/daytimeclnt.lua
+++ b/samples/daytimeclnt.lua
@@ -1,3 +1,9 @@
1-----------------------------------------------------------------------------
2-- UDP sample: daytime protocol client
3-- LuaSocket 1.5 sample files.
4-- Author: Diego Nehab
5-- RCS ID: $Id$
6-----------------------------------------------------------------------------
1host = host or "127.0.0.1" 7host = host or "127.0.0.1"
2port = port or 13 8port = port or 13
3if arg then 9if arg then
diff --git a/samples/echoclnt.lua b/samples/echoclnt.lua
index cd8b450..bca0b4d 100644
--- a/samples/echoclnt.lua
+++ b/samples/echoclnt.lua
@@ -1,3 +1,9 @@
1-----------------------------------------------------------------------------
2-- UDP sample: echo protocol client
3-- LuaSocket 1.5 sample files
4-- Author: Diego Nehab
5-- RCS ID: $Id$
6-----------------------------------------------------------------------------
1host = host or "localhost" 7host = host or "localhost"
2port = port or 7 8port = port or 7
3if arg then 9if arg then
diff --git a/samples/echosrvr.lua b/samples/echosrvr.lua
index 6117557..18bd84e 100644
--- a/samples/echosrvr.lua
+++ b/samples/echosrvr.lua
@@ -1,3 +1,9 @@
1-----------------------------------------------------------------------------
2-- UDP sample: echo protocol server
3-- LuaSocket 1.5 sample files
4-- Author: Diego Nehab
5-- RCS ID: $Id$
6-----------------------------------------------------------------------------
1host = host or "127.0.0.1" 7host = host or "127.0.0.1"
2port = port or 7 8port = port or 7
3if arg then 9if arg then
diff --git a/samples/listener.lua b/samples/listener.lua
index c035ab2..4846419 100644
--- a/samples/listener.lua
+++ b/samples/listener.lua
@@ -1,6 +1,8 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- Little program to dump lines received at a given port 2-- TCP sample: Little program to dump lines received at a given port
3-- LuaSocket 1.5 sample files 3-- LuaSocket 1.5 sample files
4-- Author: Diego Nehab
5-- RCS ID: $Id$
4----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
5host = host or "*" 7host = host or "*"
6port = port or 8080 8port = port or 8080
diff --git a/samples/talker.lua b/samples/talker.lua
index 688824f..c7a239a 100644
--- a/samples/talker.lua
+++ b/samples/talker.lua
@@ -1,3 +1,9 @@
1-----------------------------------------------------------------------------
2-- TCP sample: Little program to send text lines to a given host/port
3-- LuaSocket 1.5 sample files
4-- Author: Diego Nehab
5-- RCS ID: $Id$
6-----------------------------------------------------------------------------
1host = host or "localhost" 7host = host or "localhost"
2port = port or 8080 8port = port or 8080
3if arg then 9if arg then
diff --git a/samples/tinyirc.lua b/samples/tinyirc.lua
index d3e56e7..0b20303 100644
--- a/samples/tinyirc.lua
+++ b/samples/tinyirc.lua
@@ -1,16 +1,9 @@
1function set_add(set, sock) 1-----------------------------------------------------------------------------
2 table.insert(set, sock) 2-- Select sample: simple text line server
3end 3-- LuaSocket 1.5 sample files.
4 4-- Author: Diego Nehab
5function set_remove(set, sock) 5-- RCS ID: $Id$
6 for i = 1, table.getn(set) do 6-----------------------------------------------------------------------------
7 if set[i] == sock then
8 table.remove(set, i)
9 break
10 end
11 end
12end
13
14host = host or "*" 7host = host or "*"
15port1 = port1 or 8080 8port1 = port1 or 8080
16port2 = port2 or 8081 9port2 = port2 or 8081
@@ -21,49 +14,62 @@ if arg then
21end 14end
22 15
23server1, error = socket.bind(host, port1) 16server1, error = socket.bind(host, port1)
24if not server1 then print(error) exit() end 17assert(server1, error)
25server1:timeout(1) 18server1:timeout(1)
26server2, error = socket.bind(host, port2) 19server2, error = socket.bind(host, port2)
27if not server2 then print(error) exit() end 20assert(server2, error)
28server2:timeout(1) 21server2:timeout(1)
29 22
30sock_set = {server1, server2} 23function newset()
24 local reverse = {}
25 local set = {}
26 setmetatable(set, { __index = {
27 insert = function(set, value)
28 table.insert(set, value)
29 reverse[value] = table.getn(set)
30 end,
31 remove = function(set, value)
32 table.remove(set, reverse[value])
33 reverse[value] = nil
34 end,
35 id = function(set, value)
36 return reverse[value]
37 end
38 }})
39 return set
40end
41
42sockets = newset()
31 43
32sock_id = {} 44sockets:insert(server1)
33sock_id[server1] = 1 45sockets:insert(server2)
34sock_id[server2] = 2
35next_id = 3
36 46
37while 1 do 47while 1 do
38 local readable, _, error = socket.select(sock_set, nil) 48 local readable, _, error = socket.select(sockets, nil)
39 for _, sock in readable do 49 for _, input in readable do
40 -- is it a server socket 50 -- is it a server socket?
41 if sock_id[sock] < 3 then 51 local id = sockets:id(input)
42 local incomming = sock:accept() 52 if input == server1 or input == server2 then
43 if incomming then 53 local new = input:accept()
44 incomming:timeout(1) 54 if new then
45 sock_id[incomming] = next_id 55 new:timeout(1)
46 set_add(sock_set, incomming) 56 sockets:insert(new)
47 io.write("Added client id ", next_id, ". ", 57 io.write("Server ", id, " got client ", sockets:id(new), "\n")
48 table.getn(sock_set)-2, " total.\n")
49 next_id = next_id + 1
50 end 58 end
51 -- it is a client socket 59 -- it is a client socket
52 else 60 else
53 local line, error = sock:receive() 61 local line, error = input:receive()
54 local id = sock_id[sock]
55 if error then 62 if error then
56 sock:close() 63 input:close()
57 set_remove(sock_set, sock) 64 io.write("Removing client ", id, "\n")
58 io.write("Removed client number ", id, ". ", 65 sockets:remove(input)
59 getn(sock_set)-2, " total.\n")
60 else 66 else
61 io.write("Broadcasting line '", id, "> ", line, "'.\n") 67 io.write("Broadcasting line '", id, "> ", line, "'.\n")
62 __, writable, error = socket.select(nil, sock_set, 1) 68 __, writable, error = socket.select(nil, sockets, 1)
63 if not error then 69 if not error then
64 for ___, outgoing in writable do 70 for ___, output in writable do
65 io.write("Sending to client ", sock_id[outgoing], "\n") 71 io.write("Sending to client ", sockets:id(output), "\n")
66 outgoing:send(id, "> ", line, "\r\n") 72 output:send(id, "> ", line, "\r\n")
67 end 73 end
68 else io.write("No one ready to listen!!!\n") end 74 else io.write("No one ready to listen!!!\n") end
69 end 75 end
diff --git a/src/auxiliar.c b/src/auxiliar.c
index 5e5ba1a..96138f1 100644
--- a/src/auxiliar.c
+++ b/src/auxiliar.c
@@ -3,12 +3,7 @@
3* 3*
4* RCS ID: $Id$ 4* RCS ID: $Id$
5\*=========================================================================*/ 5\*=========================================================================*/
6#include "aux.h" 6#include "auxiliar.h"
7
8/*=========================================================================*\
9* Internal function prototypes
10\*=========================================================================*/
11static void *aux_getgroupudata(lua_State *L, const char *group, int objidx);
12 7
13/*=========================================================================*\ 8/*=========================================================================*\
14* Exported functions 9* Exported functions
@@ -20,18 +15,19 @@ static void *aux_getgroupudata(lua_State *L, const char *group, int objidx);
20\*-------------------------------------------------------------------------*/ 15\*-------------------------------------------------------------------------*/
21void aux_newclass(lua_State *L, const char *name, luaL_reg *func) 16void aux_newclass(lua_State *L, const char *name, luaL_reg *func)
22{ 17{
23 luaL_newmetatable(L, name); 18 lua_pushstring(L, name);
19 lua_newtable(L);
24 lua_pushstring(L, "__index"); 20 lua_pushstring(L, "__index");
25 lua_newtable(L); 21 lua_newtable(L);
26 luaL_openlib(L, NULL, func, 0); 22 luaL_openlib(L, NULL, func, 0);
27 lua_pushstring(L, "class"); 23 lua_pushstring(L, "class");
28 lua_pushstring(L, name); 24 lua_pushstring(L, name);
29 lua_settable(L, -3); 25 lua_rawset(L, -3);
30 lua_settable(L, -3);
31 lua_pushstring(L, "group"); 26 lua_pushstring(L, "group");
32 lua_newtable(L); 27 lua_newtable(L);
33 lua_settable(L, -3); 28 lua_rawset(L, -3);
34 lua_pop(L, 1); 29 lua_rawset(L, -3);
30 lua_rawset(L, LUA_REGISTRYINDEX);
35} 31}
36 32
37/*-------------------------------------------------------------------------*\ 33/*-------------------------------------------------------------------------*\
@@ -39,13 +35,16 @@ void aux_newclass(lua_State *L, const char *name, luaL_reg *func)
39\*-------------------------------------------------------------------------*/ 35\*-------------------------------------------------------------------------*/
40void aux_add2group(lua_State *L, const char *name, const char *group) 36void aux_add2group(lua_State *L, const char *name, const char *group)
41{ 37{
42 luaL_getmetatable(L, name); 38 lua_pushstring(L, name);
39 lua_rawget(L, LUA_REGISTRYINDEX);
40 lua_pushstring(L, "__index");
41 lua_rawget(L, -2);
43 lua_pushstring(L, "group"); 42 lua_pushstring(L, "group");
44 lua_gettable(L, -2); 43 lua_rawget(L, -2);
45 lua_pushstring(L, group); 44 lua_pushstring(L, group);
46 lua_pushnumber(L, 1); 45 lua_pushnumber(L, 1);
47 lua_settable(L, -3); 46 lua_rawset(L, -3);
48 lua_pop(L, 2); 47 lua_pop(L, 3);
49} 48}
50 49
51/*-------------------------------------------------------------------------*\ 50/*-------------------------------------------------------------------------*\
@@ -53,7 +52,7 @@ void aux_add2group(lua_State *L, const char *name, const char *group)
53\*-------------------------------------------------------------------------*/ 52\*-------------------------------------------------------------------------*/
54void *aux_checkclass(lua_State *L, const char *name, int objidx) 53void *aux_checkclass(lua_State *L, const char *name, int objidx)
55{ 54{
56 void *data = luaL_checkudata(L, objidx, name); 55 void *data = aux_getclassudata(L, name, objidx);
57 if (!data) { 56 if (!data) {
58 char msg[45]; 57 char msg[45];
59 sprintf(msg, "%.35s expected", name); 58 sprintf(msg, "%.35s expected", name);
@@ -81,7 +80,8 @@ void *aux_checkgroup(lua_State *L, const char *group, int objidx)
81\*-------------------------------------------------------------------------*/ 80\*-------------------------------------------------------------------------*/
82void aux_setclass(lua_State *L, const char *name, int objidx) 81void aux_setclass(lua_State *L, const char *name, int objidx)
83{ 82{
84 luaL_getmetatable(L, name); 83 lua_pushstring(L, name);
84 lua_rawget(L, LUA_REGISTRYINDEX);
85 if (objidx < 0) objidx--; 85 if (objidx < 0) objidx--;
86 lua_setmetatable(L, objidx); 86 lua_setmetatable(L, objidx);
87} 87}
@@ -92,17 +92,47 @@ void aux_setclass(lua_State *L, const char *name, int objidx)
92/*-------------------------------------------------------------------------*\ 92/*-------------------------------------------------------------------------*\
93* Get a userdata if object belongs to a given group. 93* Get a userdata if object belongs to a given group.
94\*-------------------------------------------------------------------------*/ 94\*-------------------------------------------------------------------------*/
95static void *aux_getgroupudata(lua_State *L, const char *group, int objidx) 95void *aux_getgroupudata(lua_State *L, const char *group, int objidx)
96{ 96{
97 if (!lua_getmetatable(L, objidx)) return NULL; 97 if (!lua_getmetatable(L, objidx))
98 return NULL;
99 lua_pushstring(L, "__index");
100 lua_rawget(L, -2);
101 if (!lua_istable(L, -1)) {
102 lua_pop(L, 2);
103 return NULL;
104 }
98 lua_pushstring(L, "group"); 105 lua_pushstring(L, "group");
99 lua_gettable(L, -2); 106 lua_rawget(L, -2);
107 if (!lua_istable(L, -1)) {
108 lua_pop(L, 3);
109 return NULL;
110 }
111 lua_pushstring(L, group);
112 lua_rawget(L, -2);
100 if (lua_isnil(L, -1)) { 113 if (lua_isnil(L, -1)) {
114 lua_pop(L, 4);
115 return NULL;
116 }
117 lua_pop(L, 4);
118 return lua_touserdata(L, objidx);
119}
120
121/*-------------------------------------------------------------------------*\
122* Get a userdata if object belongs to a given class.
123\*-------------------------------------------------------------------------*/
124void *aux_getclassudata(lua_State *L, const char *group, int objidx)
125{
126 if (!lua_getmetatable(L, objidx))
127 return NULL;
128 lua_pushstring(L, "__index");
129 lua_rawget(L, -2);
130 if (!lua_istable(L, -1)) {
101 lua_pop(L, 2); 131 lua_pop(L, 2);
102 return NULL; 132 return NULL;
103 } 133 }
104 lua_pushstring(L, group); 134 lua_pushstring(L, "class");
105 lua_gettable(L, -2); 135 lua_rawget(L, -2);
106 if (lua_isnil(L, -1)) { 136 if (lua_isnil(L, -1)) {
107 lua_pop(L, 3); 137 lua_pop(L, 3);
108 return NULL; 138 return NULL;
@@ -110,4 +140,3 @@ static void *aux_getgroupudata(lua_State *L, const char *group, int objidx)
110 lua_pop(L, 3); 140 lua_pop(L, 3);
111 return lua_touserdata(L, objidx); 141 return lua_touserdata(L, objidx);
112} 142}
113
diff --git a/src/auxiliar.h b/src/auxiliar.h
index 2681a84..66be31d 100644
--- a/src/auxiliar.h
+++ b/src/auxiliar.h
@@ -13,6 +13,8 @@ void aux_newclass(lua_State *L, const char *name, luaL_reg *func);
13void aux_add2group(lua_State *L, const char *name, const char *group); 13void aux_add2group(lua_State *L, const char *name, const char *group);
14void *aux_checkclass(lua_State *L, const char *name, int objidx); 14void *aux_checkclass(lua_State *L, const char *name, int objidx);
15void *aux_checkgroup(lua_State *L, const char *group, int objidx); 15void *aux_checkgroup(lua_State *L, const char *group, int objidx);
16void *aux_getclassudata(lua_State *L, const char *group, int objidx);
17void *aux_getgroupudata(lua_State *L, const char *group, int objidx);
16void aux_setclass(lua_State *L, const char *name, int objidx); 18void aux_setclass(lua_State *L, const char *name, int objidx);
17 19
18/* min and max macros */ 20/* min and max macros */
diff --git a/src/buffer.c b/src/buffer.c
index c5ef66c..ab059bb 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -7,8 +7,8 @@
7#include <lauxlib.h> 7#include <lauxlib.h>
8 8
9#include "error.h" 9#include "error.h"
10#include "aux.h" 10#include "auxiliar.h"
11#include "buf.h" 11#include "buffer.h"
12 12
13/*=========================================================================*\ 13/*=========================================================================*\
14* Internal function prototypes 14* Internal function prototypes
diff --git a/src/buffer.h b/src/buffer.h
index 3ffc145..1502ef0 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -8,7 +8,7 @@
8 8
9#include <lua.h> 9#include <lua.h>
10#include "io.h" 10#include "io.h"
11#include "tm.h" 11#include "timeout.h"
12 12
13/* buffer size in bytes */ 13/* buffer size in bytes */
14#define BUF_SIZE 8192 14#define BUF_SIZE 8192
diff --git a/src/inet.c b/src/inet.c
index f20762f..60106f2 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -38,6 +38,7 @@ static luaL_reg func[] = {
38void inet_open(lua_State *L) 38void inet_open(lua_State *L)
39{ 39{
40 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); 40 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
41 lua_pop(L, 1);
41} 42}
42 43
43/*=========================================================================*\ 44/*=========================================================================*\
@@ -114,7 +115,7 @@ static int inet_global_tohostname(lua_State *L)
114int inet_meth_getpeername(lua_State *L, p_sock ps) 115int inet_meth_getpeername(lua_State *L, p_sock ps)
115{ 116{
116 struct sockaddr_in peer; 117 struct sockaddr_in peer;
117 size_t peer_len = sizeof(peer); 118 socklen_t peer_len = sizeof(peer);
118 if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { 119 if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) {
119 lua_pushnil(L); 120 lua_pushnil(L);
120 return 1; 121 return 1;
@@ -135,7 +136,7 @@ int inet_meth_getpeername(lua_State *L, p_sock ps)
135int inet_meth_getsockname(lua_State *L, p_sock ps) 136int inet_meth_getsockname(lua_State *L, p_sock ps)
136{ 137{
137 struct sockaddr_in local; 138 struct sockaddr_in local;
138 size_t local_len = sizeof(local); 139 socklen_t local_len = sizeof(local);
139 if (getsockname(*ps, (SA *) &local, &local_len) < 0) { 140 if (getsockname(*ps, (SA *) &local, &local_len) < 0) {
140 lua_pushnil(L); 141 lua_pushnil(L);
141 return 1; 142 return 1;
diff --git a/src/inet.h b/src/inet.h
index bcefc5b..b8d8f19 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -7,7 +7,7 @@
7#define INET_H 7#define INET_H
8 8
9#include <lua.h> 9#include <lua.h>
10#include "sock.h" 10#include "socket.h"
11 11
12/*-------------------------------------------------------------------------*\ 12/*-------------------------------------------------------------------------*\
13* Exported functions 13* Exported functions
diff --git a/src/io.h b/src/io.h
index b5b7f1d..30d445b 100644
--- a/src/io.h
+++ b/src/io.h
@@ -1,7 +1,17 @@
1#ifndef IO_H 1#ifndef IO_H
2#define IO_H 2#define IO_H
3 3
4#include "error.h" 4#include <stdio.h>
5
6/* IO error codes */
7enum {
8 IO_DONE, /* operation completed successfully */
9 IO_TIMEOUT, /* operation timed out */
10 IO_CLOSED, /* the connection has been closed */
11 IO_ERROR, /* something wrong... */
12 IO_REFUSED, /* transfer has been refused */
13 IO_LIMITED /* maximum number of bytes reached */
14};
5 15
6/* interface to send function */ 16/* interface to send function */
7typedef int (*p_send) ( 17typedef int (*p_send) (
diff --git a/src/luasocket.c b/src/luasocket.c
index 53f8c21..5541d7f 100644
--- a/src/luasocket.c
+++ b/src/luasocket.c
@@ -24,12 +24,13 @@
24\*=========================================================================*/ 24\*=========================================================================*/
25#include "luasocket.h" 25#include "luasocket.h"
26 26
27#include "tm.h" 27#include "timeout.h"
28#include "buf.h" 28#include "buffer.h"
29#include "sock.h" 29#include "socket.h"
30#include "inet.h" 30#include "inet.h"
31#include "tcp.h" 31#include "tcp.h"
32#include "udp.h" 32#include "udp.h"
33#include "select.h"
33 34
34/*=========================================================================*\ 35/*=========================================================================*\
35* Exported functions 36* Exported functions
@@ -39,6 +40,7 @@
39\*-------------------------------------------------------------------------*/ 40\*-------------------------------------------------------------------------*/
40LUASOCKET_API int luaopen_socketlib(lua_State *L) 41LUASOCKET_API int luaopen_socketlib(lua_State *L)
41{ 42{
43 if (!sock_open()) return 0;
42 /* create namespace table */ 44 /* create namespace table */
43 lua_pushstring(L, LUASOCKET_LIBNAME); 45 lua_pushstring(L, LUASOCKET_LIBNAME);
44 lua_newtable(L); 46 lua_newtable(L);
@@ -53,13 +55,28 @@ LUASOCKET_API int luaopen_socketlib(lua_State *L)
53 lua_pushstring(L, LUASOCKET_LIBNAME); 55 lua_pushstring(L, LUASOCKET_LIBNAME);
54 lua_settable(L, LUA_GLOBALSINDEX); 56 lua_settable(L, LUA_GLOBALSINDEX);
55 /* initialize all modules */ 57 /* initialize all modules */
56 sock_open(L);
57 tm_open(L); 58 tm_open(L);
58 buf_open(L); 59 buf_open(L);
59 inet_open(L); 60 inet_open(L);
60 tcp_open(L); 61 tcp_open(L);
61 udp_open(L); 62 udp_open(L);
62 /* load all Lua code */ 63 select_open(L);
63 lua_dofile(L, "luasocket.lua"); 64#ifdef LUASOCKET_COMPILED
64 return 0; 65#include "auxiliar.lch"
66#include "concat.lch"
67#include "code.lch"
68#include "url.lch"
69#include "smtp.lch"
70#include "ftp.lch"
71#include "http.lch"
72#else
73 lua_dofile(L, "auxiliar.lua");
74 lua_dofile(L, "concat.lua");
75 lua_dofile(L, "code.lua");
76 lua_dofile(L, "url.lua");
77 lua_dofile(L, "smtp.lua");
78 lua_dofile(L, "ftp.lua");
79 lua_dofile(L, "http.lua");
80#endif
81 return 1;
65} 82}
diff --git a/src/select.c b/src/select.c
index 9f56b47..3cabbd1 100644
--- a/src/select.c
+++ b/src/select.c
@@ -1,154 +1,129 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* Select implementation 2* Select implementation
3* Global Lua fuctions:
4* select: waits until socket ready
5* RCS ID: $Id$ 3* RCS ID: $Id$
6\*=========================================================================*/ 4\*=========================================================================*/
7#include <string.h> 5#include <string.h>
6
8#include <lua.h> 7#include <lua.h>
9#include <lauxlib.h> 8#include <lauxlib.h>
10 9
11#include "luasocket.h" 10#include "luasocket.h"
12#include "lspriv.h" 11#include "socket.h"
13#include "lsselect.h" 12#include "auxiliar.h"
14#include "lsfd.h" 13#include "select.h"
15 14
16/* auxiliar functions */ 15static int meth_set(lua_State *L);
17static int local_select(lua_State *L); 16static int meth_isset(lua_State *L);
18static int local_getfd(lua_State *L); 17static int c_select(lua_State *L);
19static int local_pending(lua_State *L); 18static int global_select(lua_State *L);
20static int local_FD_SET(lua_State *L); 19static void check_obj_tab(lua_State *L, int tabidx);
21static int local_FD_ISSET(lua_State *L);
22 20
23static int select_lua_select(lua_State *L); 21/* fd_set object methods */
22static luaL_reg set[] = {
23 {"set", meth_set},
24 {"isset", meth_isset},
25 {NULL, NULL}
26};
24 27
25/*-------------------------------------------------------------------------*\ 28/* functions in library namespace */
26* Marks type as selectable 29static luaL_reg func[] = {
27* Input 30 {"select", global_select},
28* name: type name 31 {NULL, NULL}
29\*-------------------------------------------------------------------------*/ 32};
30void select_addclass(lua_State *L, cchar *lsclass)
31{
32 lua_pushstring(L, "luasocket(select)");
33 lua_gettable(L, LUA_REGISTRYINDEX);
34 lua_pushstring(L, lsclass);
35 lua_pushnumber(L, 1);
36 lua_settable(L, -3);
37 lua_pop(L, 1);
38}
39 33
40void select_open(lua_State *L) 34void select_open(lua_State *L)
41{ 35{
42 /* push select auxiliar lua function and register 36 /* get select auxiliar lua function from lua code and register
43 * select_lua_select with it as an upvalue */ 37 * pass it as an upvalue to global_select */
44#ifdef LUASOCKET_DOFILE 38#ifdef LUASOCKET_COMPILED
45 lua_dofile(L, "lsselect.lua"); 39#include "select.lch"
46#else 40#else
47#include "lsselect.loh" 41 lua_dofile(L, "select.lua");
48#endif 42#endif
49 lua_getglobal(L, LUASOCKET_LIBNAME); 43 luaL_openlib(L, LUASOCKET_LIBNAME, func, 1);
50 lua_pushstring(L, "_select");
51 lua_gettable(L, -2);
52 lua_pushcclosure(L, select_lua_select, 1);
53 priv_newglobal(L, "select");
54 lua_pop(L, 1); 44 lua_pop(L, 1);
55 /* create luasocket(select) table */ 45 aux_newclass(L, "select{fd_set}", set);
56 lua_pushstring(L, "luasocket(select)");
57 lua_newtable(L);
58 lua_settable(L, LUA_REGISTRYINDEX);
59} 46}
60 47
61/*-------------------------------------------------------------------------*\ 48/*-------------------------------------------------------------------------*\
62* Waits for a set of sockets until a condition is met or timeout. 49* Waits for a set of sockets until a condition is met or timeout.
63* Lua Input: {input}, {output} [, timeout]
64* {input}: table of sockets to be tested for input
65* {output}: table of sockets to be tested for output
66* timeout: maximum amount of time to wait for condition, in seconds
67* Lua Returns: {input}, {output}, err
68* {input}: table with sockets ready for input
69* {output}: table with sockets ready for output
70* err: "timeout" or nil
71\*-------------------------------------------------------------------------*/ 50\*-------------------------------------------------------------------------*/
72static int select_lua_select(lua_State *L) 51static int global_select(lua_State *L)
73{ 52{
74 fd_set read, write; 53 fd_set *read_fd_set, *write_fd_set;
75 FD_ZERO(&read);
76 FD_ZERO(&write);
77 /* push select lua auxiliar function */
78 lua_pushvalue(L, lua_upvalueindex(1)); lua_insert(L, 1);
79 /* make sure we have enough arguments (nil is the default) */ 54 /* make sure we have enough arguments (nil is the default) */
80 lua_settop(L, 4); 55 lua_settop(L, 3);
81 /* pass FD_SET and manipulation functions */ 56 /* check object tables */
82 lua_boxpointer(L, &read); 57 check_obj_tab(L, 1);
83 lua_boxpointer(L, &write); 58 check_obj_tab(L, 2);
84 lua_pushcfunction(L, local_FD_SET); 59 /* check timeout */
85 lua_pushcfunction(L, local_FD_ISSET); 60 if (!lua_isnil(L, 3) && !lua_isnumber(L, 3))
86 /* pass getfd function with selectable table as upvalue */ 61 luaL_argerror(L, 3, "number or nil expected");
87 lua_pushstring(L, "luasocket(select)"); lua_gettable(L, LUA_REGISTRYINDEX); 62 /* select auxiliar lua function to be called comes first */
88 lua_pushcclosure(L, local_getfd, 1); 63 lua_pushvalue(L, lua_upvalueindex(1));
89 /* pass pending function */ 64 lua_insert(L, 1);
90 lua_pushstring(L, "luasocket(select)"); lua_gettable(L, LUA_REGISTRYINDEX); 65 /* pass fd_set objects */
91 lua_pushcclosure(L, local_pending, 1); 66 read_fd_set = lua_newuserdata(L, sizeof(fd_set));
67 FD_ZERO(read_fd_set);
68 aux_setclass(L, "select{fd_set}", -1);
69 write_fd_set = lua_newuserdata(L, sizeof(fd_set));
70 FD_ZERO(write_fd_set);
71 aux_setclass(L, "select{fd_set}", -1);
92 /* pass select auxiliar C function */ 72 /* pass select auxiliar C function */
93 lua_pushcfunction(L, local_select); 73 lua_pushcfunction(L, c_select);
94 /* call select auxiliar lua function */ 74 /* call select auxiliar lua function */
95 lua_call(L, 10, 3); 75 lua_call(L, 6, 3);
96 return 3; 76 return 3;
97} 77}
98 78
99static int local_getfd(lua_State *L) 79static int c_select(lua_State *L)
100{
101 priv_pushclass(L, 1);
102 lua_gettable(L, lua_upvalueindex(1));
103 if (!lua_isnil(L, -1)) {
104 p_fd sock = (p_fd) lua_touserdata(L, 1);
105 lua_pushnumber(L, sock->fd);
106 }
107 return 1;
108}
109
110static int local_pending(lua_State *L)
111{
112 priv_pushclass(L, 1);
113 lua_gettable(L, lua_upvalueindex(1));
114 if (!lua_isnil(L, -1)) {
115 p_fd sock = (p_fd) lua_touserdata(L, 1);
116 if (sock->fd_pending(L, sock)) lua_pushnumber(L, 1);
117 else lua_pushnil(L);
118 }
119 return 1;
120}
121
122static int local_select(lua_State *L)
123{ 80{
124 int max_fd = (int) lua_tonumber(L, 1); 81 int max_fd = (int) lua_tonumber(L, 1);
125 fd_set *read_set = (fd_set *) lua_touserdata(L, 2); 82 fd_set *read_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 2);
126 fd_set *write_set = (fd_set *) lua_touserdata(L, 3); 83 fd_set *write_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 3);
127 int deadline = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000); 84 int timeout = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000);
128 struct timeval tv; 85 struct timeval tv;
129 if (deadline >= 0) { 86 tv.tv_sec = timeout / 1000;
130 tv.tv_sec = deadline / 1000; 87 tv.tv_usec = (timeout % 1000) * 1000;
131 tv.tv_usec = (deadline % 1000) * 1000; 88 lua_pushnumber(L, select(max_fd, read_fd_set, write_fd_set, NULL,
132 lua_pushnumber(L, select(max_fd, read_set, write_set, NULL, &tv)); 89 timeout < 0 ? NULL : &tv));
133 } else {
134 lua_pushnumber(L, select(max_fd, read_set, write_set, NULL, NULL));
135 }
136 return 1; 90 return 1;
137} 91}
138 92
139static int local_FD_SET(lua_State *L) 93static int meth_set(lua_State *L)
140{ 94{
141 COMPAT_FD fd = (COMPAT_FD) lua_tonumber(L, 1); 95 fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1);
142 fd_set *set = (fd_set *) lua_topointer(L, 2); 96 t_sock fd = (t_sock) lua_tonumber(L, 2);
143 if (fd >= 0) FD_SET(fd, set); 97 if (fd >= 0) FD_SET(fd, set);
144 return 0; 98 return 0;
145} 99}
146 100
147static int local_FD_ISSET(lua_State *L) 101static int meth_isset(lua_State *L)
148{ 102{
149 COMPAT_FD fd = (COMPAT_FD) lua_tonumber(L, 1); 103 fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1);
150 fd_set *set = (fd_set *) lua_topointer(L, 2); 104 t_sock fd = (t_sock) lua_tonumber(L, 2);
151 if (fd >= 0 && FD_ISSET(fd, set)) lua_pushnumber(L, 1); 105 if (fd >= 0 && FD_ISSET(fd, set)) lua_pushnumber(L, 1);
152 else lua_pushnil(L); 106 else lua_pushnil(L);
153 return 1; 107 return 1;
154} 108}
109
110static void check_obj_tab(lua_State *L, int tabidx)
111{
112 if (tabidx < 0) tabidx = lua_gettop(L) + tabidx + 1;
113 if (lua_istable(L, tabidx)) {
114 lua_pushnil(L);
115 while (lua_next(L, tabidx) != 0) {
116 if (aux_getgroupudata(L, "select{able}", -1) == NULL) {
117 char msg[45];
118 if (lua_isnumber(L, -2))
119 sprintf(msg, "table entry #%g is invalid",
120 lua_tonumber(L, -2));
121 else
122 sprintf(msg, "invalid entry found in table");
123 luaL_argerror(L, tabidx, msg);
124 }
125 lua_pop(L, 1);
126 }
127 } else if (!lua_isnil(L, tabidx))
128 luaL_argerror(L, tabidx, "table or nil expected");
129}
diff --git a/src/select.h b/src/select.h
index 2b2ed19..9521fae 100644
--- a/src/select.h
+++ b/src/select.h
@@ -2,10 +2,9 @@
2* Select implementation 2* Select implementation
3* RCS ID: $Id$ 3* RCS ID: $Id$
4\*=========================================================================*/ 4\*=========================================================================*/
5#ifndef SLCT_H_ 5#ifndef SELECT_H
6#define SLCT_H_ 6#define SELECT_H
7 7
8void select_addclass(lua_State *L, cchar *lsclass);
9void select_open(lua_State *L); 8void select_open(lua_State *L);
10 9
11#endif 10#endif /* SELECT_H */
diff --git a/src/socket.h b/src/socket.h
index f8c5d8f..70ebc52 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -6,16 +6,15 @@
6#ifndef SOCK_H 6#ifndef SOCK_H
7#define SOCK_H 7#define SOCK_H
8 8
9#include <lua.h> 9#include "io.h"
10#include "error.h"
11 10
12/*=========================================================================*\ 11/*=========================================================================*\
13* Platform specific compatibilization 12* Platform specific compatibilization
14\*=========================================================================*/ 13\*=========================================================================*/
15#ifdef WIN32 14#ifdef WIN32
16#include "sockwin32.h" 15#include "wsocket.h"
17#else 16#else
18#include "sockunix.h" 17#include "usocket.h"
19#endif 18#endif
20 19
21/* we are lazy... */ 20/* we are lazy... */
@@ -25,13 +24,13 @@ typedef struct sockaddr SA;
25* Functions bellow implement a comfortable platform independent 24* Functions bellow implement a comfortable platform independent
26* interface to sockets 25* interface to sockets
27\*=========================================================================*/ 26\*=========================================================================*/
28int sock_open(lua_State *L); 27int sock_open(void);
29
30const char *sock_create(p_sock ps, int domain, int type, int protocol); 28const char *sock_create(p_sock ps, int domain, int type, int protocol);
31void sock_destroy(p_sock ps); 29void sock_destroy(p_sock ps);
32void sock_accept(p_sock ps, p_sock pa, SA *addr, size_t *addr_len, int timeout); 30int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
33const char *sock_connect(p_sock ps, SA *addr, size_t addr_len); 31 int timeout);
34const char *sock_bind(p_sock ps, SA *addr, size_t addr_len); 32const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len);
33const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len);
35void sock_listen(p_sock ps, int backlog); 34void sock_listen(p_sock ps, int backlog);
36 35
37int sock_send(p_sock ps, const char *data, size_t count, 36int sock_send(p_sock ps, const char *data, size_t count,
@@ -39,9 +38,9 @@ int sock_send(p_sock ps, const char *data, size_t count,
39int sock_recv(p_sock ps, char *data, size_t count, 38int sock_recv(p_sock ps, char *data, size_t count,
40 size_t *got, int timeout); 39 size_t *got, int timeout);
41int sock_sendto(p_sock ps, const char *data, size_t count, 40int sock_sendto(p_sock ps, const char *data, size_t count,
42 size_t *sent, SA *addr, size_t addr_len, int timeout); 41 size_t *sent, SA *addr, socklen_t addr_len, int timeout);
43int sock_recvfrom(p_sock ps, char *data, size_t count, 42int sock_recvfrom(p_sock ps, char *data, size_t count,
44 size_t *got, SA *addr, size_t *addr_len, int timeout); 43 size_t *got, SA *addr, socklen_t *addr_len, int timeout);
45 44
46void sock_setnonblocking(p_sock ps); 45void sock_setnonblocking(p_sock ps);
47void sock_setblocking(p_sock ps); 46void sock_setblocking(p_sock ps);
@@ -52,6 +51,4 @@ const char *sock_createstrerror(void);
52const char *sock_bindstrerror(void); 51const char *sock_bindstrerror(void);
53const char *sock_connectstrerror(void); 52const char *sock_connectstrerror(void);
54 53
55const char *sock_trysetoptions(lua_State *L, p_sock ps);
56
57#endif /* SOCK_H */ 54#endif /* SOCK_H */
diff --git a/src/tcp.c b/src/tcp.c
index db6a38e..74857c9 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -10,43 +10,49 @@
10 10
11#include "luasocket.h" 11#include "luasocket.h"
12 12
13#include "aux.h" 13#include "auxiliar.h"
14#include "socket.h"
14#include "inet.h" 15#include "inet.h"
16#include "error.h"
15#include "tcp.h" 17#include "tcp.h"
16 18
17/*=========================================================================*\ 19/*=========================================================================*\
18* Internal function prototypes 20* Internal function prototypes
19\*=========================================================================*/ 21\*=========================================================================*/
20static int tcp_global_create(lua_State *L); 22static int global_create(lua_State *L);
21static int tcp_meth_connect(lua_State *L); 23static int meth_connect(lua_State *L);
22static int tcp_meth_bind(lua_State *L); 24static int meth_bind(lua_State *L);
23static int tcp_meth_send(lua_State *L); 25static int meth_send(lua_State *L);
24static int tcp_meth_getsockname(lua_State *L); 26static int meth_getsockname(lua_State *L);
25static int tcp_meth_getpeername(lua_State *L); 27static int meth_getpeername(lua_State *L);
26static int tcp_meth_receive(lua_State *L); 28static int meth_receive(lua_State *L);
27static int tcp_meth_accept(lua_State *L); 29static int meth_accept(lua_State *L);
28static int tcp_meth_close(lua_State *L); 30static int meth_close(lua_State *L);
29static int tcp_meth_timeout(lua_State *L); 31static int meth_timeout(lua_State *L);
32static int meth_fd(lua_State *L);
33static int meth_dirty(lua_State *L);
30 34
31/* tcp object methods */ 35/* tcp object methods */
32static luaL_reg tcp[] = { 36static luaL_reg tcp[] = {
33 {"connect", tcp_meth_connect}, 37 {"connect", meth_connect},
34 {"send", tcp_meth_send}, 38 {"send", meth_send},
35 {"receive", tcp_meth_receive}, 39 {"receive", meth_receive},
36 {"bind", tcp_meth_bind}, 40 {"bind", meth_bind},
37 {"accept", tcp_meth_accept}, 41 {"accept", meth_accept},
38 {"setpeername", tcp_meth_connect}, 42 {"setpeername", meth_connect},
39 {"setsockname", tcp_meth_bind}, 43 {"setsockname", meth_bind},
40 {"getpeername", tcp_meth_getpeername}, 44 {"getpeername", meth_getpeername},
41 {"getsockname", tcp_meth_getsockname}, 45 {"getsockname", meth_getsockname},
42 {"timeout", tcp_meth_timeout}, 46 {"timeout", meth_timeout},
43 {"close", tcp_meth_close}, 47 {"close", meth_close},
48 {"fd", meth_fd},
49 {"dirty", meth_dirty},
44 {NULL, NULL} 50 {NULL, NULL}
45}; 51};
46 52
47/* functions in library namespace */ 53/* functions in library namespace */
48static luaL_reg func[] = { 54static luaL_reg func[] = {
49 {"tcp", tcp_global_create}, 55 {"tcp", global_create},
50 {NULL, NULL} 56 {NULL, NULL}
51}; 57};
52 58
@@ -60,11 +66,13 @@ void tcp_open(lua_State *L)
60 aux_newclass(L, "tcp{client}", tcp); 66 aux_newclass(L, "tcp{client}", tcp);
61 aux_newclass(L, "tcp{server}", tcp); 67 aux_newclass(L, "tcp{server}", tcp);
62 /* create class groups */ 68 /* create class groups */
63 aux_add2group(L, "tcp{client}", "tcp{client, server}");
64 aux_add2group(L, "tcp{server}", "tcp{client, server}");
65 aux_add2group(L, "tcp{master}", "tcp{any}"); 69 aux_add2group(L, "tcp{master}", "tcp{any}");
66 aux_add2group(L, "tcp{client}", "tcp{any}"); 70 aux_add2group(L, "tcp{client}", "tcp{any}");
67 aux_add2group(L, "tcp{server}", "tcp{any}"); 71 aux_add2group(L, "tcp{server}", "tcp{any}");
72 aux_add2group(L, "tcp{client}", "tcp{client, server}");
73 aux_add2group(L, "tcp{server}", "tcp{client, server}");
74 aux_add2group(L, "tcp{client}", "select{able}");
75 aux_add2group(L, "tcp{server}", "select{able}");
68 /* define library functions */ 76 /* define library functions */
69 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); 77 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
70 lua_pop(L, 1); 78 lua_pop(L, 1);
@@ -76,28 +84,45 @@ void tcp_open(lua_State *L)
76/*-------------------------------------------------------------------------*\ 84/*-------------------------------------------------------------------------*\
77* Just call buffered IO methods 85* Just call buffered IO methods
78\*-------------------------------------------------------------------------*/ 86\*-------------------------------------------------------------------------*/
79static int tcp_meth_send(lua_State *L) 87static int meth_send(lua_State *L)
80{ 88{
81 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1); 89 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
82 return buf_meth_send(L, &tcp->buf); 90 return buf_meth_send(L, &tcp->buf);
83} 91}
84 92
85static int tcp_meth_receive(lua_State *L) 93static int meth_receive(lua_State *L)
86{ 94{
87 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1); 95 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
88 return buf_meth_receive(L, &tcp->buf); 96 return buf_meth_receive(L, &tcp->buf);
89} 97}
90 98
91/*-------------------------------------------------------------------------*\ 99/*-------------------------------------------------------------------------*\
100* Select support methods
101\*-------------------------------------------------------------------------*/
102static int meth_fd(lua_State *L)
103{
104 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1);
105 lua_pushnumber(L, tcp->sock);
106 return 1;
107}
108
109static int meth_dirty(lua_State *L)
110{
111 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1);
112 lua_pushboolean(L, !buf_isempty(&tcp->buf));
113 return 1;
114}
115
116/*-------------------------------------------------------------------------*\
92* Just call inet methods 117* Just call inet methods
93\*-------------------------------------------------------------------------*/ 118\*-------------------------------------------------------------------------*/
94static int tcp_meth_getpeername(lua_State *L) 119static int meth_getpeername(lua_State *L)
95{ 120{
96 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1); 121 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
97 return inet_meth_getpeername(L, &tcp->sock); 122 return inet_meth_getpeername(L, &tcp->sock);
98} 123}
99 124
100static int tcp_meth_getsockname(lua_State *L) 125static int meth_getsockname(lua_State *L)
101{ 126{
102 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1); 127 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1);
103 return inet_meth_getsockname(L, &tcp->sock); 128 return inet_meth_getsockname(L, &tcp->sock);
@@ -106,7 +131,7 @@ static int tcp_meth_getsockname(lua_State *L)
106/*-------------------------------------------------------------------------*\ 131/*-------------------------------------------------------------------------*\
107* Just call tm methods 132* Just call tm methods
108\*-------------------------------------------------------------------------*/ 133\*-------------------------------------------------------------------------*/
109static int tcp_meth_timeout(lua_State *L) 134static int meth_timeout(lua_State *L)
110{ 135{
111 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); 136 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
112 return tm_meth_timeout(L, &tcp->tm); 137 return tm_meth_timeout(L, &tcp->tm);
@@ -115,7 +140,7 @@ static int tcp_meth_timeout(lua_State *L)
115/*-------------------------------------------------------------------------*\ 140/*-------------------------------------------------------------------------*\
116* Closes socket used by object 141* Closes socket used by object
117\*-------------------------------------------------------------------------*/ 142\*-------------------------------------------------------------------------*/
118static int tcp_meth_close(lua_State *L) 143static int meth_close(lua_State *L)
119{ 144{
120 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1); 145 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
121 sock_destroy(&tcp->sock); 146 sock_destroy(&tcp->sock);
@@ -125,7 +150,7 @@ static int tcp_meth_close(lua_State *L)
125/*-------------------------------------------------------------------------*\ 150/*-------------------------------------------------------------------------*\
126* Turns a master tcp object into a client object. 151* Turns a master tcp object into a client object.
127\*-------------------------------------------------------------------------*/ 152\*-------------------------------------------------------------------------*/
128static int tcp_meth_connect(lua_State *L) 153static int meth_connect(lua_State *L)
129{ 154{
130 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); 155 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
131 const char *address = luaL_checkstring(L, 2); 156 const char *address = luaL_checkstring(L, 2);
@@ -145,7 +170,7 @@ static int tcp_meth_connect(lua_State *L)
145/*-------------------------------------------------------------------------*\ 170/*-------------------------------------------------------------------------*\
146* Turns a master object into a server object 171* Turns a master object into a server object
147\*-------------------------------------------------------------------------*/ 172\*-------------------------------------------------------------------------*/
148static int tcp_meth_bind(lua_State *L) 173static int meth_bind(lua_State *L)
149{ 174{
150 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1); 175 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
151 const char *address = luaL_checkstring(L, 2); 176 const char *address = luaL_checkstring(L, 2);
@@ -167,10 +192,10 @@ static int tcp_meth_bind(lua_State *L)
167* Waits for and returns a client object attempting connection to the 192* Waits for and returns a client object attempting connection to the
168* server object 193* server object
169\*-------------------------------------------------------------------------*/ 194\*-------------------------------------------------------------------------*/
170static int tcp_meth_accept(lua_State *L) 195static int meth_accept(lua_State *L)
171{ 196{
172 struct sockaddr_in addr; 197 struct sockaddr_in addr;
173 size_t addr_len = sizeof(addr); 198 socklen_t addr_len = sizeof(addr);
174 p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1); 199 p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1);
175 p_tm tm = &server->tm; 200 p_tm tm = &server->tm;
176 p_tcp client = lua_newuserdata(L, sizeof(t_tcp)); 201 p_tcp client = lua_newuserdata(L, sizeof(t_tcp));
@@ -200,7 +225,7 @@ static int tcp_meth_accept(lua_State *L)
200/*-------------------------------------------------------------------------*\ 225/*-------------------------------------------------------------------------*\
201* Creates a master tcp object 226* Creates a master tcp object
202\*-------------------------------------------------------------------------*/ 227\*-------------------------------------------------------------------------*/
203int tcp_global_create(lua_State *L) 228int global_create(lua_State *L)
204{ 229{
205 /* allocate tcp object */ 230 /* allocate tcp object */
206 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); 231 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
diff --git a/src/tcp.h b/src/tcp.h
index d4cc65c..f4319f3 100644
--- a/src/tcp.h
+++ b/src/tcp.h
@@ -3,9 +3,9 @@
3 3
4#include <lua.h> 4#include <lua.h>
5 5
6#include "buf.h" 6#include "buffer.h"
7#include "tm.h" 7#include "timeout.h"
8#include "sock.h" 8#include "socket.h"
9 9
10typedef struct t_tcp_ { 10typedef struct t_tcp_ {
11 t_sock sock; 11 t_sock sock;
diff --git a/src/timeout.c b/src/timeout.c
index 17878aa..1553069 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -12,8 +12,8 @@
12#include <lauxlib.h> 12#include <lauxlib.h>
13 13
14#include "luasocket.h" 14#include "luasocket.h"
15#include "aux.h" 15#include "auxiliar.h"
16#include "tm.h" 16#include "timeout.h"
17 17
18#ifdef WIN32 18#ifdef WIN32
19#include <windows.h> 19#include <windows.h>
@@ -118,6 +118,7 @@ int tm_gettime(void)
118void tm_open(lua_State *L) 118void tm_open(lua_State *L)
119{ 119{
120 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); 120 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
121 lua_pop(L, 1);
121} 122}
122 123
123/*-------------------------------------------------------------------------*\ 124/*-------------------------------------------------------------------------*\
diff --git a/src/udp.c b/src/udp.c
index 1701d1b..bcf515b 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -10,43 +10,49 @@
10 10
11#include "luasocket.h" 11#include "luasocket.h"
12 12
13#include "aux.h" 13#include "auxiliar.h"
14#include "socket.h"
14#include "inet.h" 15#include "inet.h"
16#include "error.h"
15#include "udp.h" 17#include "udp.h"
16 18
17/*=========================================================================*\ 19/*=========================================================================*\
18* Internal function prototypes 20* Internal function prototypes
19\*=========================================================================*/ 21\*=========================================================================*/
20static int udp_global_create(lua_State *L); 22static int global_create(lua_State *L);
21static int udp_meth_send(lua_State *L); 23static int meth_send(lua_State *L);
22static int udp_meth_sendto(lua_State *L); 24static int meth_sendto(lua_State *L);
23static int udp_meth_receive(lua_State *L); 25static int meth_receive(lua_State *L);
24static int udp_meth_receivefrom(lua_State *L); 26static int meth_receivefrom(lua_State *L);
25static int udp_meth_getsockname(lua_State *L); 27static int meth_getsockname(lua_State *L);
26static int udp_meth_getpeername(lua_State *L); 28static int meth_getpeername(lua_State *L);
27static int udp_meth_setsockname(lua_State *L); 29static int meth_setsockname(lua_State *L);
28static int udp_meth_setpeername(lua_State *L); 30static int meth_setpeername(lua_State *L);
29static int udp_meth_close(lua_State *L); 31static int meth_close(lua_State *L);
30static int udp_meth_timeout(lua_State *L); 32static int meth_timeout(lua_State *L);
33static int meth_fd(lua_State *L);
34static int meth_dirty(lua_State *L);
31 35
32/* udp object methods */ 36/* udp object methods */
33static luaL_reg udp[] = { 37static luaL_reg udp[] = {
34 {"setpeername", udp_meth_setpeername}, 38 {"setpeername", meth_setpeername},
35 {"setsockname", udp_meth_setsockname}, 39 {"setsockname", meth_setsockname},
36 {"getsockname", udp_meth_getsockname}, 40 {"getsockname", meth_getsockname},
37 {"getpeername", udp_meth_getpeername}, 41 {"getpeername", meth_getpeername},
38 {"send", udp_meth_send}, 42 {"send", meth_send},
39 {"sendto", udp_meth_sendto}, 43 {"sendto", meth_sendto},
40 {"receive", udp_meth_receive}, 44 {"receive", meth_receive},
41 {"receivefrom", udp_meth_receivefrom}, 45 {"receivefrom", meth_receivefrom},
42 {"timeout", udp_meth_timeout}, 46 {"timeout", meth_timeout},
43 {"close", udp_meth_close}, 47 {"close", meth_close},
48 {"fd", meth_fd},
49 {"dirty", meth_dirty},
44 {NULL, NULL} 50 {NULL, NULL}
45}; 51};
46 52
47/* functions in library namespace */ 53/* functions in library namespace */
48static luaL_reg func[] = { 54static luaL_reg func[] = {
49 {"udp", udp_global_create}, 55 {"udp", global_create},
50 {NULL, NULL} 56 {NULL, NULL}
51}; 57};
52 58
@@ -59,8 +65,10 @@ void udp_open(lua_State *L)
59 aux_newclass(L, "udp{connected}", udp); 65 aux_newclass(L, "udp{connected}", udp);
60 aux_newclass(L, "udp{unconnected}", udp); 66 aux_newclass(L, "udp{unconnected}", udp);
61 /* create class groups */ 67 /* create class groups */
62 aux_add2group(L, "udp{connected}", "udp{any}"); 68 aux_add2group(L, "udp{connected}", "udp{any}");
63 aux_add2group(L, "udp{unconnected}", "udp{any}"); 69 aux_add2group(L, "udp{unconnected}", "udp{any}");
70 aux_add2group(L, "udp{connected}", "select{able}");
71 aux_add2group(L, "udp{unconnected}", "select{able}");
64 /* define library functions */ 72 /* define library functions */
65 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0); 73 luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
66 lua_pop(L, 1); 74 lua_pop(L, 1);
@@ -72,7 +80,7 @@ void udp_open(lua_State *L)
72/*-------------------------------------------------------------------------*\ 80/*-------------------------------------------------------------------------*\
73* Send data through connected udp socket 81* Send data through connected udp socket
74\*-------------------------------------------------------------------------*/ 82\*-------------------------------------------------------------------------*/
75static int udp_meth_send(lua_State *L) 83static int meth_send(lua_State *L)
76{ 84{
77 p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1); 85 p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1);
78 p_tm tm = &udp->tm; 86 p_tm tm = &udp->tm;
@@ -90,7 +98,7 @@ static int udp_meth_send(lua_State *L)
90/*-------------------------------------------------------------------------*\ 98/*-------------------------------------------------------------------------*\
91* Send data through unconnected udp socket 99* Send data through unconnected udp socket
92\*-------------------------------------------------------------------------*/ 100\*-------------------------------------------------------------------------*/
93static int udp_meth_sendto(lua_State *L) 101static int meth_sendto(lua_State *L)
94{ 102{
95 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); 103 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
96 size_t count, sent = 0; 104 size_t count, sent = 0;
@@ -117,7 +125,7 @@ static int udp_meth_sendto(lua_State *L)
117/*-------------------------------------------------------------------------*\ 125/*-------------------------------------------------------------------------*\
118* Receives data from a UDP socket 126* Receives data from a UDP socket
119\*-------------------------------------------------------------------------*/ 127\*-------------------------------------------------------------------------*/
120static int udp_meth_receive(lua_State *L) 128static int meth_receive(lua_State *L)
121{ 129{
122 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 130 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
123 char buffer[UDP_DATAGRAMSIZE]; 131 char buffer[UDP_DATAGRAMSIZE];
@@ -136,11 +144,11 @@ static int udp_meth_receive(lua_State *L)
136/*-------------------------------------------------------------------------*\ 144/*-------------------------------------------------------------------------*\
137* Receives data and sender from a UDP socket 145* Receives data and sender from a UDP socket
138\*-------------------------------------------------------------------------*/ 146\*-------------------------------------------------------------------------*/
139static int udp_meth_receivefrom(lua_State *L) 147static int meth_receivefrom(lua_State *L)
140{ 148{
141 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); 149 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
142 struct sockaddr_in addr; 150 struct sockaddr_in addr;
143 size_t addr_len = sizeof(addr); 151 socklen_t addr_len = sizeof(addr);
144 char buffer[UDP_DATAGRAMSIZE]; 152 char buffer[UDP_DATAGRAMSIZE];
145 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); 153 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
146 int err; 154 int err;
@@ -162,15 +170,33 @@ static int udp_meth_receivefrom(lua_State *L)
162} 170}
163 171
164/*-------------------------------------------------------------------------*\ 172/*-------------------------------------------------------------------------*\
173* Select support methods
174\*-------------------------------------------------------------------------*/
175static int meth_fd(lua_State *L)
176{
177 p_udp udp = (p_udp) aux_checkclass(L, "udp{any}", 1);
178 lua_pushnumber(L, udp->sock);
179 return 1;
180}
181
182static int meth_dirty(lua_State *L)
183{
184 p_udp udp = (p_udp) aux_checkclass(L, "udp{any}", 1);
185 (void) udp;
186 lua_pushboolean(L, 0);
187 return 1;
188}
189
190/*-------------------------------------------------------------------------*\
165* Just call inet methods 191* Just call inet methods
166\*-------------------------------------------------------------------------*/ 192\*-------------------------------------------------------------------------*/
167static int udp_meth_getpeername(lua_State *L) 193static int meth_getpeername(lua_State *L)
168{ 194{
169 p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1); 195 p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1);
170 return inet_meth_getpeername(L, &udp->sock); 196 return inet_meth_getpeername(L, &udp->sock);
171} 197}
172 198
173static int udp_meth_getsockname(lua_State *L) 199static int meth_getsockname(lua_State *L)
174{ 200{
175 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 201 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
176 return inet_meth_getsockname(L, &udp->sock); 202 return inet_meth_getsockname(L, &udp->sock);
@@ -179,7 +205,7 @@ static int udp_meth_getsockname(lua_State *L)
179/*-------------------------------------------------------------------------*\ 205/*-------------------------------------------------------------------------*\
180* Just call tm methods 206* Just call tm methods
181\*-------------------------------------------------------------------------*/ 207\*-------------------------------------------------------------------------*/
182static int udp_meth_timeout(lua_State *L) 208static int meth_timeout(lua_State *L)
183{ 209{
184 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 210 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
185 return tm_meth_timeout(L, &udp->tm); 211 return tm_meth_timeout(L, &udp->tm);
@@ -188,7 +214,7 @@ static int udp_meth_timeout(lua_State *L)
188/*-------------------------------------------------------------------------*\ 214/*-------------------------------------------------------------------------*\
189* Turns a master udp object into a client object. 215* Turns a master udp object into a client object.
190\*-------------------------------------------------------------------------*/ 216\*-------------------------------------------------------------------------*/
191static int udp_meth_setpeername(lua_State *L) 217static int meth_setpeername(lua_State *L)
192{ 218{
193 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1); 219 p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
194 const char *address = luaL_checkstring(L, 2); 220 const char *address = luaL_checkstring(L, 2);
@@ -211,7 +237,7 @@ static int udp_meth_setpeername(lua_State *L)
211/*-------------------------------------------------------------------------*\ 237/*-------------------------------------------------------------------------*\
212* Closes socket used by object 238* Closes socket used by object
213\*-------------------------------------------------------------------------*/ 239\*-------------------------------------------------------------------------*/
214static int udp_meth_close(lua_State *L) 240static int meth_close(lua_State *L)
215{ 241{
216 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1); 242 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
217 sock_destroy(&udp->sock); 243 sock_destroy(&udp->sock);
@@ -221,7 +247,7 @@ static int udp_meth_close(lua_State *L)
221/*-------------------------------------------------------------------------*\ 247/*-------------------------------------------------------------------------*\
222* Turns a master object into a server object 248* Turns a master object into a server object
223\*-------------------------------------------------------------------------*/ 249\*-------------------------------------------------------------------------*/
224static int udp_meth_setsockname(lua_State *L) 250static int meth_setsockname(lua_State *L)
225{ 251{
226 p_udp udp = (p_udp) aux_checkclass(L, "udp{master}", 1); 252 p_udp udp = (p_udp) aux_checkclass(L, "udp{master}", 1);
227 const char *address = luaL_checkstring(L, 2); 253 const char *address = luaL_checkstring(L, 2);
@@ -242,7 +268,7 @@ static int udp_meth_setsockname(lua_State *L)
242/*-------------------------------------------------------------------------*\ 268/*-------------------------------------------------------------------------*\
243* Creates a master udp object 269* Creates a master udp object
244\*-------------------------------------------------------------------------*/ 270\*-------------------------------------------------------------------------*/
245int udp_global_create(lua_State *L) 271int global_create(lua_State *L)
246{ 272{
247 /* allocate udp object */ 273 /* allocate udp object */
248 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); 274 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
diff --git a/src/udp.h b/src/udp.h
index 4ba53e6..a6f17e2 100644
--- a/src/udp.h
+++ b/src/udp.h
@@ -3,8 +3,8 @@
3 3
4#include <lua.h> 4#include <lua.h>
5 5
6#include "tm.h" 6#include "timeout.h"
7#include "sock.h" 7#include "socket.h"
8 8
9#define UDP_DATAGRAMSIZE 576 9#define UDP_DATAGRAMSIZE 576
10 10
diff --git a/src/usocket.c b/src/usocket.c
index b4b8d5a..062a0ff 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -1,24 +1,8 @@
1/*=========================================================================*\
2* Socket compatibilization module for Unix
3*
4* RCS ID: $Id$
5\*=========================================================================*/
6#include <lua.h>
7#include <lauxlib.h>
8#include <string.h> 1#include <string.h>
9 2
10#include "sock.h" 3#include "socket.h"
11 4
12/*=========================================================================*\ 5int sock_open(void)
13* Internal function prototypes
14\*=========================================================================*/
15static const char *try_setoption(lua_State *L, p_sock ps);
16static const char *try_setbooloption(lua_State *L, p_sock ps, int name);
17
18/*=========================================================================*\
19* Exported functions.
20\*=========================================================================*/
21int sock_open(lua_State *L)
22{ 6{
23 /* instals a handler to ignore sigpipe. */ 7 /* instals a handler to ignore sigpipe. */
24 struct sigaction new; 8 struct sigaction new;
@@ -43,13 +27,13 @@ const char *sock_create(p_sock ps, int domain, int type, int protocol)
43 return NULL; 27 return NULL;
44} 28}
45 29
46const char *sock_connect(p_sock ps, SA *addr, size_t addr_len) 30const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len)
47{ 31{
48 if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); 32 if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror();
49 else return NULL; 33 else return NULL;
50} 34}
51 35
52const char *sock_bind(p_sock ps, SA *addr, size_t addr_len) 36const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
53{ 37{
54 if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); 38 if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror();
55 else return NULL; 39 else return NULL;
@@ -60,17 +44,25 @@ void sock_listen(p_sock ps, int backlog)
60 listen(*ps, backlog); 44 listen(*ps, backlog);
61} 45}
62 46
63void sock_accept(p_sock ps, p_sock pa, SA *addr, size_t *addr_len, int timeout) 47int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
48 int timeout)
64{ 49{
65 t_sock sock = *ps; 50 t_sock sock = *ps;
66 struct timeval tv; 51 struct timeval tv;
52 SA dummy_addr;
53 socklen_t dummy_len;
67 fd_set fds; 54 fd_set fds;
68 tv.tv_sec = timeout / 1000; 55 tv.tv_sec = timeout / 1000;
69 tv.tv_usec = (timeout % 1000) * 1000; 56 tv.tv_usec = (timeout % 1000) * 1000;
70 FD_ZERO(&fds); 57 FD_ZERO(&fds);
71 FD_SET(sock, &fds); 58 FD_SET(sock, &fds);
72 select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL); 59 if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0)
60 return IO_TIMEOUT;
61 if (!addr) addr = &dummy_addr;
62 if (!addr_len) addr_len = &dummy_len;
73 *pa = accept(sock, addr, addr_len); 63 *pa = accept(sock, addr, addr_len);
64 if (*pa == SOCK_INVALID) return IO_ERROR;
65 else return IO_DONE;
74} 66}
75 67
76int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, 68int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
@@ -108,7 +100,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
108} 100}
109 101
110int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, 102int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
111 SA *addr, size_t addr_len, int timeout) 103 SA *addr, socklen_t addr_len, int timeout)
112{ 104{
113 t_sock sock = *ps; 105 t_sock sock = *ps;
114 struct timeval tv; 106 struct timeval tv;
@@ -169,7 +161,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
169} 161}
170 162
171int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, 163int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
172 SA *addr, size_t *addr_len, int timeout) 164 SA *addr, socklen_t *addr_len, int timeout)
173{ 165{
174 t_sock sock = *ps; 166 t_sock sock = *ps;
175 struct timeval tv; 167 struct timeval tv;
@@ -196,9 +188,6 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
196 } 188 }
197} 189}
198 190
199/*-------------------------------------------------------------------------*\
200* Returns a string describing the last host manipulation error.
201\*-------------------------------------------------------------------------*/
202const char *sock_hoststrerror(void) 191const char *sock_hoststrerror(void)
203{ 192{
204 switch (h_errno) { 193 switch (h_errno) {
@@ -210,9 +199,6 @@ const char *sock_hoststrerror(void)
210 } 199 }
211} 200}
212 201
213/*-------------------------------------------------------------------------*\
214* Returns a string describing the last socket manipulation error.
215\*-------------------------------------------------------------------------*/
216const char *sock_createstrerror(void) 202const char *sock_createstrerror(void)
217{ 203{
218 switch (errno) { 204 switch (errno) {
@@ -224,9 +210,6 @@ const char *sock_createstrerror(void)
224 } 210 }
225} 211}
226 212
227/*-------------------------------------------------------------------------*\
228* Returns a string describing the last bind command error.
229\*-------------------------------------------------------------------------*/
230const char *sock_bindstrerror(void) 213const char *sock_bindstrerror(void)
231{ 214{
232 switch (errno) { 215 switch (errno) {
@@ -241,9 +224,6 @@ const char *sock_bindstrerror(void)
241 } 224 }
242} 225}
243 226
244/*-------------------------------------------------------------------------*\
245* Returns a string describing the last connect error.
246\*-------------------------------------------------------------------------*/
247const char *sock_connectstrerror(void) 227const char *sock_connectstrerror(void)
248{ 228{
249 switch (errno) { 229 switch (errno) {
@@ -259,20 +239,12 @@ const char *sock_connectstrerror(void)
259 } 239 }
260} 240}
261 241
262/*-------------------------------------------------------------------------*\
263* Sets the SO_REUSEADDR socket option
264* Input
265* sock: socket descriptor
266\*-------------------------------------------------------------------------*/
267void sock_setreuseaddr(p_sock ps) 242void sock_setreuseaddr(p_sock ps)
268{ 243{
269 int val = 1; 244 int val = 1;
270 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); 245 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
271} 246}
272 247
273/*-------------------------------------------------------------------------*\
274* Put socket into blocking mode.
275\*-------------------------------------------------------------------------*/
276void sock_setblocking(p_sock ps) 248void sock_setblocking(p_sock ps)
277{ 249{
278 int flags = fcntl(*ps, F_GETFL, 0); 250 int flags = fcntl(*ps, F_GETFL, 0);
@@ -280,68 +252,9 @@ void sock_setblocking(p_sock ps)
280 fcntl(*ps, F_SETFL, flags); 252 fcntl(*ps, F_SETFL, flags);
281} 253}
282 254
283/*-------------------------------------------------------------------------*\
284* Put socket into non-blocking mode.
285\*-------------------------------------------------------------------------*/
286void sock_setnonblocking(p_sock ps) 255void sock_setnonblocking(p_sock ps)
287{ 256{
288 int flags = fcntl(*ps, F_GETFL, 0); 257 int flags = fcntl(*ps, F_GETFL, 0);
289 flags |= O_NONBLOCK; 258 flags |= O_NONBLOCK;
290 fcntl(*ps, F_SETFL, flags); 259 fcntl(*ps, F_SETFL, flags);
291} 260}
292
293/*-------------------------------------------------------------------------*\
294* Tries to set extended udp socket options
295* Input
296* udp: udp structure
297* oldtop: top of stack
298* Returns
299* NULL if successfull, error message on error
300\*-------------------------------------------------------------------------*/
301const char *sock_trysetoptions(lua_State *L, p_sock ps)
302{
303 if (!lua_istable(L, 1)) luaL_argerror(L, 1, "invalid options table");
304 lua_pushnil(L);
305 while (lua_next(L, 1)) {
306 const char *err = try_setoption(L, ps);
307 lua_pop(L, 1);
308 if (err) return err;
309 }
310 return NULL;
311}
312
313/*-------------------------------------------------------------------------*\
314* Set socket options from a table on top of Lua stack.
315* Supports SO_KEEPALIVE, SO_DONTROUTE, and SO_BROADCAST options.
316* Input
317* sock: socket
318* Returns
319* 1 if successful, 0 otherwise
320\*-------------------------------------------------------------------------*/
321static const char *try_setoption(lua_State *L, p_sock ps)
322{
323 static const char *options[] = {
324 "SO_KEEPALIVE", "SO_DONTROUTE", "SO_BROADCAST", NULL
325 };
326 const char *option = lua_tostring(L, -2);
327 if (!lua_isstring(L, -2)) return "invalid option";
328 switch (luaL_findstring(option, options)) {
329 case 0: return try_setbooloption(L, ps, SO_KEEPALIVE);
330 case 1: return try_setbooloption(L, ps, SO_DONTROUTE);
331 case 2: return try_setbooloption(L, ps, SO_BROADCAST);
332 default: return "unsupported option";
333 }
334}
335
336/*=========================================================================*\
337* Internal functions.
338\*=========================================================================*/
339static const char *try_setbooloption(lua_State *L, p_sock ps, int name)
340{
341 int bool, res;
342 if (!lua_isnumber(L, -1)) luaL_error(L, "invalid option value");
343 bool = (int) lua_tonumber(L, -1);
344 res = setsockopt(*ps, SOL_SOCKET, name, (char *) &bool, sizeof(bool));
345 if (res < 0) return "error setting option";
346 else return NULL;
347}
diff --git a/src/usocket.h b/src/usocket.h
index f124bce..9e4b75a 100644
--- a/src/usocket.h
+++ b/src/usocket.h
@@ -31,6 +31,11 @@
31#include <netinet/in.h> 31#include <netinet/in.h>
32#include <arpa/inet.h> 32#include <arpa/inet.h>
33 33
34#ifdef __APPLE__
35/* for some reason socklen_t is not defined in mac os x */
36typedef int socklen_t;
37#endif
38
34typedef int t_sock; 39typedef int t_sock;
35typedef t_sock *p_sock; 40typedef t_sock *p_sock;
36 41