Commit 8bbd4a31 authored by Antoine Cellerier's avatar Antoine Cellerier

Add vlc.net.poll() and use in modules/host.lua.

parent 92432bcb
......@@ -125,7 +125,6 @@ static int vlclua_net_listen_close( lua_State *L )
static int vlclua_net_fds( lua_State *L )
{
vlc_object_t *p_this = vlclua_get_this( L );
int **ppi_fd = (int**)luaL_checkudata( L, 1, "net_listen" );
int *pi_fd = *ppi_fd;
......@@ -208,6 +207,43 @@ static int vlclua_net_recv( lua_State *L )
/*****************************************************************************
*
*****************************************************************************/
/* Takes a { fd : events } table as first arg and modifies it to { fd : revents } */
static int vlclua_net_poll( lua_State *L )
{
luaL_checktype( L, 1, LUA_TTABLE );
double f_timeout = luaL_optnumber( L, 2, -1. );
int i_fds = 0;
lua_pushnil( L );
while( lua_next( L, 1 ) )
{
i_fds++;
lua_pop( L, 1 );
}
struct pollfd *p_fds = malloc( i_fds * sizeof( struct pollfd ) );
lua_pushnil( L );
int i = 0;
while( lua_next( L, 1 ) )
{
p_fds[i].fd = luaL_checkinteger( L, -2 );
p_fds[i].events = luaL_checkinteger( L, -1 );
p_fds[i].revents = 0;
lua_pop( L, 1 );
i++;
}
int i_ret = poll( p_fds, i_fds, f_timeout < 0. ? -1 : (int)(f_timeout*1000) );
for( i = 0; i < i_fds; i++ )
{
lua_pushinteger( L, p_fds[i].fd );
lua_pushinteger( L, p_fds[i].revents );
lua_settable( L, 1 );
}
free( p_fds );
lua_pushinteger( L, i_ret );
return 1;
}
static int vlclua_net_select( lua_State *L )
{
int i_ret;
......@@ -423,6 +459,7 @@ static const luaL_Reg vlclua_net_reg[] = {
{ "close", vlclua_net_close },
{ "send", vlclua_net_send },
{ "recv", vlclua_net_recv },
{ "poll", vlclua_net_poll },
{ "select", vlclua_net_select },
{ "fd_set_new", vlclua_fd_set_new },
{ "read", vlclua_fd_read },
......@@ -436,5 +473,15 @@ void luaopen_net( lua_State *L )
{
lua_newtable( L );
luaL_register( L, NULL, vlclua_net_reg );
#define ADD_CONSTANT( name, value ) \
lua_pushinteger( L, value ); \
lua_setfield( L, -2, name );
ADD_CONSTANT( "POLLIN", POLLIN )
ADD_CONSTANT( "POLLPRI", POLLPRI )
ADD_CONSTANT( "POLLOUT", POLLOUT )
ADD_CONSTANT( "POLLRDHUP", POLLRDHUP )
ADD_CONSTANT( "POLLERR", POLLERR )
ADD_CONSTANT( "POLLHUP", POLLHUP )
ADD_CONSTANT( "POLLNVAL", POLLNVAL )
lua_setfield( L, -2, "net" );
}
......@@ -126,9 +126,12 @@ end
net.close( fd ): Close file descriptor.
net.send( fd, string, [length] ): Send data on fd.
net.recv( fd, [max length] ): Receive data from fd.
net.poll( { fd = events }, [timeout in seconds] ): Implement poll function.
Retruns the numbers of file descriptors with a non 0 revent. The function
modifies the input table to { fd = revents }. See "man poll".
net.POLLIN/POLLPRI/POLLOUT/POLLRDHUP/POLLERR/POLLHUP/POLLNVAL: poll event flags
net.select( nfds, fds_read, fds_write, timeout ): Monitor a bunch of file
descriptors. Returns number of fds to handle and the amount of time not
slept. See "man select".
descriptors. Returns number of fds to handle. See "man select".
net.fd_set_new(): Create a new fd_set.
local fds = vlc.net.fd_set_new()
fds:clr( fd ) -- remove fd from set
......
......@@ -72,10 +72,6 @@ function host()
local listeners = {}
local status_callbacks = {}
-- private data
local fds_read = vlc.net.fd_set_new()
local fds_write = vlc.net.fd_set_new()
-- private methods
local function fd_client( client )
if client.status == status.read then
......@@ -177,18 +173,6 @@ function host()
client:switch_status(status.password)
end
function filter_client( fd, status, status2 )
local l = 0
fd:zero()
for _, client in pairs(clients) do
if client.status == status or client.status == status2 then
fd:set( client:fd() )
l = math.max( l, client:fd() )
end
end
return l
end
-- public methods
local function _listen_tcp( h, host, port )
if listeners.tcp and listeners.tcp[host]
......@@ -238,36 +222,42 @@ function host()
end
local function _accept_and_select( h, timeout )
local nfds = math.max( filter_client( fds_read, status.read, status.password ),
filter_client( fds_write, status.write ) ) + 1
local function filter_client( fds, status, event )
for _, client in pairs(clients) do
if client.status == status then
fds[client:fd()] = event
end
end
end
local pollfds = {}
filter_client( pollfds, status.read, vlc.net.POLLIN )
filter_client( pollfds, status.password, vlc.net.POLLIN )
filter_client( pollfds, status.write, vlc.net.POLLOUT )
if listeners.tcp then
for _, listener in pairs(listeners.tcp.list) do
for _, fd in pairs({listener:fds()}) do
fds_read:set(fd)
if fd >= nfds then
nfds = fd + 1
end
pollfds[fd] = vlc.net.POLLIN
end
end
end
local ret = vlc.net.select( nfds, fds_read, fds_write,
timeout or -1 )
local ret = vlc.net.poll( pollfds, timeout or -1 )
local wclients = {}
local rclients = {}
if ret > 0 then
for _, client in pairs(clients) do
if fds_write:isset( client:fd() ) then
if pollfds[client:fd()] == vlc.net.POLLOUT then
table.insert(wclients,client)
end
if fds_read:isset( client:fd() ) then
if pollfds[client:fd()] == vlc.net.POLLIN then
table.insert(rclients,client)
end
end
if listeners.tcp then
for _, listener in pairs(listeners.tcp.list) do
for _, fd in pairs({listener:fds()}) do
if fds_read:isset(fd) then
if pollfds[fd] == vlc.net.POLLIN then
local afd = listener:accept(0)
new_client( h, afd, afd, client_type.net )
break
......@@ -276,6 +266,7 @@ function host()
end
end
end
return wclients, rclients
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment