1
mirror of https://code.videolan.org/videolan/vlc synced 2024-08-31 06:46:39 +02:00

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

This commit is contained in:
Antoine Cellerier 2010-01-09 01:49:54 +01:00
parent 92432bcb27
commit 8bbd4a3154
3 changed files with 74 additions and 33 deletions

View File

@ -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" );
}

View File

@ -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

View File

@ -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
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
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 ret = vlc.net.select( nfds, fds_read, fds_write,
timeout or -1 )
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
pollfds[fd] = vlc.net.POLLIN
end
end
end
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