diff --git a/configs/everything.cfg b/configs/everything.cfg index d7ab9f1..85bee67 100755 --- a/configs/everything.cfg +++ b/configs/everything.cfg @@ -11,7 +11,7 @@ modules/lib/print.lua modules/drivers/kbd.lua modules/lib/cdlib.lua modules/lib/relib.lua -modules/net/copper.lua +modules/net/ncd.lua modules/util/motd.lua modules/lib/readline.lua modules/lib/shutil.lua diff --git a/configs/headless.cfg b/configs/headless.cfg index f0bc9e6..0690330 100755 --- a/configs/headless.cfg +++ b/configs/headless.cfg @@ -9,7 +9,7 @@ modules/lib/io.lua modules/lib/print.lua modules/lib/cdlib.lua modules/lib/relib.lua -modules/net/copper.lua +modules/net/ncd.lua modules/util/motd.lua modules/lib/readline.lua modules/lib/shutil.lua diff --git a/configs/minimal.cfg b/configs/minimal.cfg index b253ee0..db56986 100755 --- a/configs/minimal.cfg +++ b/configs/minimal.cfg @@ -11,7 +11,7 @@ modules/lib/print.lua modules/drivers/kbd.lua modules/lib/cdlib.lua modules/lib/relib.lua -modules/net/copper.lua +modules/net/ncd.lua modules/util/motd.lua modules/lib/readline.lua modules/lib/shutil.lua diff --git a/modules/net/ncd.lua b/modules/net/ncd.lua new file mode 100644 index 0000000..c00ccd3 --- /dev/null +++ b/modules/net/ncd.lua @@ -0,0 +1,156 @@ +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