mirror of
https://github.com/ShadowKatStudios/OC-Minitel.git
synced 2024-11-23 10:38:05 +11:00
added a KittenOS NEO version, or at least the bare service you need to route, send and receive packets.
This commit is contained in:
parent
b6bd5d5726
commit
b2332a97aa
258
KittenOS/apps/svc-minitel.lua
Normal file
258
KittenOS/apps/svc-minitel.lua
Normal file
@ -0,0 +1,258 @@
|
||||
-- KittenOS NEO Wrapper for OpenOS Minitel
|
||||
-- Take my word for it it works p. well
|
||||
|
||||
local rcomputer = neo.requireAccess("k.computer","pushing packets")
|
||||
neo.requireAccess("s.h.modem_message","pulling packets")
|
||||
local processes = {}
|
||||
local hooks = {}
|
||||
local computer = {["uptime"]=rcomputer.uptime,["address"]=rcomputer.address} -- wrap computer so the OpenOS code more or less works
|
||||
local event = {}
|
||||
function event.timer()
|
||||
end
|
||||
function event.listen(et,fn) -- add it to the hooks which is executed by the main event loop
|
||||
hooks["h."..et] = fn
|
||||
end
|
||||
function computer.pushSignal(...)
|
||||
for k,v in pairs(processes) do
|
||||
v(...)
|
||||
end
|
||||
end
|
||||
function print(...)
|
||||
for k,v in pairs({...}) do
|
||||
neo.emergency(v)
|
||||
end
|
||||
end
|
||||
|
||||
-- OpenOS Minitel stuff, I guess.
|
||||
|
||||
--[[
|
||||
packet format:
|
||||
packetID: random string to differentiate
|
||||
packetType:
|
||||
- 0: unreliable
|
||||
- 1: reliable, requires ack
|
||||
- 2: ack packet
|
||||
destination: end destination hostname
|
||||
sender: original sender of packet
|
||||
data: the actual packet data, duh.
|
||||
]]--
|
||||
|
||||
local listeners = {}
|
||||
local timers = {}
|
||||
|
||||
--[[
|
||||
local event = require "event"
|
||||
local component = require "component"
|
||||
local computer = require "computer"
|
||||
]]--
|
||||
local hostname = computer.address():sub(1,8)
|
||||
local listener = false
|
||||
local dbug = true
|
||||
local modems = {}
|
||||
local port = 4096
|
||||
local retry = 30
|
||||
local route = true
|
||||
|
||||
--[[
|
||||
LKR format:
|
||||
address {
|
||||
local hardware address
|
||||
remote hardware address
|
||||
time last received
|
||||
}
|
||||
]]--
|
||||
local sroutes = {}
|
||||
local rcache = setmetatable({},{__index=sroutes})
|
||||
local rctime = 30
|
||||
|
||||
--[[
|
||||
packet queue format:
|
||||
{
|
||||
packetID,
|
||||
packetType
|
||||
destination,
|
||||
data,
|
||||
timestamp,
|
||||
attempts
|
||||
}
|
||||
]]--
|
||||
local pqueue = {}
|
||||
|
||||
-- packet cache: [packet ID]=uptime
|
||||
local pcache = {}
|
||||
local pctime = 30
|
||||
|
||||
local function dprint(...)
|
||||
if dbug then
|
||||
print(...)
|
||||
end
|
||||
end
|
||||
|
||||
-- this stuff doesn't work on KittenOS, I'll need to implement a better hostname getting thing than the computer address
|
||||
--[[
|
||||
local f=io.open("/etc/hostname","rb")
|
||||
if f then
|
||||
hostname = f:read()
|
||||
f:close()
|
||||
end
|
||||
print("Hostname: "..hostname)
|
||||
if listener then return end
|
||||
for a,t in component.list("modem") do
|
||||
modems[#modems+1] = component.proxy(a)
|
||||
end
|
||||
]]--
|
||||
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
|
||||
|
||||
local function genPacketID()
|
||||
local npID = ""
|
||||
for i = 1, 16 do
|
||||
npID = npID .. string.char(math.random(32,126))
|
||||
end
|
||||
return npID
|
||||
end
|
||||
|
||||
local function sendPacket(packetID,packetType,dest,sender,vport,data)
|
||||
if rcache[dest] then
|
||||
dprint("Cached", rcache[dest][1],"send",rcache[dest][2],port,packetID,packetType,dest,sender,vport,data)
|
||||
if modems[rcache[dest][1]].type == "modem" then
|
||||
modems[rcache[dest][1]].send(rcache[dest][2],port,packetID,packetType,dest,sender,vport,data)
|
||||
elseif modems[rcache[dest][1]].type == "tunnel" then
|
||||
modems[rcache[dest][1]].send(packetID,packetType,dest,sender,vport,data)
|
||||
end
|
||||
else
|
||||
dprint("Not cached", port,packetID,packetType,dest,sender,vport,data)
|
||||
for k,v in pairs(modems) do
|
||||
if v.type == "modem" then
|
||||
v.broadcast(port,packetID,packetType,dest,sender,vport,data)
|
||||
elseif v.type == "tunnel" then
|
||||
v.send(packetID,packetType,dest,sender,vport,data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function pruneCache()
|
||||
for k,v in pairs(rcache) do
|
||||
dprint(k,v[3],computer.uptime())
|
||||
if v[3] < computer.uptime() then
|
||||
rcache[k] = nil
|
||||
dprint("pruned "..k.." from routing cache")
|
||||
end
|
||||
end
|
||||
for k,v in pairs(pcache) do
|
||||
if v < computer.uptime() then
|
||||
pcache[k] = nil
|
||||
dprint("pruned "..k.." from packet cache")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function checkPCache(packetID)
|
||||
dprint(packetID)
|
||||
for k,v in pairs(pcache) do
|
||||
dprint(k)
|
||||
if k == packetID then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function processPacket(_,localModem,from,pport,_,packetID,packetType,dest,sender,vport,data)
|
||||
pruneCache()
|
||||
if pport == port or pport == 0 then -- for linked cards
|
||||
dprint(port,vport,packetType,dest)
|
||||
if checkPCache(packetID) then return end
|
||||
if dest == hostname then
|
||||
if packetType == 1 then
|
||||
sendPacket(genPacketID(),2,sender,hostname,vport,packetID)
|
||||
end
|
||||
if packetType == 2 then
|
||||
dprint("Dropping "..data.." from queue")
|
||||
pqueue[data] = nil
|
||||
computer.pushSignal("net_ack",data)
|
||||
end
|
||||
if packetType ~= 2 then
|
||||
computer.pushSignal("net_msg",sender,vport,data)
|
||||
end
|
||||
elseif dest:sub(1,1) == "~" then -- broadcasts start with ~
|
||||
computer.pushSignal("net_broadcast",sender,vport,data)
|
||||
elseif route then -- repeat packets if route is enabled
|
||||
sendPacket(packetID,packetType,dest,sender,vport,data)
|
||||
end
|
||||
if not rcache[sender] then -- add the sender to the rcache
|
||||
dprint("rcache: "..sender..":", localModem,from,computer.uptime())
|
||||
rcache[sender] = {localModem,from,computer.uptime()+rctime}
|
||||
end
|
||||
if not pcache[packetID] then -- add the packet ID to the pcache
|
||||
pcache[packetID] = computer.uptime()+pctime
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
listeners["modem_message"]=processPacket
|
||||
event.listen("modem_message",processPacket)
|
||||
print("Started packet listening daemon: "..tostring(processPacket))
|
||||
|
||||
local function queuePacket(_,ptype,to,vport,data,npID)
|
||||
npID = npID or genPacketID()
|
||||
pqueue[npID] = {ptype,to,vport,data,0,0}
|
||||
dprint(npID,table.unpack(pqueue[npID]))
|
||||
end
|
||||
|
||||
listeners["net_send"]=queuePacket
|
||||
event.listen("net_send",queuePacket)
|
||||
print("Started packet queueing daemon: "..tostring(queuePacket))
|
||||
|
||||
local function packetPusher()
|
||||
for k,v in pairs(pqueue) do
|
||||
if v[5] < computer.uptime() then
|
||||
dprint(k,v[1],v[2],hostname,v[3],v[4])
|
||||
sendPacket(k,v[1],v[2],hostname,v[3],v[4])
|
||||
if v[1] ~= 1 or v[6] == 255 then
|
||||
pqueue[k] = nil
|
||||
else
|
||||
pqueue[k][5]=computer.uptime()+retry
|
||||
pqueue[k][6]=pqueue[k][6]+1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
timers[#timers+1]=event.timer(0,packetPusher,math.huge)
|
||||
print("Started packet pusher: "..tostring(timers[#timers]))
|
||||
|
||||
listeners["net_ack"]=dprint
|
||||
event.listen("net_ack",dprint)
|
||||
|
||||
-- More KOS NEO stuff
|
||||
|
||||
neo.requireAccess("r.svc.minitel","minitel daemon")(function(pkg,pid,sendSig)
|
||||
processes[pid] = sendSig
|
||||
return {["sendPacket"]=queuePacket}
|
||||
end)
|
||||
|
||||
while true do
|
||||
local ev = {coroutine.yield()}
|
||||
print(ev[1])
|
||||
packetPusher()
|
||||
pruneCache()
|
||||
if ev[1] == "k.procdie" then
|
||||
processes[ev[3]] = nil
|
||||
end
|
||||
if hooks[ev[1]] then
|
||||
pcall(hooks[ev[1]],table.unpack(ev))
|
||||
end
|
||||
for k,v in pairs(ev) do
|
||||
neo.emergency(v)
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user