Compare commits

..

No commits in common. "e20c9546eafa8a0da2b5b3451f223301b671910d" and "0712210768921f06505711a2edc6da38ad61fc7a" have entirely different histories.

6 changed files with 157 additions and 180 deletions

View File

@ -1,47 +1,38 @@
local computer = require "computer"
local minitel = require "minitel"
local event = require "event"
local rpc = require "rpc"
local netutil = {}
function netutil.importfs(host,rpath,lpath) -- import filesystem *rpath* from *host* and attach it to *lpath*
function netutil.importfs(host,rpath,lpath)
local px = rpc.proxy(host,rpath.."_")
function px.getLabel()
return host..":"..rpath
end
return fs.mount(lpath,px)
fs.mount(lpath,px)
end
function netutil.exportfs(path) -- export the directory *path* over RPC
function netutil.exportfs(path)
local path = "/"..table.concat(fs.segments(path),"/")
local px = ufs.create(path)
for k,v in pairs(px) do
rpcs.register(path.."_"..k,v)
print(path.."_"..k)
end
return true
end
function netutil.ping(addr,times,timeout, silent) -- Request acknowledgment from *addr*, waiting *timeout* seconds each try, and try *times* times. If *silent* is true, don't print status. Returns true if there was at least one successful ping, the number of successes, the number of failures, and the average round trip time.
function netutil.ping(addr,times,timeout)
local times, timeout = times or 5, timeout or 30
local success, fail, time, avg = 0, 0, 0, 0
for i = 1, times do
local ipt = computer.uptime()
local pid = minitel.genPacketID()
computer.pushSignal("net_send",1,addr,0,"ping",pid)
local t,a = event.pull(timeout,"net_ack")
if t == "net_ack" and a == pid then
if not silent then print("Ping reply: "..tostring(computer.uptime()-ipt).." seconds.") end
success = success + 1
time = time + computer.uptime()-ipt
avg = time / success
print("Ping reply: "..tostring(computer.uptime()-ipt).." seconds.")
else
if not silent then print("Timed out.") end
fail = fail + 1
print("Timed out.")
end
end
if not silent then print(string.format("%d packets transmitted, %d received, %0.0f%% packet loss, %0.1fs",times,success,fail/times*100,time)) end
return success > 0, success, fail, avg
end
return netutil

View File

@ -1,76 +0,0 @@
local serial = require "serialization"
local rc = {}
local service = {}
local cfg = {}
cfg.enabled = {}
local function loadConfig()
local f = io.open("/boot/cfg/rc.cfg","rb")
if not f then return false end
cfg = serial.unserialize(f:read("*a")) or {}
f:close()
cfg.enabled = cfg.enabled or {}
return true
end
local function saveConfig()
local f = io.open("/boot/cfg/rc.cfg","wb")
if not f then return false end
f:write(serial.serialize(cfg))
f:close()
return true
end
function rc.load(name,force)
if force then
rc.stop(name)
service[name] = nil
end
if service[name] then return true end
service[name] = setmetatable({},{__index=_G})
local f = io.open("/boot/service/"..name..".lua","rb")
local res = load(f:read("*a"),name,"t",service[name])()
f:close()
return res
end
function rc.stop(name,...)
if not service[name] then return false, "service not found" end
service[name].stop(...)
end
function rc.start(name,...)
rc.load(name)
if not service[name] then return false, "service not found" end
return service[name].start(...)
end
function rc.restart(name)
rc.stop(name)
rc.start(name)
end
function rc.enable(name)
for k,v in pairs(cfg.enabled) do
if v == name then return false end
end
saveConfig()
end
function rc.disable(name)
local disabled = false
for k,v in pairs(cfg.enabled) do
if v == name then table.remove(cfg.enabled,k) disabled = true break end
end
saveConfig()
return disabled
end
loadConfig()
for k,v in pairs(cfg.enabled) do
rc.start(v)
end
_G.service = service
return rc

View File

@ -22,16 +22,20 @@ os.spawn(function()
os.setenv("HOSTNAME",hostname)
syslog(string.format("Hostname set to %s",hostname))
local pids = {}
local rc = require "rc"
for k,v in pairs(rc.cfg.enabled) do
pids[v] = -1
dprint(v)
local function loadlist()
local f = io.open("/boot/cfg/init.txt","rb")
if not f then return false end
for line in f:read("*a"):gmatch("[^\r\n]+") do
pids[line] = -1
end
f:close()
end
loadlist()
while true do
for k,v in pairs(pids) do
if not os.taskInfo(v) then
syslog("Starting service "..k)
pids[k] = rc.start(k)
pids[k] = os.spawnfile("/boot/service/"..k)
end
end
coroutine.yield()

View File

@ -1,12 +1,12 @@
io = {}
function io.open(path,mode) -- Open file *path* in *mode*. Returns a buffer object.
function io.open(path,mode)
local f,e = fs.open(path, mode)
if not f then return false, e end
return buffer.new(mode,f)
end
function io.input(fd) -- Sets the default input stream to *fd* if provided, either as a buffer as a path. Returns the default input stream.
function io.input(fd)
if type(fd) == "string" then
fd=io.open(fd,"rb")
end
@ -15,7 +15,7 @@ function io.input(fd) -- Sets the default input stream to *fd* if provided, eith
end
return os.getenv("STDIN")
end
function io.output(fd) -- Sets the default output stream to *fd* if provided, either as a buffer as a path. Returns the default output stream.
function io.output(fd)
if type(fd) == "string" then
fd=io.open(fd,"wb")
end
@ -25,14 +25,14 @@ function io.output(fd) -- Sets the default output stream to *fd* if provided, ei
return os.getenv("STDOUT")
end
function io.read(...) -- Reads from the default input stream.
return io.input():read(...)
function io.read(...)
return io.input():read()
end
function io.write(...) -- Writes its arguments to the default output stream.
function io.write(...)
io.output():write(...)
end
function print(...) -- Writes each argument to the default output stream, separated by newlines.
function print(...)
for k,v in ipairs({...}) do
io.write(tostring(v).."\n")
end

View File

@ -1,5 +1,4 @@
local gpus,screens,ttyn,pids = {}, {}, 0, {}
local basepid = nil
local shell = require "shell"
local function scan()
local w,di = pcall(computer.getDeviceInfo)
@ -54,11 +53,9 @@ local function allocate()
end
end
function start()
scan()
allocate()
dprint("screens ready")
basepid = os.spawn(function()
while true do
coroutine.yield()
for k,v in pairs(pids) do
@ -69,10 +66,3 @@ while true do
end
end
end
end,"getty")
return basepid
end
function stop()
os.kill(basepid)
basepid = nil
end

View File

@ -10,27 +10,36 @@ sender: original sender of packet
data: the actual packet data, duh.
]]--
local listeners = {}
local timers = {}
local listeners,timers,processes,modems = {},{},{},{}
local hostname = os.getenv("HOSTNAME")
local cfg = {}
local event = require "event"
local component = require "component"
local computer = require "computer"
local serial = require "serialization"
local hostname = computer.address():sub(1,8)
local modems = {}
local pid = nil
cfg.debug = false
cfg.port = 4096
cfg.retry = 10
cfg.retrycount = 3
cfg.retrycount = 64
cfg.route = true
local event, component, computer, serial = event, component, computer, serial
local hnpath, cfgpath = "", ""
OPENOS, PSYCHOS, KITTENOS = false, false, false
if _OSVERSION:sub(1,6) == "OpenOS" then
OPENOS = true
hnpath = "/etc/hostname"
cfgpath = "/etc/minitel.cfg"
elseif _OSVERSION:sub(1,7) == "PsychOS" then
PSYCHOS = true
hnpath = "/boot/cfg/hostname"
cfgpath = "/boot/cfg/minitel.cfg"
elseif _OSVERSION:sub(1,8) == "KittenOS" then
KITTENOS = true
end
-- packet cache: [packet ID]=uptime
local pcache = {}
cfg.pctime = 30
--[[
LKR format:
address {
@ -39,6 +48,7 @@ address {
time last received
}
]]--
cfg.sroutes = {}
local rcache = setmetatable({},{__index=cfg.sroutes})
cfg.rctime = 15
@ -56,27 +66,26 @@ packet queue format:
]]--
local pqueue = {}
-- packet cache: [packet ID]=uptime
local pcache = {}
cfg.pctime = 30
local function dprint(...)
if cfg.debug then
print(...)
end
end
local function saveconfig()
local f = io.open("/boot/cfg/minitel.cfg","wb")
if OPENOS or PSYCHOS then
local f = io.open(cfgpath,"wb")
if f then
f:write(serial.serialize(cfg))
f:close()
end
end
end
local function loadconfig()
local f = io.open("/boot/cfg/minitel.cfg","rb")
hostname = os.getenv("HOSTNAME") or computer.address():sub(1,8)
if OPENOS or PSYCHOS then
local f,g=io.open(hnpath,"rb")
if f then
local newcfg = serial.unserialize(f:read("*a"))
hostname = f:read("*a"):match("(.-)\n")
f:close()
end
local f = io.open(cfgpath,"rb")
if f then
local newcfg = serial.unserialize(f:read("*a")) or {}
f:close()
for k,v in pairs(newcfg) do
cfg[k] = v
@ -84,26 +93,69 @@ local function loadconfig()
else
saveconfig()
end
elseif KITTENOS then
local globals = neo.requestAccess("x.neo.pub.globals") -- KittenOS standard hostname stuff
if globals then
hostname = globals.getSetting("hostname") or hostname
globals.setSetting("hostname",hostname)
end
end
end
-- specific OS support here
if PSYCHOS then -- PsychOS specific code
serial = require "serialization"
elseif OPENOS then -- OpenOS specific code
event = require "event"
component = require "component"
computer = require "computer"
serial = require "serialization"
listener = false
elseif KITTENOS then
neo.requireAccess("s.h.modem_message","pulling packets")
computer = {["uptime"]=os.uptime,["address"]=os.address} -- wrap computer so the OpenOS code more or less works
function computer.pushSignal(...)
for k,v in pairs(processes) do
v(...)
end
end
end
local function dprint(...)
if cfg.debug then
print(...)
end
end
function start()
loadconfig()
hostname = os.getenv("HOSTNAME") or computer.address():sub(1,8)
print("Hostname: "..hostname)
if pid then return false end
modems={}
if listener then return end
if OPENOS or PSYCHOS then
for a,t in component.list("modem") do
modems[#modems+1] = component.proxy(a)
end
for k,v in ipairs(modems) do
v.open(cfg.port)
print("Opened port "..cfg.port.." on "..v.address)
print("Opened port "..cfg.port.." on "..v.address:sub(1,8))
end
for a,t in component.list("tunnel") do
modems[#modems+1] = component.proxy(a)
end
elseif KITTENOS then
for p in neo.requireAccess("c.modem","networking").list() do -- fun stuff for KittenOS
dprint(p.address)
modems[p.address] = p
end
for k,v in pairs(modems) do
v.open(port)
print("Opened port "..port.." on "..v.address)
end
for p in neo.requireAccess("c.tunnel","networking").list() do
dprint(p.address)
modems[p.address] = p
end
end
local function genPacketID()
local npID = ""
@ -124,11 +176,10 @@ function start()
else
dprint("Not cached", cfg.port,packetID,packetType,dest,sender,vPort,data)
for k,v in pairs(modems) do
-- do not send message back to the wired or linked modem it came from
-- the check for tunnels is for short circuiting `v.isWireless()`, which does not exist for tunnels
if v.address ~= repeatingFrom or (v.type ~= "tunnel" and v.isWireless()) then
if v.type == "modem" then
v.broadcast(cfg.port,packetID,packetType,dest,sender,vPort,data)
elseif v.type == "tunnel" then
v.send(packetID,packetType,dest,sender,vPort,data)
end
end
@ -204,6 +255,7 @@ function start()
dprint(npID,table.unpack(pqueue[npID]))
end
local function packetPusher()
for k,v in pairs(pqueue) do
if v[5] < computer.uptime() then
@ -221,29 +273,43 @@ function start()
listeners["modem_message"]=processPacket
listeners["net_send"]=queuePacket
listeners["net_ack"]=dprint
if OPENOS then
event.listen("modem_message",processPacket)
print("Started packet listening daemon: "..tostring(processPacket))
event.listen("net_send",queuePacket)
print("Started packet queueing daemon: "..tostring(queuePacket))
timers[#timers+1]=event.timer(0,packetPusher,math.huge)
print("Started packet pusher: "..tostring(timers[#timers]))
elseif KITTENOS then
neo.requireAccess("r.svc.minitel","minitel daemon")(function(pkg,pid,sendSig)
processes[pid] = sendSig
return {["sendPacket"]=queuePacket}
end)
end
pid=os.spawn(function()
if KITTENOS or PSYCHOS then
while true do
local ev = {coroutine.yield()}
packetPusher()
pruneCache()
if ev[1] == "k.procdie" then
processes[ev[3]] = nil
end
if listeners[ev[1]] then
pcall(listeners[ev[1]],table.unpack(ev))
end
end
end,"minitel")
print("Started Minitel daemon: "..tostring(pid))
return pid
end
end
function stop()
if pid then
os.kill(pid)
pid = nil
return true
else
return false
for k,v in pairs(listeners) do
event.ignore(k,v)
print("Stopped listener: "..tostring(v))
end
for k,v in pairs(timers) do
event.cancel(v)
print("Stopped timer: "..tostring(v))
end
end
@ -265,9 +331,11 @@ end
function set_route(to,laddr,raddr)
cfg.sroutes[to] = {laddr,raddr,0}
saveconfig()
end
function del_route(to)
cfg.sroutes[to] = nil
saveconfig()
end
if not OPENOS then
start()
end