diff --git a/culib.lua b/culib.lua index eb3398f..f111d57 100644 --- a/culib.lua +++ b/culib.lua @@ -30,11 +30,11 @@ return function (hostname, transmit, onReceive, time) -- Expect a response by this many seconds, -- or else clear the known receivers cache and resend. - local tuningExpectResponse = 20 + local tuningExpectResponse = 10 -- Flush the loop detector every so often. -- This is not a complete clear. - local tuningFlushLoopDetector = 120 + local tuningFlushLoopDetector = 10 -- Do not change this value. I mean it. Don't. Just. Don't. local tuningAutorejectLen = 4000 @@ -49,17 +49,12 @@ return function (hostname, transmit, onReceive, time) local seenBefore = {} local seenBeforeCount = 0 - -- Unacknowledged packets. - -- Can cause an earlier cache flush. - -- [address] = giveupTime - -- (These are just forgotten after a while) - --local sentBNR = {}--NYI - -- [address] = { -- node, - -- expiry + -- expiry, + -- broadcastOnExpire -- } - --local lastKnownReceiver = {}--NYI + local lastKnownReceiver = {} local function refresh() local t = time() @@ -75,6 +70,14 @@ return function (hostname, transmit, onReceive, time) end loopDetectorNext = time() + tuningFlushLoopDetector end + for k, v in pairs(lastKnownReceiver) do + if t >= v[2] then + lastKnownReceiver[k] = nil + for _, m in ipairs(v[3]) do + transmit(nil, m) + end + end + end end local culib = {} @@ -82,6 +85,7 @@ return function (hostname, transmit, onReceive, time) -- Can be changed. culib.hostname = hostname culib.input = function (node, message) + local t = time() if message:len() > tuningAutorejectLen then return end @@ -97,24 +101,44 @@ return function (hostname, transmit, onReceive, time) seenBefore = {} end end + -- Begin parsing + local rawmessage = message + if message:len() < 2 then return end local nlen = message:byte(1) + 1 - local fnam = message:sub(1, nlen) - message = message:sub(nlen + 1) + local fnam = message:sub(2, nlen + 1) + message = message:sub(nlen + 2) + if message:len() < 2 then return end local nlen = message:byte(1) + 1 - local tnam = message:sub(1, nlen) - message = message:sub(nlen + 1) - if message:len() < 1 then return end + local tnam = message:sub(2, nlen + 1) + message = message:sub(nlen + 2) + + lastKnownReceiver[fnam] = {node, t + tuningExpectResponse, {}} + onReceive(fnam, tnam, message) if culib.hostname == tnam then return end + -- Redistribution of messages not aimed here - transmit(nil, message) + local lkr = lastKnownReceiver[tnam] + if lkr then + transmit(lkr[1], rawmessage) + table.insert(lkr[3], rawmessage) + else + transmit(nil, rawmessage) + end end + local function encodeName(name) + if name:len() > 256 then error("Bad name (l>256)") end + if name == "" then error("No name") end + return string.char(name:len() - 1) .. name + end + culib.refresh = refresh culib.output = function (fnam, tnam, message) onReceive(fnam, tnam, message) if tnam == culib.hostname then return end - transmit(nil, encodeName(fnam) .. encodeName(tnam) .. message) + local m = encodeName(fnam) .. encodeName(tnam) .. message + transmit(nil, m) end return culib end diff --git a/runtest.lua b/runtest.lua index 4e65480..d0b8771 100644 --- a/runtest.lua +++ b/runtest.lua @@ -1,13 +1,88 @@ -- Load testnet +local culib = require("culib") + local nodes = {} +local nodeconnect = {} local nodenames = {} -loadfile("testnet.lua")(function (n) - table.insert(nodes, {}) + +local systime = 0 +local function getsystime() + return systime / 20 +end + +local queuedCalls = {} +local function queueSend(n, v, data) + --print("transmit", n, v, data) + table.insert(queuedCalls, function () + nodes[v].input(n, data) + end) +end + +local statSD = 0 +local statPT = 0 + +loadfile("testnet.lua")()(function (n) + local conn = {} + local nodeidx = (#nodes) + 1 + table.insert(nodes, culib(n, function (node, data) + if node then + for _, v in ipairs(conn) do + if v == node then + queueSend(nodeidx, v, data) + return + end + end + error(nodeidx .. " -> " .. node .. " not directly possible") + else + for _, v in ipairs(conn) do + queueSend(nodeidx, v, data) + end + end + end, function (nfrom, nto, data) + if nto == n then + if data:sub(1, 1) == "T" then + nodes[nodeidx].output(n, nfrom, "R" .. data) + else + statSD = statSD + 1 + end + else + statPT = statPT + 1 + end + end, getsystime)) + table.insert(nodeconnect, conn) table.insert(nodenames, n) end, function (a, b) - table.insert(nodes[a], b) - table.insert(nodes[b], a) + table.insert(nodeconnect[a], b) + table.insert(nodeconnect[b], a) end) -- Start testing -require("culib") + +local function generateMessage() + local na = math.random(#nodes) + local nb = math.random(#nodes) + nodes[na].output(nodenames[na], nodenames[nb], "T" .. tostring(math.random())) +end + +local generateEvery = 1 +local generateCount = 10000 +while (generateCount > 0) or (#queuedCalls > 0) do + if (systime % generateEvery) == 0 then + if generateCount > 0 then + generateMessage() + generateCount = generateCount - 1 + end + end + local qc = queuedCalls + queuedCalls = {} + for _, v in ipairs(nodes) do + v.refresh() + end + for _, v in ipairs(qc) do + v() + end + print("run iteration, " .. #qc .. " calls") + systime = systime + 1 +end + +print(statSD, statPT)