1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
/*=========================================================================*\
* Select implementation
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#include <string.h>
#include <lua.h>
#include <lauxlib.h>
#include "luasocket.h"
#include "socket.h"
#include "auxiliar.h"
#include "select.h"
/*=========================================================================*\
* Internal function prototypes.
\*=========================================================================*/
static int meth_set(lua_State *L);
static int meth_isset(lua_State *L);
static int c_select(lua_State *L);
static int global_select(lua_State *L);
static void check_obj_tab(lua_State *L, int tabidx);
/* fd_set object methods */
static luaL_reg set[] = {
{"set", meth_set},
{"isset", meth_isset},
{NULL, NULL}
};
/* functions in library namespace */
static luaL_reg func[] = {
{"select", global_select},
{NULL, NULL}
};
/*=========================================================================*\
* Internal function prototypes.
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Initializes module
\*-------------------------------------------------------------------------*/
int select_open(lua_State *L)
{
/* get select auxiliar lua function from lua code and register
* pass it as an upvalue to global_select */
#ifdef LUASOCKET_COMPILED
#include "select.lch"
#else
lua_dofile(L, "select.lua");
#endif
luaL_openlib(L, LUASOCKET_LIBNAME, func, 1);
lua_pop(L, 1);
aux_newclass(L, "select{fd_set}", set);
return 0;
}
/*=========================================================================*\
* Global Lua functions
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Waits for a set of sockets until a condition is met or timeout.
\*-------------------------------------------------------------------------*/
static int global_select(lua_State *L)
{
fd_set *read_fd_set, *write_fd_set;
/* make sure we have enough arguments (nil is the default) */
lua_settop(L, 3);
/* check object tables */
check_obj_tab(L, 1);
check_obj_tab(L, 2);
/* check timeout */
if (!lua_isnil(L, 3) && !lua_isnumber(L, 3))
luaL_argerror(L, 3, "number or nil expected");
/* select auxiliar lua function to be called comes first */
lua_pushvalue(L, lua_upvalueindex(1));
lua_insert(L, 1);
/* pass fd_set objects */
read_fd_set = (fd_set *) lua_newuserdata(L, sizeof(fd_set));
FD_ZERO(read_fd_set);
aux_setclass(L, "select{fd_set}", -1);
write_fd_set = (fd_set *) lua_newuserdata(L, sizeof(fd_set));
FD_ZERO(write_fd_set);
aux_setclass(L, "select{fd_set}", -1);
/* pass select auxiliar C function */
lua_pushcfunction(L, c_select);
/* call select auxiliar lua function */
lua_call(L, 6, 3);
return 3;
}
/*=========================================================================*\
* Lua methods
\*=========================================================================*/
static int meth_set(lua_State *L)
{
fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1);
t_sock fd = (t_sock) lua_tonumber(L, 2);
if (fd >= 0) FD_SET(fd, set);
return 0;
}
static int meth_isset(lua_State *L)
{
fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1);
t_sock fd = (t_sock) lua_tonumber(L, 2);
if (fd >= 0 && FD_ISSET(fd, set)) lua_pushnumber(L, 1);
else lua_pushnil(L);
return 1;
}
/*=========================================================================*\
* Internal functions
\*=========================================================================*/
static int c_select(lua_State *L)
{
int max_fd = (int) lua_tonumber(L, 1);
fd_set *read_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 2);
fd_set *write_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 3);
int timeout = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000);
struct timeval tv;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
lua_pushnumber(L, select(max_fd, read_fd_set, write_fd_set, NULL,
timeout < 0 ? NULL : &tv));
return 1;
}
static void check_obj_tab(lua_State *L, int tabidx)
{
if (tabidx < 0) tabidx = lua_gettop(L) + tabidx + 1;
if (lua_istable(L, tabidx)) {
lua_pushnil(L);
while (lua_next(L, tabidx) != 0) {
if (aux_getgroupudata(L, "select{able}", -1) == NULL) {
char msg[45];
if (lua_isnumber(L, -2))
sprintf(msg, "table entry #%g is invalid",
lua_tonumber(L, -2));
else
sprintf(msg, "invalid entry found in table");
luaL_argerror(L, tabidx, msg);
}
lua_pop(L, 1);
}
} else if (!lua_isnil(L, tabidx))
luaL_argerror(L, tabidx, "table or nil expected");
}
|