103 lines
3.6 KiB
Lua
103 lines
3.6 KiB
Lua
local os_execute = os.execute
|
|
function set_insecure_environment(env)
|
|
env = env or _G
|
|
os_execute = env.os.execute
|
|
local socket
|
|
local original_require = rawget(_G, "require")
|
|
rawset(_G, "require", env.require)
|
|
pcall(function() socket = env.require"socket" end)
|
|
rawset(_G, "require", original_require)
|
|
build_bridge = (socket and build_socket_bridge) or build_file_bridge
|
|
set_insecure_environment = nil
|
|
end
|
|
|
|
local ping_timeout = 5
|
|
|
|
function build_socket_bridge(name, logs)
|
|
local server = socket.tcp()
|
|
server:bind("*", 0)
|
|
server:settimeout(5)
|
|
local ip, port = server:getsockname()
|
|
local logs=logs or minetest.get_worldpath().."/bridges/"..name.."/logs.txt"
|
|
minetest.mkdir(minetest.get_worldpath().."/bridges/"..name)
|
|
modlib.file.create_if_not_exists(logs, "")
|
|
minetest.register_on_shutdown(function()
|
|
server:close()
|
|
end)
|
|
|
|
local self = {
|
|
info={name=name, server=server, ip=ip, port=port},
|
|
serve=function() end
|
|
}
|
|
|
|
function self.start(process)
|
|
os_execute(process:format("", tostring(port), logs))
|
|
self.client = server:accept()
|
|
self.start=nil
|
|
end
|
|
|
|
function self.write(line)
|
|
self.client:send(line.."\n")
|
|
end
|
|
|
|
function self.listen(line_consumer)
|
|
local status, err_msg=server:listen()
|
|
if status ~= 1 then
|
|
minetest.request_shutdown("adv_chat: "..name..": socket error: "..err_msg)
|
|
end
|
|
minetest.register_globalstep(function()
|
|
local available = socket.select({self.client}, nil, 0)
|
|
if next(available) then
|
|
local line, error = self.client:receive("*l")
|
|
if not error then
|
|
if modlib.text.starts_with(line, "[KIL]") then
|
|
minetest.request_shutdown("adv_chat: "..name..": process terminated: "..line:sub(6))
|
|
else
|
|
line_consumer(line)
|
|
end
|
|
elseif error=="closed" then
|
|
minetest.request_shutdown("adv_chat: "..name..": socket closed")
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
return self
|
|
end
|
|
|
|
function build_file_bridge(name, input, output, logs)
|
|
modlib.file.process_bridge_build(name, input, output, logs)
|
|
local self
|
|
self = {
|
|
info={name=name, ref=modlib.file.process_bridges[name]},
|
|
serve=function()
|
|
return modlib.file.process_bridge_serve(name)
|
|
end,
|
|
write=function(line)
|
|
return modlib.file.process_bridge_write(name, line)
|
|
end,
|
|
listen=function(line_consumer)
|
|
function consumer(line)
|
|
if modlib.text.starts_with(line, "[PIN]") then
|
|
self.last_ping = minetest.get_gametime()
|
|
elseif modlib.text.starts_with(line, "[KIL]") then
|
|
minetest.request_shutdown("adv_chat: "..name..": process terminated: "..line:sub(6))
|
|
else
|
|
return line_consumer(line)
|
|
end
|
|
end
|
|
return modlib.file.process_bridge_listen(name, consumer)
|
|
end
|
|
}
|
|
self.start=function(process)
|
|
modlib.file.process_bridge_start(name, process, os_execute)
|
|
self.last_ping = minetest.get_gametime()
|
|
minetest.register_globalstep(function()
|
|
self.last_ping = self.last_ping or minetest.get_gametime()
|
|
if minetest.get_gametime()-self.last_ping > ping_timeout then
|
|
minetest.request_shutdown("adv_chat: "..name..": process crashed (no ping during last "..ping_timeout.."s)")
|
|
end
|
|
end)
|
|
self.start = nil
|
|
end
|
|
return self
|
|
end |