X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=share%2Flua%2Fintf%2Fmodules%2Fhost.lua;h=8b52e0bf08508efca86d6f588edff54255c8cae7;hb=fdcdeaa3da38b09860fa0d8e8398e27468660f19;hp=4601b253c8d4dd9540f13317fc450b03035c3fb1;hpb=c4e65e386a753aef5d9954b2dc280056b8682e4b;p=vlc diff --git a/share/lua/intf/modules/host.lua b/share/lua/intf/modules/host.lua index 4601b253c8..8b52e0bf08 100644 --- a/share/lua/intf/modules/host.lua +++ b/share/lua/intf/modules/host.lua @@ -52,6 +52,7 @@ Example use: -- handle clients in read mode for _, client in pairs(read) do local str = client:recv(1000) + if not str then break end str = string.gsub(str,"\r?\n$","") client.buffer = "Got `"..str.."'.\r\n" client:switch_status( host.status.write ) @@ -64,7 +65,11 @@ For complete examples see existing VLC Lua interface modules (ie telnet.lua) module("host",package.seeall) status = { init = 0, read = 1, write = 2, password = 3 } -client_type = { net = 1, stdio = 2, fifo = 3 } +client_type = { net = 1, stdio = 2, fifo = 3, telnet = 4 } + +function is_flag_set(val, flag) + return (((val - (val % flag)) / flag) % 2 ~= 0) +end function host() -- private data @@ -116,7 +121,8 @@ function host() end for i, c in pairs(clients) do if c == client then - if client.type == client_type.net then + if client.type == client_type.net + or client.type == client_type.telnet then if client.wfd ~= client.rfd then vlc.net.close( client.rfd ) end @@ -128,7 +134,7 @@ function host() end vlc.msg.err("couldn't find client to remove.") end - + local function switch_status( client, s ) if client.status == s then return end client.status = s @@ -145,7 +151,7 @@ function host() local function new_client( h, fd, wfd, t ) if fd < 0 then return end local w, r - if t == client_type.net then + if t == client_type.net or t == client_type.telnet then w = send r = recv else if t == client_type.stdio or t == client_type.fifo then @@ -175,7 +181,7 @@ function host() end -- public methods - local function _listen_tcp( h, host, port ) + local function _listen_tcp( h, host, port, telnet ) if listeners.tcp and listeners.tcp[host] and listeners.tcp[host][port] then error("Already listening on tcp host `"..host..":"..tostring(port).."'") @@ -186,19 +192,19 @@ function host() if not listeners.tcp[host] then listeners.tcp[host] = {} end - local listener = vlc.net.listen_tcp( host, port ) - listeners.tcp[host][port] = listener + listeners.tcp[host][port] = true if not listeners.tcp.list then -- FIXME: if host == "list" we'll have a problem listeners.tcp.list = {} - local m = { __mode = "v" } -- week values - setmetatable( listeners.tcp.list, m ) end - table.insert( listeners.tcp.list, listener ) + local listener = vlc.net.listen_tcp( host, port ) + local type = telnet and client_type.telnet or client_type.net; + table.insert( listeners.tcp.list, { data = listener, + type = type, + } ) end local function _listen_stdio( h ) - if listeners.stdio then error("Already listening on stdio") end @@ -217,7 +223,7 @@ function host() h:listen_stdio() else u = vlc.net.url_parse( url ) - h:listen_tcp( u.host, u.port ) + h:listen_tcp( u.host, u.port, (u.protocol == "telnet") ) end end end @@ -237,7 +243,7 @@ function host() 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 + for _, fd in pairs({listener.data:fds()}) do pollfds[fd] = vlc.net.POLLIN end end @@ -248,19 +254,22 @@ function host() local rclients = {} if ret > 0 then for _, client in pairs(clients) do - if pollfds[client:fd()] == vlc.net.POLLOUT then + if is_flag_set(pollfds[client:fd()], vlc.net.POLLERR) + or is_flag_set(pollfds[client:fd()], vlc.net.POLLHUP) + or is_flag_set(pollfds[client:fd()], vlc.net.POLLNVAL) then + del_client(client) + elseif is_flag_set(pollfds[client:fd()], vlc.net.POLLOUT) then table.insert(wclients,client) - end - if pollfds[client:fd()] == vlc.net.POLLIN then + elseif is_flag_set(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 pollfds[fd] == vlc.net.POLLIN then - local afd = listener:accept() - new_client( h, afd, afd, client_type.net ) + for _, fd in pairs({listener.data:fds()}) do + if is_flag_set(pollfds[fd], vlc.net.POLLIN) then + local afd = listener.data:accept() + new_client( h, afd, afd, listener.type ) break end end @@ -271,11 +280,13 @@ function host() return wclients, rclients end + -- FIXME: this is never called, client sockets are leaked local function destructor( h ) print "destructor" for _,client in pairs(clients) do - client:send("Shutting down.") - if client.type == client_type.tcp then + --client:send("Shutting down.") + if client.type == client_type.net + or client.type == client_type.telnet then if client.wfd ~= client.rfd then vlc.net.close(client.rfd) end @@ -301,14 +312,5 @@ function host() broadcast = _broadcast, } - -- the metatable - local m = { -- data - __metatable = "Nothing to see here. Move along.", - -- methods - __gc = destructor, - } - - setmetatable( h, m ) - return h end