require "host"
h = host.host()
- -- Bypass any authentification
+ -- Bypass any authentication
function on_password( client )
client:switch_status( host.status.read )
end
-- 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 )
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
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
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
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
wfd = wfd or fd,
status = status.init,
buffer = "",
+ cmds = "",
type = t,
-- methods
fd = fd_client,
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).."'")
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
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
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
end
- local ret = vlc.net.poll( pollfds, timeout or -1 )
+ local ret = vlc.net.poll( pollfds )
local wclients = {}
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
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
broadcast = _broadcast,
}
- -- the metatable
- local m = { -- data
- __metatable = "Nothing to see here. Move along.",
- -- methods
- __gc = destructor,
- }
-
- setmetatable( h, m )
-
return h
end