Advertisement
osmarks

SensibleRednetRepeat

Nov 11th, 2018
2,198
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.00 KB | None | 0 0
  1. --[[
  2. For reasons outlined here (https://wiki.computercraft.cc/Network_security), Rednet is not really a good choice for new networking setups, apart from its capability to relay messages (obsoleted by ender modems).
  3.  
  4. However, if you do want to keep using it, without the risk of it crashing due to the exploits I have identified (https://pastebin.com/pJnfSDcL), you can use this convenient, patched repeater. It doesn't alleviate the fundamental issues with Rednet, though.
  5. ]]
  6.  
  7. -- Find modems
  8. local modems = {peripheral.find "modem"}
  9.  
  10. local comp_ID = os.getComputerID()
  11.  
  12. print(("%d modem(s) found"):format(#modems))
  13.  
  14. local function for_each_modem(fn)
  15.     for _, m in pairs(modems) do
  16.         fn(m)
  17.     end
  18. end
  19.  
  20. local function open(channel)
  21.     for_each_modem(function(m) m.open(channel) end)
  22. end
  23.  
  24. local function close(channel)
  25.     for_each_modem(function(m) m.close(channel) end)
  26. end
  27.  
  28. -- Open channels
  29. open(rednet.CHANNEL_REPEAT)
  30.  
  31. -- Main loop (terminate to break)
  32. local ok, error = pcall(function()
  33.     local received_messages = {}
  34.     local received_message_timers = {}
  35.     local transmitted_messages = 0
  36.  
  37.     while true do
  38.         local event, modem, channel, reply_channel, message, distance = os.pullEvent()
  39.         if event == "modem_message" then
  40.             -- Got a modem message, rebroadcast it if it's a rednet thing
  41.             if channel == rednet.CHANNEL_REPEAT and type(message) == "table" then
  42.                 local id = message.nMessageID -- unfortunately we must keep the stupid rednet identifiers SOMEWHERE...
  43.                 local recipient = message.nRecipient
  44.                 local route = message.route -- protocol extension
  45.                 if type(route) ~= "table" then route = { reply_channel } end
  46.                 table.insert(route, comp_ID)
  47.                 message.route = route
  48.                 if id and recipient and (type(id) == "number" or type(id) == "string") and type(recipient) == "number" and recipient >= 0 and recipient <= 65535 then
  49.                     if not received_messages[id] then
  50.                         -- Ensure we only repeat a message once per 30 seconds
  51.                         received_messages[id] = true
  52.                         received_message_timers[os.startTimer(30)] = id
  53.  
  54.                         -- Send on all other open modems, to the target and to other repeaters
  55.                         for_each_modem(function(m)
  56.                             m.transmit(rednet.CHANNEL_REPEAT, reply_channel, message)
  57.                             m.transmit(recipient, reply_channel, message)
  58.                         end)
  59.  
  60.                         -- Log the event
  61.                         transmitted_messages = transmitted_messages + 1
  62.                         term.clear()
  63.                         term.setCursorPos(1, 1)
  64.                         print(("%d message(s) repeated"):format(transmitted_messages))
  65.                         print(string.format("%s\nfrom %d to %s dist %d", tostring(message.message), reply_channel, tostring(recipient), tostring(distance) or "[n/a]"))
  66.                     end
  67.                 end
  68.             end
  69.  
  70.         elseif event == "timer" then
  71.             -- Got a timer event, use it to clear the message history
  72.             local timer = modem
  73.             local id = received_message_timers[timer]
  74.             if id then
  75.                 received_message_timers[timer] = nil
  76.                 received_messages[timer] = nil
  77.             end
  78.  
  79.         end
  80.     end
  81. end)
  82. if not ok then
  83.     printError(error)
  84. end
  85.  
  86. -- Close channels
  87. close(rednet.CHANNEL_REPEAT)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement