157 lines
4.1 KiB
Lua
157 lines
4.1 KiB
Lua
|
net = {}
|
||
|
net.id = computer.address():sub(1,8)
|
||
|
net.delay = 2
|
||
|
net.np = 4957
|
||
|
net.cache = true
|
||
|
net.cache_time = 16
|
||
|
net.log = false
|
||
|
if cdlib and relib then
|
||
|
spawn("ncd",function() print(pcall(function()
|
||
|
|
||
|
local olog = log
|
||
|
local function log(...)
|
||
|
if net.log then
|
||
|
for k,v in ipairs({...}) do
|
||
|
olog("[ncd] " .. tostring(v))
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local mtab = {} -- modem table
|
||
|
local lkr = {} -- LKR cache, contains copper_name = {modem="modem address last received from",addr="address last received from"}
|
||
|
local rpackets = {} -- packets that have already been seen
|
||
|
local pqueue = {} -- queue for packets to be sent. same format as relib.encode accepts. contains:
|
||
|
-- packet_id = {
|
||
|
-- pid = "3 char string of random data, same as packet_id",
|
||
|
-- addr = "address to send to",
|
||
|
-- port = #port number, 0-65535,
|
||
|
-- msg = "the packet data",
|
||
|
-- wf = "packet ID to wait till ack'd"
|
||
|
-- at = #attempts,
|
||
|
-- lst = #time of last attempt (USE UPTIME, NOT os.time() BECAUSE WINDOWS IS DUMB)
|
||
|
-- }
|
||
|
|
||
|
for modem in component.list("modem") do
|
||
|
mtab[#mtab+1] = modem
|
||
|
log("added "..modem)
|
||
|
component.invoke(modem,"open",net.np)
|
||
|
end
|
||
|
|
||
|
local function send(addr,msg,hops,src)
|
||
|
log("sending packet "..msg.." to "..addr)
|
||
|
local src=src or net.id
|
||
|
local hops=hops or 0
|
||
|
if lkr[addr] and net.cache then
|
||
|
component.invoke(lkr[addr].modem,"send",lkr[addr].addr,net.np,"copper",cdlib.encode(hops,src,addr,msg))
|
||
|
else
|
||
|
for _,modem in ipairs(mtab) do
|
||
|
-- log(modem,"broadcast",net.np,hops,net.id,addr,msg,cdlib.encode(hops,net.id,addr,msg))
|
||
|
component.invoke(modem,"broadcast",net.np,"copper",cdlib.encode(hops,net.id,addr,msg))
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
local function enqueue(addr,port,msg,waitfor)
|
||
|
local qp = {}
|
||
|
qp.msg = msg
|
||
|
qp.addr = addr
|
||
|
qp.port = port
|
||
|
qp.wf = waitfor
|
||
|
qp.pid = os.gensalt(3)
|
||
|
qp.at = 0
|
||
|
qp.pt = 1
|
||
|
qp.lst = 0
|
||
|
pqueue[qp.pid] = qp
|
||
|
for k,v in pairs(qp) do log(k.." = "..tostring(v)) end
|
||
|
return qp.pid
|
||
|
end
|
||
|
net.send = enqueue
|
||
|
|
||
|
local function ppacket(hops,src,dst,data)
|
||
|
if not rpackets[src..dst..data] then
|
||
|
if dst == net.id then
|
||
|
log("packet addressed here")
|
||
|
event.push("net_rmsg",src,data)
|
||
|
local pd = relib.decode(data)
|
||
|
log(pd)
|
||
|
if pd then
|
||
|
log("valid relib packet")
|
||
|
for k,v in pairs(pd) do log(k.." = "..v) end
|
||
|
if pd.port and pd.pid and pd.at and pd.pt then
|
||
|
if pd.pt == 0 then
|
||
|
log("unreliable packet")
|
||
|
event.push("net_msg",src,pd.port,pd.msg)
|
||
|
elseif pd.pt == 1 then
|
||
|
log("reliable packet, sending ack")
|
||
|
event.push("net_msg",src,pd.port,pd.msg)
|
||
|
pd.pt = 2
|
||
|
pd.addr = src
|
||
|
pd.lst = 0
|
||
|
pd.msg = ""
|
||
|
pd.unreliable=true
|
||
|
pqueue[pd.pid] = pd
|
||
|
for k,v in pairs(pqueue[pd.pid]) do log(k.." = "..tostring(v)) end
|
||
|
elseif pd.pt == 2 then
|
||
|
log("ack packet: "..pd.pid)
|
||
|
pqueue[pd.pid] = nil
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
elseif src ~= net.id then
|
||
|
if hops < 255 then
|
||
|
send(dst,data,hops+1,src)
|
||
|
end
|
||
|
end
|
||
|
rpackets[src..dst..data] = computer.uptime()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
while true do
|
||
|
local ev = {event.pull()}
|
||
|
|
||
|
if ev[1] == "rsendmsg" or ev[1] == "sendmsg" or ev[1] == "modem_message" then
|
||
|
-- log(table.unpack(ev))
|
||
|
end
|
||
|
|
||
|
if ev[1] == "rsendmsg" then
|
||
|
send(ev[2],ev[3])
|
||
|
elseif ev[1] == "sendmsg" then
|
||
|
table.remove(ev,1)
|
||
|
enqueue(table.unpack(ev))
|
||
|
elseif ev[1] == "modem_message" and ev[4] == net.np and ev[6] == "copper" then
|
||
|
local hops,src,dst,data = cdlib.decode(ev[7])
|
||
|
if hops and src and dst and data then
|
||
|
if lkr[src] ~= ev[3] then
|
||
|
log("lkr["..tostring(src).."] = "..tostring(ev[3]))
|
||
|
lkr[src] = {modem=ev[2],addr=ev[3],time=computer.uptime()}
|
||
|
end
|
||
|
ppacket(hops,src,dst,data)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
for k,v in pairs(pqueue) do
|
||
|
if computer.uptime() > v.lst+net.delay and pqueue[v.wf] == nil then
|
||
|
send(v.addr,relib.encode(v))
|
||
|
v.lst = computer.uptime()
|
||
|
v.at = v.at+1
|
||
|
if v.at > 254 then
|
||
|
pqueue[k] = nil
|
||
|
end
|
||
|
if v.unreliable then pqueue[k] = nil end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
for k,v in pairs(lkr) do
|
||
|
if computer.uptime() > v.time+net.cache_time then
|
||
|
lkr[k] = nil
|
||
|
end
|
||
|
end
|
||
|
for k,v in pairs(rpackets) do
|
||
|
if computer.uptime() > v+net.cache_time then
|
||
|
rpackets[k] = nil
|
||
|
end
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end)) end)
|
||
|
end
|