diff --git a/oc/occure.lua b/oc/occure.lua index 7bdad9f..c382d59 100644 --- a/oc/occure.lua +++ b/oc/occure.lua @@ -19,6 +19,7 @@ if package.loaded["occure"] then error("Already installed") end +local culib = require("culib") local node = require("relib")(host, function (tgt, data) for _, v in ipairs(modems) do if tgt then @@ -29,15 +30,16 @@ local node = require("relib")(host, function (tgt, data) end end, function (...) computer.pushSignal("copper_packet", ...) -end, computer.uptime) - -package.loaded["occure"] = node +end, computer.uptime, culib) for v, _ in component.list("modem") do local m = component.proxy(v) table.insert(modems, m) m.open(4957) end + +package.loaded["occure"] = node + event.listen("modem_message", function (et, adto, adfrom, port, dist, magic, data) if et ~= "modem_message" then return end if port == 4957 then diff --git a/relib.lua b/relib.lua index 2e15a08..9add9f9 100644 --- a/relib.lua +++ b/relib.lua @@ -4,16 +4,34 @@ -- Copper Reliability Layer -- Notably, this should be instantiated rather than the normal Copper instance. -local culib = require("culib") +-- The Copper node constructor (which could be replaced with something else, +-- should you decide to run the Reliability layer over another transport) +-- is passed as function (hostname, transmit, onReceive, time), +-- where hostname is the hostname given, +-- transmit is the (target/nil (for broadcast), data) function as given, +-- onReceive is the (nfrom. nto, ndata) function +-- internal to the Reliability Layer to translate packets for onRReceive +-- and acknowledge packets that need to be acknowledged, +-- and time is the function-that-returns-current-time-in-seconds +-- function as given. + +-- The resulting Copper-like node should have the following fields: +-- node.hostname: Editable hostname. +-- node.refresh(): Do various timed cleanup tasks. +-- node.input(...): relib.input is set to this for convenience. +-- Ought to be function (opaqueFrom, data). +-- node.output(nFrom, nTo, data): The normal Copper send function. -- onRReceive is now: (from, to, port, data, unreliablePacket) --- where to can be anything for unreliable packets, but otherwise is the current hostname. -return function (hostname, transmit, onRReceive, time) +-- where to can be anything for unreliable packets, +-- but otherwise is the current hostname. +return function (hostname, transmit, onRReceive, time, culib) -- node.hostname should be used for hostname generally. local node - -- The maximum amount of timers (used to cap memory usage) - local tuningMaxTimers = 0x200 + -- The maximum amount of timers (used to cap memory usage). + -- Assuming 16 bytes per key, this should be 64k. + local tuningMaxTimers = 0x400 local tuningClearAntiduplicate = 60 local tuningAttempts = 12 local tuningAttemptTime = 2.5 @@ -78,15 +96,19 @@ return function (hostname, transmit, onRReceive, time) if nto ~= node.hostname then return end node.output(nto, nfrom, data:sub(1, 6) .. "\x02") end + -- Ignore ACKs for our packets that aren't going our way. + -- (Just a fringe case of packet ID reuse) + if nto ~= node.hostname then + return + end if (tp == 0x02) and needsAck[nfrom .. globalId] then needsAck[nfrom .. globalId][1](nfrom) killTimer(needsAck[nfrom .. globalId][2]) needsAck[nfrom .. globalId] = nil end - if nto ~= node.hostname then - return - end end + + -- Instantiate the node or lookalike. node = culib(hostname, transmit, onReceive, time) local relib = {}