3 changed files with 0 additions and 422 deletions
@ -1,63 +0,0 @@ |
|||
local imt = {} |
|||
|
|||
imt.ttypes = {} |
|||
imt.ttypes.string=1 |
|||
imt.ttypes.number=2 |
|||
|
|||
imt.ftypes = {tostring,tonumber} |
|||
|
|||
function imt.to16bn(n) |
|||
return string.char(math.floor(n/256))..string.char(math.floor(n%256)) |
|||
end |
|||
function imt.from16bn(s) |
|||
return (string.byte(s,1,1)*256)+string.byte(s,2,2) |
|||
end |
|||
|
|||
function imt.encodePacket(...) |
|||
local tArgs = {...} |
|||
local packet = string.char(#tArgs%256) |
|||
for _,segment in ipairs(tArgs) do |
|||
local segtype = type(segment) |
|||
segment = tostring(segment) |
|||
packet = packet .. imt.to16bn(segment:len()) .. string.char(imt.ttypes[segtype]) .. tostring(segment) |
|||
end |
|||
packet = imt.to16bn(packet:len()) .. packet |
|||
return packet |
|||
end |
|||
|
|||
function imt.decodePacket(s) |
|||
local function getfirst(n) |
|||
local ns = s:sub(1,n) |
|||
s=s:sub(n+1) |
|||
return ns |
|||
end |
|||
if s:len() < 2 then return false end |
|||
local plen = imt.from16bn(getfirst(2)) |
|||
local segments = {} |
|||
if s:len() < plen then return false end |
|||
local nsegments = string.byte(getfirst(1)) |
|||
--print(tostring(plen).." bytes, "..tostring(nsegments).." segments") |
|||
for i = 1, nsegments do |
|||
local seglen = imt.from16bn(getfirst(2)) |
|||
local segtype = imt.ftypes[string.byte(getfirst(1))] |
|||
local segment = segtype(getfirst(seglen)) |
|||
--print(seglen,segtype,segment,type(segment)) |
|||
segments[#segments+1] = segment |
|||
end |
|||
return table.unpack(segments) |
|||
end |
|||
function imt.getRemainder(s) |
|||
local function getfirst(n) |
|||
local ns = s:sub(1,n) |
|||
s=s:sub(n+1) |
|||
return ns |
|||
end |
|||
local plen = imt.from16bn(getfirst(2)) |
|||
if s:len() > plen then |
|||
getfirst(plen) |
|||
return s |
|||
end |
|||
return nil |
|||
end |
|||
|
|||
return imt |
@ -1,197 +0,0 @@ |
|||
local proxylist = {} |
|||
local proxyobjs = {} |
|||
local typelist = {} |
|||
local doclist = {} |
|||
|
|||
local oproxy = component.proxy |
|||
function component.proxy(address) |
|||
checkArg(1,address,"string") |
|||
if proxyobjs[address] ~= nil then |
|||
return proxyobjs[address] |
|||
end |
|||
return oproxy(address) |
|||
end |
|||
|
|||
local olist = component.list |
|||
function component.list(filter, exact) |
|||
checkArg(1,filter,"string","nil") |
|||
local result = {} |
|||
local data = {} |
|||
for k,v in olist(filter, exact) do |
|||
data[#data + 1] = k |
|||
data[#data + 1] = v |
|||
result[k] = v |
|||
end |
|||
for k,v in pairs(typelist) do |
|||
if filter == nil or (exact and v == filter) or (not exact and v:find(filter, nil, true)) then |
|||
data[#data + 1] = k |
|||
data[#data + 1] = v |
|||
result[k] = v |
|||
end |
|||
end |
|||
local place = 1 |
|||
return setmetatable(result, |
|||
{__call=function() |
|||
local addr,type = data[place], data[place + 1] |
|||
place = place + 2 |
|||
return addr, type |
|||
end} |
|||
) |
|||
end |
|||
|
|||
local otype = component.type |
|||
function component.type(address) |
|||
checkArg(1,address,"string") |
|||
if typelist[address] ~= nil then |
|||
return typelist[address] |
|||
end |
|||
return otype(address) |
|||
end |
|||
|
|||
local odoc = component.doc |
|||
function component.doc(address, method) |
|||
checkArg(1,address,"string") |
|||
checkArg(2,method,"string") |
|||
if proxylist[address] ~= nil then |
|||
if proxylist[address][method] == nil then |
|||
error("no such method",2) |
|||
end |
|||
if doclist[address] ~= nil then |
|||
return doclist[address][method] |
|||
end |
|||
return nil |
|||
end |
|||
return odoc(address, method) |
|||
end |
|||
|
|||
local oslot = component.slot |
|||
function component.slot(address) |
|||
checkArg(1,address,"string") |
|||
if proxylist[address] ~= nil then |
|||
return -1 -- vcomponents do not exist in a slot |
|||
end |
|||
return oslot(address) |
|||
end |
|||
|
|||
local omethods = component.methods |
|||
function component.methods(address) |
|||
checkArg(1,address,"string") |
|||
if proxylist[address] ~= nil then |
|||
local methods = {} |
|||
for k,v in pairs(proxylist[address]) do |
|||
if type(v) == "function" then |
|||
methods[k] = true -- All vcomponent methods are direct |
|||
end |
|||
end |
|||
return methods |
|||
end |
|||
return omethods(address) |
|||
end |
|||
|
|||
local oinvoke = component.invoke |
|||
function component.invoke(address, method, ...) |
|||
checkArg(1,address,"string") |
|||
checkArg(2,method,"string") |
|||
if proxylist[address] ~= nil then |
|||
if proxylist[address][method] == nil then |
|||
error("no such method",2) |
|||
end |
|||
return proxylist[address][method](...) |
|||
end |
|||
return oinvoke(address, method, ...) |
|||
end |
|||
|
|||
local ofields = component.fields |
|||
function component.fields(address) |
|||
checkArg(1,address,"string") |
|||
if proxylist[address] ~= nil then |
|||
return {} -- What even is this? |
|||
end |
|||
return ofields(address) |
|||
end |
|||
|
|||
local componentCallback = |
|||
{ |
|||
__call = function(self, ...) return proxylist[self.address][self.name](...) end, |
|||
__tostring = function(self) return (doclist[self.address] ~= nil and doclist[self.address][self.name] ~= nil) and doclist[self.address][self.name] or "function" end |
|||
} |
|||
|
|||
local vcomponent = {} |
|||
|
|||
function vcomponent.register(address, ctype, proxy, doc) |
|||
checkArg(1,address,"string") |
|||
checkArg(2,ctype,"string") |
|||
checkArg(3,proxy,"table") |
|||
if proxylist[address] ~= nil then |
|||
return nil, "component already at address" |
|||
elseif component.type(address) ~= nil then |
|||
return nil, "cannot register over real component" |
|||
end |
|||
proxy.address = address |
|||
proxy.type = ctype |
|||
local proxyobj = {} |
|||
for k,v in pairs(proxy) do |
|||
if type(v) == "function" then |
|||
proxyobj[k] = setmetatable({name=k,address=address},componentCallback) |
|||
else |
|||
proxyobj[k] = v |
|||
end |
|||
end |
|||
proxylist[address] = proxy |
|||
proxyobjs[address] = proxyobj |
|||
typelist[address] = ctype |
|||
doclist[address] = doc |
|||
computer.pushSignal("component_added",address,ctype) |
|||
return true |
|||
end |
|||
|
|||
function vcomponent.unregister(address) |
|||
checkArg(1,address,"string") |
|||
if proxylist[address] == nil then |
|||
if component.type(address) ~= nil then |
|||
return nil, "cannot unregister real component" |
|||
else |
|||
return nil, "no component at address" |
|||
end |
|||
end |
|||
local thetype = typelist[address] |
|||
proxylist[address] = nil |
|||
proxyobjs[address] = nil |
|||
typelist[address] = nil |
|||
doclist[address] = nil |
|||
computer.pushSignal("component_removed",address,thetype) |
|||
return true |
|||
end |
|||
|
|||
function vcomponent.list() |
|||
local list = {} |
|||
for k,v in pairs(proxylist) do |
|||
list[#list + 1] = {k,typelist[k],v} |
|||
end |
|||
return list |
|||
end |
|||
|
|||
function vcomponent.resolve(address, componentType) |
|||
checkArg(1, address, "string") |
|||
checkArg(2, componentType, "string", "nil") |
|||
for k,v in pairs(typelist) do |
|||
if componentType == nil or v == componentType then |
|||
if k:sub(1, #address) == address then |
|||
return k |
|||
end |
|||
end |
|||
end |
|||
return nil, "no such component" |
|||
end |
|||
|
|||
local r = math.random |
|||
function vcomponent.uuid() |
|||
return string.format("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
|||
r(0,255),r(0,255),r(0,255),r(0,255), |
|||
r(0,255),r(0,255), |
|||
r(64,79),r(0,255), |
|||
r(128,191),r(0,255), |
|||
r(0,255),r(0,255),r(0,255),r(0,255),r(0,255),r(0,255)) |
|||
end |
|||
|
|||
return vcomponent |
@ -1,162 +0,0 @@ |
|||
local vcomponent = require "vcomponent" |
|||
local serial = require "serialization" |
|||
local component = require "component" |
|||
local computer = require "computer" |
|||
local event = require "event" |
|||
local imt = require "interminitel" |
|||
|
|||
local cfg = {} |
|||
cfg.peers = {} |
|||
cfg.rtimer = 5 |
|||
cfg.katimer = 30 |
|||
local listeners = {} |
|||
local proxies = {} |
|||
|
|||
local function loadcfg() |
|||
local f = io.open("/boot/cfg/vtunnel.cfg","rb") |
|||
if not f then return false end |
|||
for k,v in pairs(serial.unserialize(f:read("*a")) or {}) do |
|||
cfg[k] = v |
|||
end |
|||
f:close() |
|||
end |
|||
local function savecfg() |
|||
local f = io.open("/boot/cfg/vtunnel.cfg","wb") |
|||
if not f then |
|||
print("Warning: unable to save configuration.") |
|||
return false |
|||
end |
|||
f:write(serial.serialize(cfg)) |
|||
f:close() |
|||
end |
|||
|
|||
local function createTunnel(host,port,addr,raddr) |
|||
local proxy = {address=addr,buffer=""} |
|||
function proxy.connect() |
|||
if proxy.socket then |
|||
proxy.socket.close() |
|||
end |
|||
proxy.socket = component.invoke(component.list("internet")(),"connect",host,port) |
|||
local st = computer.uptime() |
|||
repeat |
|||
coroutine.yield() |
|||
until proxy.socket.finishConnect() or computer.uptime() > st+5 |
|||
end |
|||
function proxy.send(...) |
|||
rt = 0 |
|||
while not proxy.socket.write(imt.encodePacket(...)) and rt < 10 do |
|||
proxy.connect() |
|||
rt = rt + 1 |
|||
end |
|||
proxy.last = computer.uptime() |
|||
end |
|||
function proxy.read() |
|||
local rb, r |
|||
local rt = 0 |
|||
while true do |
|||
rb,r = proxy.socket.read(4096) |
|||
if rb or rt > 10 then break end |
|||
if type(rb) == "nil" then |
|||
proxy.connect() |
|||
end |
|||
rt = rt + 1 |
|||
end |
|||
proxy.buffer = proxy.buffer .. rb |
|||
while imt.decodePacket(proxy.buffer) do |
|||
computer.pushSignal("modem_message",addr,raddr,0,0,imt.decodePacket(proxy.buffer)) |
|||
proxy.buffer = imt.getRemainder(proxy.buffer) or "" |
|||
end |
|||
if computer.uptime() > proxy.last + cfg.katimer then |
|||
proxy.socket.write("\0\1\0") |
|||
proxy.last = computer.uptime() |
|||
end |
|||
end |
|||
function proxy.getWakeMessage() |
|||
return false |
|||
end |
|||
proxy.setWakeMessage = proxy.getWakeMessage |
|||
function proxy.maxPacketSize() |
|||
return 8192 |
|||
end |
|||
function proxy.getChannel() |
|||
return host..":"..tostring(port) |
|||
end |
|||
proxy.connect() |
|||
proxy.last = computer.uptime() |
|||
return proxy |
|||
end |
|||
|
|||
vt = {} |
|||
function start() |
|||
loadcfg() |
|||
for k,v in pairs(cfg.peers) do |
|||
print(string.format("Connecting to %s:%d",v.host,v.port)) |
|||
v.addr = v.addr or vcomponent.uuid() |
|||
v.raddr = v.raddr or vcomponent.uuid() |
|||
local px = createTunnel(v.host, v.port, v.addr, v.raddr) |
|||
vcomponent.register(v.addr, "tunnel", px) |
|||
proxies[v.addr] = px |
|||
end |
|||
for k,v in pairs(os.tasks()) do |
|||
if os.taskInfo(v).name:match("minitel") then |
|||
os.kill(v) |
|||
end |
|||
end |
|||
end |
|||
function vt.stop() |
|||
for k,v in pairs(proxies) do |
|||
vcomponent.unregister(k) |
|||
end |
|||
end |
|||
|
|||
function vt.listpeers() |
|||
for k,v in pairs(cfg.peers) do |
|||
print(string.format("#%d (%s:%d)\n Local address: %s\n Remote address: %s",k,v.host,v.port,v.addr,v.raddr)) |
|||
end |
|||
end |
|||
function vt.addpeer(host,port) |
|||
port = tonumber(port) or 4096 |
|||
local t = {} |
|||
t.host = host |
|||
t.port = port |
|||
t.addr = vcomponent.uuid() |
|||
t.raddr = vcomponent.uuid() |
|||
cfg.peers[#cfg.peers+1] = t |
|||
print(string.format("Added peer #%d (%s:%d) to the configuration.\nRestart to apply changes.",#cfg.peers,host,port)) |
|||
savecfg() |
|||
end |
|||
function vt.delpeer(n) |
|||
n=tonumber(n) |
|||
if not n then |
|||
print("delpeer requires a number, representing the peer number, as an argument.") |
|||
return false |
|||
end |
|||
local dp = table.remove(cfg.peers, n) |
|||
savecfg() |
|||
print(string.format("Removed peer %s:%d",dp.host, dp.port)) |
|||
end |
|||
|
|||
function vt.settimer(time) |
|||
time = tonumber(time) |
|||
if not time then |
|||
print("Timer must be a number.") |
|||
return false |
|||
end |
|||
cfg.rtime = time |
|||
savecfg() |
|||
end |
|||
|
|||
vt.start = start |
|||
_G.libs.vtunnel = vt |
|||
|
|||
start() |
|||
local last = computer.uptime() |
|||
while true do |
|||
local tE = {coroutine.yield()} |
|||
if computer.uptime() > last + cfg.rtimer then |
|||
for k,v in pairs(proxies) do |
|||
v.read() |
|||
end |
|||
last = computer.uptime() |
|||
end |
|||
end |
Loading…
issues.context.reference_issue