forked from izaya/OC-PsychOS2
address RPC loop issues as described in https://github.com/ShadowKatStudios/OC-Minitel/pull/40 plus implement ACLs like the OpenOS version of the RPC library
This commit is contained in:
parent
026f2524e6
commit
a7708b9e47
44
lib/rpc.lua
44
lib/rpc.lua
@ -5,19 +5,34 @@ local rpc = {}
|
|||||||
_G.rpcf = {}
|
_G.rpcf = {}
|
||||||
rpc.port = 111
|
rpc.port = 111
|
||||||
|
|
||||||
|
local function setacl(self, fname, host)
|
||||||
|
self[fname] = self[fname] or {}
|
||||||
|
self[fname][host] = true
|
||||||
|
end
|
||||||
|
rpc.allow = setmetatable({},{__call=setacl})
|
||||||
|
rpc.deny = setmetatable({},{__call=setacl})
|
||||||
|
|
||||||
|
local function isPermitted(host,fn)
|
||||||
|
if rpc.allow[fn] then
|
||||||
|
return rpc.allow[fn][host] or false
|
||||||
|
end
|
||||||
|
if rpc.deny[fn] and rpc.deny[fn][host] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
local function rpcexec(_, from, port, data)
|
local function rpcexec(_, from, port, data)
|
||||||
|
os.spawn(function()
|
||||||
if port == rpc.port then
|
if port == rpc.port then
|
||||||
local rpcrq = serial.unserialize(data)
|
local rpcrq = serial.unserialize(data) or {}
|
||||||
local rpcn, rpcid = table.remove(rpcrq,1), table.remove(rpcrq,1)
|
if rpcf[rpcrq[1]] and isPermitted(from,rpcrq[1]) then
|
||||||
if rpcf[rpcn] then
|
minitel.send(from,port,serial.serialize({rpcrq[2],pcall(rpcf[rpcrq[1]],table.unpack(rpcrq,3))}))
|
||||||
local rt = {pcall(rpcf[rpcn],table.unpack(rpcrq))}
|
elseif type(rpcrq[2]) == "string" then
|
||||||
if rt[1] == true then
|
minitel.send(from,port,serial.serialize({rpcrq[2],false,"function unavailable"}))
|
||||||
table.remove(rt,1)
|
|
||||||
end
|
|
||||||
minitel.send(from,port,serial.serialize({rpcid,table.unpack(rt)}))
|
|
||||||
else
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end,"rpc worker for "..tostring(from))
|
||||||
end
|
end
|
||||||
function rpcf.list()
|
function rpcf.list()
|
||||||
local rt = {}
|
local rt = {}
|
||||||
@ -39,10 +54,13 @@ function rpc.call(hostname,fn,...) -- string string -- boolean -- Calls exported
|
|||||||
local _, from, port, data = event.pull(30, "net_msg", hostname, rpc.port)
|
local _, from, port, data = event.pull(30, "net_msg", hostname, rpc.port)
|
||||||
rt = serial.unserialize(tostring(data)) or {}
|
rt = serial.unserialize(tostring(data)) or {}
|
||||||
until (type(rt) == "table" and rt[1] == rv) or computer.uptime() > st + 30
|
until (type(rt) == "table" and rt[1] == rv) or computer.uptime() > st + 30
|
||||||
if table.remove(rt,1) == rv then
|
if rt[1] == rv then
|
||||||
return table.unpack(rt)
|
if rt[2] then
|
||||||
|
return table.unpack(rt,3)
|
||||||
end
|
end
|
||||||
return false
|
error(rt[3])
|
||||||
|
end
|
||||||
|
error("timed out")
|
||||||
end
|
end
|
||||||
function rpc.proxy(hostname,filter) -- string string -- table -- Returns a component.proxy()-like table from the functions on *hostname* with names matching *filter*.
|
function rpc.proxy(hostname,filter) -- string string -- table -- Returns a component.proxy()-like table from the functions on *hostname* with names matching *filter*.
|
||||||
filter=(filter or "").."(.+)"
|
filter=(filter or "").."(.+)"
|
||||||
@ -69,7 +87,7 @@ function rpc.register(name,fn) -- string function -- -- Registers a function to
|
|||||||
if not rpcrunning then
|
if not rpcrunning then
|
||||||
os.spawn(function()
|
os.spawn(function()
|
||||||
while true do
|
while true do
|
||||||
rpcexec(event.pull("net_msg"))
|
pcall(rpcexec,event.pull("net_msg"))
|
||||||
end
|
end
|
||||||
end,"rpc daemon")
|
end,"rpc daemon")
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user