aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-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
18 files changed, 344 insertions, 344 deletions
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