Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- if not fs.exists ".jnet-ecc.0.lua" then
- print "ECC not found. Downloading..."
- local h = http.get "https://pastebin.com/raw/ykK4UMa6"
- local f = fs.open(".jnet-ecc.0.lua", "w")
- f.write(h.readAll())
- h.close()
- f.close()
- print "Done!"
- end
- local ecc = dofile ".jnet-ecc.0.lua"
- local CHANNEL = 62831
- local modems = {}
- local LOG_LEVEL = 3
- local function log(level, ...)
- if level <= LOG_LEVEL then
- local out = {os.clock()}
- for _, thing in pairs{...} do
- if type(thing) == "string" then table.insert(out, thing)
- else
- local ok, x = pcall(textutils.serialise, thing)
- if ok then table.insert(out, x)
- else table.insert(out, tostring(thing)) end
- end
- end
- print(table.concat(out, " "))
- end
- end
- local function log_debg(...) log(3, ...) end
- local function log_info(...) log(2, ...) end
- local function log_warn(...) log(1, ...) end
- local function log_fail(...) log(0, ...) end
- local function hex_to_bytes(hex)
- local out = {}
- for i = 1, #hex, 2 do
- local pair = hex:sub(i, i + 1)
- table.insert(out, tonumber(pair, 16))
- end
- return out
- end
- local function bytes_to_hex(key)
- local out = ""
- for _, v in pairs(key) do
- out = out .. string.format("%.2x", v)
- end
- return out
- end
- local private_key, public_key = settings.get "jnet.private_key"
- if not private_key then
- log_warn "Private key for node not found. A keypair is being generated."
- private_key, public_key = ecc.keypair()
- settings.set("jnet.private_key", bytes_to_hex(private_key))
- settings.save ".settings"
- else
- private_key = hex_to_bytes(private_key)
- public_key = ecc.publicKey(private_key)
- end
- log_info("Public key is", bytes_to_hex(public_key))
- -- Generate random 31-bit-or-so UUID. Why? Because CC's random function is mildly broken.
- local function generate_UUID()
- if chaos then -- Use PotatOS Chaos service if available
- return chaos.get_u32()
- end
- return math.random(0, 0x6FFFFFFF)
- end
- local seen_UUIDs = {}
- local UUID_clear_timers = {}
- local function add_modem(name)
- local new = peripheral.wrap(name)
- modems[name] = new
- new.open(CHANNEL)
- new.wireless = new.isWireless() -- cache wireless-ness
- log_info("Added modem", name)
- end
- local function log_UUID(UUID)
- seen_UUIDs[UUID] = true
- UUID_clear_timers[UUID] = os.startTimer(30)
- end
- local function handle_packet(packet)
- if packet.type == "data" and type(packet.UUID) == "number" and packet.data then
- -- lazy rednet-style relaying
- log_info("Received packet", packet)
- os.queueEvent("jnet_packet", packet)
- if not seen_UUIDs[packet.UUID] then
- log_info("Retransmitting", packet.UUID)
- for name, periph in pairs(modems) do
- periph.transmit(CHANNEL, CHANNEL, packet)
- log_debg("Transmitted on modem", name)
- end
- log_UUID(packet.UUID)
- else
- log_debg("Ignoring already-handled packet", packet.UUID)
- end
- else
- log_info("Invalid packet", packet)
- end
- end
- local function listener()
- peripheral.find("modem", add_modem)
- while true do
- local ev = {coroutine.yield()}
- if ev[1] == "peripheral" then
- local _, name = unpack(ev)
- if peripheral.getType(name) == "modem" then
- add_modem(name)
- end
- elseif ev[1] == "peripheral_detach" then
- local _, name = unpack(ev)
- if peripheral.getType(name) == "modem" then modems[name] = nil end
- elseif ev[1] == "modem_message" then
- local _, side, channel, reply_channel, packet, distance = unpack(ev)
- if channel == CHANNEL and type(packet) == "table" then
- handle_packet(packet)
- end
- elseif ev[1] == "timer" then
- local timer = ev[2]
- local UUID = UUID_clear_timers[timer]
- if UUID then
- log_debg("Removing UUID", UUID, "from seen UUIDs.")
- seen_UUIDs[UUID] = nil
- UUID_clear_timers[timer] = nil
- end
- end
- end
- end
- local function send(data)
- local UUID = generate_UUID()
- log_UUID(UUID)
- for name, periph in pairs(modems) do
- periph.transmit(CHANNEL, CHANNEL, { UUID = UUID, data = data, type = "data" })
- end
- end
- local function recv()
- local _, packet = os.pullEvent "jnet_packet"
- return packet.data, packet
- end
- local option = ...
- if option == "send" then
- parallel.waitForAny(listener, function()
- send(read())
- end)
- elseif option == "recv" then
- parallel.waitForAny(listener, function()
- print(recv())
- end)
- elseif option == "run" then
- listener()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement