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
|
/*=========================================================================*\
* Select implementation
* LuaSocket toolkit
*
* RCS ID: $Id: select.c,v 1.10 2003/06/26 18:47:47 diego Exp $
\*=========================================================================*/
#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
\*-------------------------------------------------------------------------*/
void 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);
}
/*=========================================================================*\
* 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");
}
|