Operating system for OpenComputers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
2.1KB

  1. local serial = require "serialization"
  2. local minitel = require "minitel"
  3. local event = require "event"
  4. local rpc = {}
  5. _G.rpcf = {}
  6. rpc.port = 111
  7. local function rpcexec(_, from, port, data)
  8. if port == rpc.port then
  9. local rpcrq = serial.unserialize(data)
  10. local rpcn, rpcid = table.remove(rpcrq,1), table.remove(rpcrq,1)
  11. if rpcf[rpcn] then
  12. local rt = {pcall(rpcf[rpcn],table.unpack(rpcrq))}
  13. if rt[1] == true then
  14. table.remove(rt,1)
  15. end
  16. minitel.send(from,port,serial.serialize({rpcid,table.unpack(rt)}))
  17. else
  18. end
  19. end
  20. end
  21. function rpcf.list()
  22. local rt = {}
  23. for k,v in pairs(rpcf) do
  24. rt[#rt+1] = k
  25. end
  26. return rt
  27. end
  28. function rpc.call(hostname,fn,...) -- string string -- boolean -- Calls exported function *fn* on host *hostname*, with parameters *...*, returning whatever the function returns, or false.
  29. if hostname == "localhost" then
  30. return rpcf[fn](...)
  31. end
  32. local rv = minitel.genPacketID()
  33. minitel.rsend(hostname,rpc.port,serial.serialize({fn,rv,...}),true)
  34. local st = computer.uptime()
  35. local rt = {}
  36. repeat
  37. local _, from, port, data = event.pull(30, "net_msg", hostname, rpc.port)
  38. rt = serial.unserialize(tostring(data)) or {}
  39. until (type(rt) == "table" and rt[1] == rv) or computer.uptime() > st + 30
  40. if table.remove(rt,1) == rv then
  41. return table.unpack(rt)
  42. end
  43. return false
  44. end
  45. function rpc.proxy(hostname,filter) -- string string -- table -- Returns a component.proxy()-like table from the functions on *hostname* with names matching *filter*.
  46. filter=(filter or "").."(.+)"
  47. local fnames = rpc.call(hostname,"list")
  48. if not fnames then return false end
  49. local rt = {}
  50. for k,v in pairs(fnames) do
  51. fv = v:match(filter)
  52. if fv then
  53. rt[fv] = function(...)
  54. return rpc.call(hostname,v,...)
  55. end
  56. end
  57. end
  58. return rt
  59. end
  60. function rpc.register(name,fn) -- string function -- -- Registers a function to be exported by the RPC library.
  61. local rpcrunning = false
  62. for k,v in pairs(os.tasks()) do
  63. if os.taskInfo(v).name == "rpc daemon" then
  64. rpcrunning = true
  65. end
  66. end
  67. if not rpcrunning then
  68. os.spawn(function()
  69. while true do
  70. rpcexec(event.pull("net_msg"))
  71. end
  72. end,"rpc daemon")
  73. end
  74. rpcf[name] = fn
  75. end
  76. return rpc