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