mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-14 04:00:30 +00:00
Fix computer IDs greater than 65535 crashing Rednet (#900)
This commit is contained in:
parent
eb61c5c5d7
commit
297426419b
@ -61,6 +61,8 @@
|
||||
(table space)
|
||||
(index no-space))
|
||||
|
||||
(allow-clarifying-parens true)
|
||||
|
||||
;; colours imports from colors, and we don't handle that right now.
|
||||
;; keys is entirely dynamic, so we skip it.
|
||||
(dynamic-modules colours keys _G)
|
||||
|
@ -25,10 +25,18 @@ CHANNEL_BROADCAST = 65535
|
||||
--- The channel used by the Rednet API to repeat messages.
|
||||
CHANNEL_REPEAT = 65533
|
||||
|
||||
--- The number of channels rednet reserves for computer IDs. Computers with IDs
|
||||
-- greater or equal to this limit wrap around to 0.
|
||||
MAX_ID_CHANNELS = 65500
|
||||
|
||||
local tReceivedMessages = {}
|
||||
local tReceivedMessageTimeouts = {}
|
||||
local tHostnames = {}
|
||||
|
||||
local function id_as_channel(id)
|
||||
return (id or os.getComputerID()) % MAX_ID_CHANNELS
|
||||
end
|
||||
|
||||
--[[- Opens a modem with the given @{peripheral} name, allowing it to send and
|
||||
receive messages over rednet.
|
||||
|
||||
@ -47,7 +55,7 @@ function open(modem)
|
||||
if peripheral.getType(modem) ~= "modem" then
|
||||
error("No such modem: " .. modem, 2)
|
||||
end
|
||||
peripheral.call(modem, "open", os.getComputerID())
|
||||
peripheral.call(modem, "open", id_as_channel())
|
||||
peripheral.call(modem, "open", CHANNEL_BROADCAST)
|
||||
end
|
||||
|
||||
@ -64,7 +72,7 @@ function close(modem)
|
||||
if peripheral.getType(modem) ~= "modem" then
|
||||
error("No such modem: " .. modem, 2)
|
||||
end
|
||||
peripheral.call(modem, "close", os.getComputerID())
|
||||
peripheral.call(modem, "close", id_as_channel())
|
||||
peripheral.call(modem, "close", CHANNEL_BROADCAST)
|
||||
else
|
||||
-- Close all modems
|
||||
@ -87,7 +95,7 @@ function isOpen(modem)
|
||||
if modem then
|
||||
-- Check if a specific modem is open
|
||||
if peripheral.getType(modem) == "modem" then
|
||||
return peripheral.call(modem, "isOpen", os.getComputerID()) and peripheral.call(modem, "isOpen", CHANNEL_BROADCAST)
|
||||
return peripheral.call(modem, "isOpen", id_as_channel()) and peripheral.call(modem, "isOpen", CHANNEL_BROADCAST)
|
||||
end
|
||||
else
|
||||
-- Check if any modem is open
|
||||
@ -134,10 +142,11 @@ function send(nRecipient, message, sProtocol)
|
||||
tReceivedMessageTimeouts[os.startTimer(30)] = nMessageID
|
||||
|
||||
-- Create the message
|
||||
local nReplyChannel = os.getComputerID()
|
||||
local nReplyChannel = id_as_channel()
|
||||
local tMessage = {
|
||||
nMessageID = nMessageID,
|
||||
nRecipient = nRecipient,
|
||||
nSender = os.getComputerID(),
|
||||
message = message,
|
||||
sProtocol = sProtocol,
|
||||
}
|
||||
@ -145,10 +154,14 @@ function send(nRecipient, message, sProtocol)
|
||||
local sent = false
|
||||
if nRecipient == os.getComputerID() then
|
||||
-- Loopback to ourselves
|
||||
os.queueEvent("rednet_message", nReplyChannel, message, sProtocol)
|
||||
os.queueEvent("rednet_message", os.getComputerID(), message, sProtocol)
|
||||
sent = true
|
||||
else
|
||||
-- Send on all open modems, to the target and to repeaters
|
||||
if nRecipient ~= CHANNEL_BROADCAST then
|
||||
nRecipient = id_as_channel(nRecipient)
|
||||
end
|
||||
|
||||
for _, sModem in ipairs(peripheral.getNames()) do
|
||||
if isOpen(sModem) then
|
||||
peripheral.call(sModem, "transmit", nRecipient, nReplyChannel, tMessage)
|
||||
@ -390,13 +403,14 @@ function run()
|
||||
if sEvent == "modem_message" then
|
||||
-- Got a modem message, process it and add it to the rednet event queue
|
||||
local sModem, nChannel, nReplyChannel, tMessage = p1, p2, p3, p4
|
||||
if isOpen(sModem) and (nChannel == os.getComputerID() or nChannel == CHANNEL_BROADCAST) then
|
||||
if isOpen(sModem) and (nChannel == id_as_channel() or nChannel == CHANNEL_BROADCAST) then
|
||||
if type(tMessage) == "table" and type(tMessage.nMessageID) == "number"
|
||||
and tMessage.nMessageID == tMessage.nMessageID and not tReceivedMessages[tMessage.nMessageID]
|
||||
and ((tMessage.nRecipient and tMessage.nRecipient == os.getComputerID()) or nChannel == CHANNEL_BROADCAST)
|
||||
then
|
||||
tReceivedMessages[tMessage.nMessageID] = true
|
||||
tReceivedMessageTimeouts[os.startTimer(30)] = tMessage.nMessageID
|
||||
os.queueEvent("rednet_message", nReplyChannel, tMessage.message, tMessage.sProtocol)
|
||||
os.queueEvent("rednet_message", tMessage.nSender or nReplyChannel, tMessage.message, tMessage.sProtocol)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -14,6 +14,10 @@ else
|
||||
print(#tModems .. " modems found.")
|
||||
end
|
||||
|
||||
local function idAsChannel(id)
|
||||
return (id or os.getComputerID()) % rednet.MAX_ID_CHANNELS
|
||||
end
|
||||
|
||||
local function open(nChannel)
|
||||
for n = 1, #tModems do
|
||||
local sModem = tModems[n]
|
||||
@ -53,7 +57,7 @@ local ok, error = pcall(function()
|
||||
for n = 1, #tModems do
|
||||
local sOtherModem = tModems[n]
|
||||
peripheral.call(sOtherModem, "transmit", rednet.CHANNEL_REPEAT, nReplyChannel, tMessage)
|
||||
peripheral.call(sOtherModem, "transmit", tMessage.nRecipient, nReplyChannel, tMessage)
|
||||
peripheral.call(sOtherModem, "transmit", idAsChannel(tMessage.nRecipient), nReplyChannel, tMessage)
|
||||
end
|
||||
|
||||
-- Log the event
|
||||
|
@ -84,7 +84,7 @@ describe("The rednet library", function()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("on a fake computers", function()
|
||||
describe("on fake computers", function()
|
||||
local fake_computer = require "support.fake_computer"
|
||||
|
||||
local function computer_with_rednet(id, fn, options)
|
||||
@ -168,5 +168,24 @@ describe("The rednet library", function()
|
||||
|
||||
fake_computer.run_all({ computer_1, computer_2, computer_3 }, { computer_1, computer_3 })
|
||||
end)
|
||||
|
||||
it("repeats messages between computers with massive ids", function()
|
||||
local id_1, id_3 = 24283947, 93428798
|
||||
local computer_1, modem_1 = computer_with_rednet(id_1, function(rednet, _ENV)
|
||||
rednet.send(id_3, "Hello")
|
||||
local id, message = rednet.receive()
|
||||
expect { id, message }:same { id_3, "World" }
|
||||
end, { open = true })
|
||||
local computer_2, modem_2 = computer_with_rednet(2, nil, { open = true, rep = true })
|
||||
local computer_3, modem_3 = computer_with_rednet(id_3, function(rednet)
|
||||
rednet.send(id_1, "World")
|
||||
local id, message = rednet.receive()
|
||||
expect { id, message }:same { id_1, "Hello" }
|
||||
end, { open = true })
|
||||
fake_computer.add_modem_edge(modem_1, modem_2)
|
||||
fake_computer.add_modem_edge(modem_2, modem_3)
|
||||
|
||||
fake_computer.run_all({ computer_1, computer_2, computer_3 }, { computer_1, computer_3 })
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
@ -70,15 +70,22 @@ local function make_computer(id, fn)
|
||||
return { env = env, peripherals = peripherals, queue_event = queue_event, step = step, co = co }
|
||||
end
|
||||
|
||||
local function parse_channel(c)
|
||||
if c < 0 or c > 65535 then error("Expected number in range 0-65535", 3) end
|
||||
return c
|
||||
end
|
||||
|
||||
--- Add a modem to a computer on a particular side
|
||||
local function add_modem(owner, side)
|
||||
local open, adjacent = {}, {}
|
||||
local peripheral = setmetatable({
|
||||
open = function(channel) open[channel] = true end,
|
||||
close = function(channel) open[channel] = false end,
|
||||
open = function(channel) open[parse_channel(channel)] = true end,
|
||||
close = function(channel) open[parse_channel(channel)] = false end,
|
||||
closeAll = function(channel) open = {} end,
|
||||
isOpen = function(channel) return open[channel] == true end,
|
||||
isOpen = function(channel) return open[parse_channel(channel)] == true end,
|
||||
transmit = function(channel, reply_channel, payload)
|
||||
channel, reply_channel = parse_channel(channel), parse_channel(reply_channel)
|
||||
|
||||
for _, adjacent in pairs(adjacent) do
|
||||
if adjacent.open[channel] then
|
||||
adjacent.owner.queue_event("modem_message", adjacent.side, channel, reply_channel, payload, 123)
|
||||
|
Loading…
Reference in New Issue
Block a user