1 --[==========================================================================[
2 telnet.lua: VLM interface plugin
3 --[==========================================================================[
4 Copyright (C) 2007 the VideoLAN team
7 Authors: Antoine Cellerier <dionoea at videolan dot org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 --]==========================================================================]
24 --[==========================================================================[
25 Copy (features wise) of the original VLC modules/control/telnet.c module.
29 * 'lock' command to lock the telnet promt
30 * possibility to listen on different hosts including stdin
32 listen on stdin: vlc -I lua --lua-intf telnet --lua-config "telnet={host='*console'}"
33 listen on stdin + 2 ports on localhost: vlc -I lua --lua-intf telnet --lua-config "telnet={hosts={'localhost:4212','localhost:5678','*console'}}"
34 --]==========================================================================]
38 --[[ Some telnet command special characters ]]
39 WILL = "\251" -- Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option.
40 WONT = "\252" -- Indicates the refusal to perform, or continue performing, the indicated option.
41 DO = "\253" -- Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option.
42 DONT = "\254" -- Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option.
43 IAC = "\255" -- Interpret as command
47 --[[ Client status change callbacks ]]
48 function on_password( client )
49 if client.type == host.client_type.net then
50 client:send( "Password: " ..IAC..WILL..ECHO )
52 -- no authentification needed on stdin
53 client:switch_status( host.status.read )
56 function on_read( client )
59 function on_write( client )
62 --[[ Misc functions ]]
63 function telnet_commands( client )
64 -- remove telnet command replies from the client's data
65 client.buffer = string.gsub( client.buffer, IAC.."["..DO..DONT..WILL..WONT.."].", "" )
68 function vlm_message_to_string(client,message,prefix)
69 local prefix = prefix or ""
71 client:append(prefix .. message.name .. " : " .. message.value)
74 client:append(prefix .. message.name)
75 if message.children then
76 for i,c in ipairs(message.children) do
77 vlm_message_to_string(client,c,prefix.." ")
84 --[[ Configure the host ]]
87 h.status_callbacks[host.status.password] = on_password
88 h.status_callbacks[host.status.read] = on_read
89 h.status_callbacks[host.status.write] = on_write
91 h:listen( config.hosts or config.host or "localhost:4212" )
92 password = config.password or "admin"
98 function shutdown(client)
99 h:broadcast("Shutting down.\r\n")
100 vlc.msg.err("shutdown requested")
104 function logout(client)
108 function quit(client)
109 if client.type == host.client_type.net then
110 return logout(client)
112 return shutdown(client)
115 function lock(client)
117 client:switch_status( host.status.password )
121 function help(client)
122 client:append(" Telnet Specific Commands:")
123 for c,t in pairs(commands) do
124 client:append(" "..c.." : "..t.help)
129 ["shutdown"] = { func = shutdown, help = "shutdown VLC" },
130 ["quit"] = { func = quit, help = "logout from telnet/shutdown VLC from local shell" },
131 ["logout"] = { func = logout, help = "logout" },
132 ["lock"] = { func = lock, help = "lock the telnet prompt" },
133 ["help"] = { func = help, help = "show this help", dovlm = true },
136 function client_command( client )
137 local cmd = client.buffer
139 if not commands[cmd] or not commands[cmd].func or commands[cmd].dovlm then
140 -- if it's not an interface specific command, it has to be a VLM command
141 message = vlc.vlm.execute_command( vlm, cmd )
142 vlm_message_to_string( client, message )
143 if not commands[cmd] or not commands[cmd].func and not commands[cmd].dovlm then
147 ok, msg = pcall( commands[cmd].func, client )
149 client:append( "Error in `"..cmd.."' "..msg )
155 --[[ The main loop ]]
156 while not vlc.should_die() do
158 local w, r = h:select( 0.1 )
161 for _, client in pairs(w) do
162 local len = client:send()
163 client.buffer = string.sub(client.buffer,len+1)
164 if client.buffer == "" then client:switch_status( host.status.read ) end
168 for _, client in pairs(r) do
169 local str = client:recv(1000)
171 if string.match(str,"\n$") then
172 client.buffer = string.gsub(client.buffer..str,"\r?\n$","")
174 elseif client.buffer == ""
175 and ((client.type == host.client_type.stdio and str == "")
176 or (client.type == host.client_type.net and str == "\004")) then
178 client.buffer = "quit"
181 client.buffer = client.buffer .. str
183 if client.type == host.client_type.net then
184 telnet_commands( client )
187 if client.status == host.status.password then
188 if client.buffer == password then
189 client:send( IAC..WONT..ECHO.."\r\nWelcome, Master\r\n" )
191 client:switch_status( host.status.write )
193 client:send( "\r\nWrong password\r\nPassword: " )
196 elseif client_command( client ) then
197 client:switch_status( host.status.write )
204 vlc.vlm.delete( vlm )