local emerald = {} local path = "/usr/lib/emerald/" local component = require("component") local event = require("event") local fs = require("filesystem") local ser = require("serialization") local modem = component.modem local bPort = 20 -- Broadcast port local ePort = 21 -- General transmision port modem.open(bPort) local localAddress = modem.address local localAlias = "" emerald.localAlias = "" local router = "" -- LOG FUNCTIONS -- local function log(f, m) event.push("emerald", f, m) end -- LEN FUNCTION -- (Gives the length of a table) local function len(table) local count = 0 for _, _ in pairs(table) do count = count + 1 end return count end -- READ FUNCTION -- (Read the config file) local function read() if fs.exists(path..".eConfig.cfg") then local file = io.open(path..".eConfig.cfg") local stream = file:read() file:close() return ser.unserialize(stream) else log("ERR", "No config file.") return "{}" end end -- WAIT FOR ACK FUNCTION -- (Wait 5 secs for a confirmation after send()) local function wait(expectedFrom) local _, _, addr, _, _, flag, from, to = event.pull(5, "modem_message") if flag == "ACK" then if from == expectedFrom then log("LOG", "ACK") else log("ERR", "Entangled packets. Expected from: "..expectedFrom.." but received from: "..from) end elseif flag == "PNF" then log("ERR", "Pair not found.") else log("ERR", "Pair seems to have crashed. Disconnecting pair.") modem.send(router, ePort, "DISCONNECT", "0", expectedFrom) end end -- HANDLER FUNCTION -- (Handle all incoming transmissions) function handler(_, _, addr, _, _, flag, from, to, data) if flag == "MSG" then log("MSG", data) modem.send(router, ePort, "ACK", localAlias, from) end end -- WHO FUNCTION -- (Tries to discover all nearby routers) function emerald.who() modem.broadcast(bPort, "WHO") local doSearch = true local routerList = {} while doSearch do _, _, addr, _, _, flag, alias = event.pull(1, "modem_message") if flag == nil then doSearch = false return routerList elseif flag == "WHO" then routerList[alias] = addr end end return routerList end -- CONNECT FUNCTION -- (Connect to the router) function emerald.connect() if router == "" then data = read() localAlias = data["hostname"] emerald.localAlias = localAlias to = data["router"] modem.send(to, bPort, "CONNECT", localAddress, localAlias) _, _, addr, _, _, flag = event.pull(2, "modem_message") if addr == to then if flag == "CONNECT" then router = addr log("LOG", "CONNECT") modem.close(bPort) modem.open(ePort) messageListener = event.listen("modem_message", handler) elseif flag == "DPL" then log("ERR", flag) end end else log("ERR", "Already connected to router.") end end -- SEND FUNCTION -- (Send a message to another node) function emerald.send(to, data) if router ~= "" then modem.send(router, ePort, "MSG", localAlias, to, data) wait(to) else log("ERR", "Not connected to router.") end end -- DISCONNECT FUNCTION -- (Disconnect from the router) function emerald.disconnect() if router ~= "" then modem.send(router, ePort, "DISCONNECT", localAddress, localAlias) _, _, addr, _, _, flag = event.pull(2, "modem_message") if addr == router then if flag == "DISCONNECT" then router = "" log("LOG", "DISCONNECT") modem.close(ePort) modem.open(bPort) end end else log("ERR", "Not connected to a router.") end end return emerald