From ac23911d6dc4a2f338951f05a7778dfbe4a7abfb Mon Sep 17 00:00:00 2001 From: XeonSquared Date: Fri, 10 Nov 2023 17:45:28 +1000 Subject: [PATCH] add rica and ricad --- rica/package.cfg | 4 +++ rica/service/rica.lua | 63 +++++++++++++++++++++++++++++++++++++++++ ricad/package.cfg | 3 ++ ricad/service/ricad.lua | 52 ++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 rica/package.cfg create mode 100644 rica/service/rica.lua create mode 100644 ricad/package.cfg create mode 100644 ricad/service/ricad.lua diff --git a/rica/package.cfg b/rica/package.cfg new file mode 100644 index 0000000..6d2f34b --- /dev/null +++ b/rica/package.cfg @@ -0,0 +1,4 @@ +{["name"]="rica", + ["description"]="Remote Internet Card Access (rica) client", + ["authors"]="Izaya", + ["dependencies"]={"vcomponent"}} diff --git a/rica/service/rica.lua b/rica/service/rica.lua new file mode 100644 index 0000000..db766de --- /dev/null +++ b/rica/service/rica.lua @@ -0,0 +1,63 @@ +local vcomponent = require "vcomponent" +local serial = require "serialization" +local computer = require "computer" +local rpc = require "rpc" +local cfgpath = _OSVERSION:sub(1,7) == "PsychOS" and "/boot/cfg/rica.cfg" or "/etc/rica.cfg" + +local cfg = {addr = vcomponent.uuid(), hosts={}} + +local function rf() return false end +local function rt() return true end +local function genFn(host, id, name) + return function(...) + return rpc.call(host, "rica_"..name, id, ...) + end +end + +function reload() + local f = io.open(cfgpath, "rb") + if not f then return false end + cfg = serial.unserialize(f:read("*a")) + f:close() + return true +end +local function saveCfg() + local f = io.open(cfgpath, "wb") + if not f then return false end + f:write(serial.serialize(cfg)) + f:close() + return true +end + +function addhost(addr) + reload() + cfg.hosts[#cfg.hosts+1] = addr + saveCfg() +end + +function start() + reload() + vcomponent.register(cfg.addr, "internet", { + isTcpEnabled = rf, + isHttpEnabled = rt, + request = function (url, pd) + assert(#cfg.hosts > 0, "no proxies available") + local host = cfg.hosts[math.random(#cfg.hosts)] + local id, e = rpc.call(host, "rica_request", url, pd) + if not id then + return {read=rf,response=rf,close=rf,finishConnect=function() error(e) end} + end + local rt = {finishConnect = rt} + for k,v in ipairs{"read","response","close","finishConnect"} do + rt[v] = genFn(host,id,v) + end + return rt + end + }) +end + +function stop() + vcomponent.unregister(cfg.addr) +end + +return {start=start,stop=stop,reload=reload,addhost=addhost} diff --git a/ricad/package.cfg b/ricad/package.cfg new file mode 100644 index 0000000..74fdff1 --- /dev/null +++ b/ricad/package.cfg @@ -0,0 +1,3 @@ +{["name"]="ricad", + ["description"]="Remote Internet Card Access (rica) server", + ["authors"]="Izaya"} diff --git a/ricad/service/ricad.lua b/ricad/service/ricad.lua new file mode 100644 index 0000000..1fb26f5 --- /dev/null +++ b/ricad/service/ricad.lua @@ -0,0 +1,52 @@ +local component = require "component" +local computer = require "computer" +local rpc = require "rpc" +local handles = {} +local timeout, pid = 30 + +local function prune() + for k,v in pairs(handles) do + if computer.uptime() > v.ts + timeout then + v.rq.close() + handles[k] = nil + end + end +end + +function start() + -- function to keep the socket alive, will be run by long-running TCP clients + rpc.register("rica_keepalive", function(id) + assert(handles[id], "no such handle") + handles[id].ts = computer.uptime() + prune() + end) + + -- create a socket object and return the ID to the client + rpc.register("rica_request", function(url, pd) + prune() + local ic = component.proxy(component.list("internet")()) + local rq = ic.request(url, pd) + local rv = math.random(2^16) + handles[rv] = {rq=rq, ts=computer.uptime()} + return rv + end) + + -- generate thin wrappers around the samey functions + for k,v in ipairs({"read","write","close","response","finishConnect"}) do + rpc.register("rica_"..tostring(v), function(id, ...) + prune() + assert(handles[id], "no such handle") + -- any activity should update the timestamp + handles[id].ts = computer.uptime() + return handles[id].rq[v](...) + end) + end +end + +function stop() + for k,v in ipairs({"keepalive","request","connect","read","write","close","response"}) do + rpc.unregister(v) + end +end + +return {start=start,stop=stop}