Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- GLOBALS
- local routers = {}
- local servers = {}
- local side = "top"
- local myID = os.getComputerID()
- local w, h = term.getSize()
- -- Functions & Stuff
- function writeToFile(data, filename)
- local file = fs.open(filename, "w")
- file.write(textutils.serialise(data))
- file.close()
- end
- function readFromFile(filename)
- if not fs.exists(filename) then
- return
- end
- local file = fs.open(filename, "r")
- local data = file.readAll()
- file.close()
- return data
- end
- function split(str, pat)
- local t = { }
- local fpat = "(.-)"..pat
- local last_end = 1
- local s, e, cap = str:find(fpat, 1)
- while s do
- if s ~= 1 or cap ~= "" then
- table.insert(t,cap)
- end
- last_end = e+1
- s, e, cap = str:find(fpat, last_end)
- end
- if last_end <= #str then
- cap = str:sub(last_end)
- table.insert(t, cap)
- end
- return t
- end
- function addConnector(newid, parentid, connections)
- -- If there are no connectors there is nothing to add to.
- if #connections == 0 then return false end
- for i = 1, #connections, 1 do
- local child = connections[i]
- -- Removing new connector if it already exists.
- for j = 1, #child.children, 1 do
- if child.children[j].id == newid then
- table.remove(child.children, j)
- end
- end
- -- If parent connector is found, add new connector to children.
- if child.id == parentid then
- table.insert(child.children, {
- id = newid,
- children = {}
- })
- return true
- end
- -- If no parent connector is found, use recursion to go through all children of the the current connector.
- addConnector(newid, parentid, child.children)
- end
- -- If no parent connector is found, return false.
- return false
- end
- function removeConnector(oldid, connections)
- -- If there are no connections we can't remove any.
- if #connections == 0 then return false end
- -- Looping over connections to find target id.
- for i = 1, #connections, 1 do
- local child = connections[i]
- -- If current router's id matches the one we're looking for, remove it and return true.
- if child.id == oldid then
- table.remove(connections, i)
- return true
- end
- -- Using recursion to search all children of the current router for the id we're looking for.
- if removeConnector(oldid, child.children) then return true end
- end
- -- Returning false if we don't find the id we're looking for.
- return false
- end
- function findConnector(id, connections)
- -- If no connections are found we have nothing to search for.
- if #connections == 0 then return "" end
- -- Loop through all connections to find the id we're searching for.
- for i = 1, #connections, 1 do
- local child = connections[i]
- -- If the current router's id matches the one we're searching for we return that.
- if child.id == id then return child.id end
- -- Using recursion to search routers' childs.
- local path = findConnector(id, child.children)
- -- If a path is found to the id we're searching for, we'll return the current router's id and that path.
- if path ~= "" then return child.id.."-"..path end
- end
- return ""
- end
- function findTopConnector(id)
- -- Loop over all top routers and check id's.
- for i = 1, #routers, 1 do
- local route = routers[i]
- -- If top router is the one we're searching for we don't return a path.
- if route.id == id then
- return route.id, ""
- end
- -- Trying to find the id we're searching for in current routers children.
- local path = findConnector(id, route.children)
- -- If a path is found to the id we're searching for, return the current router id and that path.
- if path ~= "" then return route.id, path end
- end
- -- If no path at all is found, error.
- print("A network error has occured.")
- return -1, ""
- end
- function printNetworkTree(connections, index)
- -- If no connections, we can't print the network tree.
- if #connections == 0 then return end
- for i = 1, #connections, 1 do
- local child = connections[i]
- print(string.rep(" ", index)..child.id)
- printNetworkTree(child.children, index + 1)
- end
- end
- function processRequest(request, senderId)
- -- Same in routers, simple responds to messages.
- if request == "$HELLO" then
- -- If we receive a network discovery message, we'll respond with $HELLO
- rednet.send(senderId, "$HELLO")
- return
- elseif request == "$ADDME" then
- -- If we receive an add me request, we'll instantly add this router to the network.
- table.insert(routers, {
- id = senderId,
- children = {}
- })
- local file =
- rednet.send(senderId, "$ACK")
- printNetworkTree(routers, 0)
- return
- end
- -- If it's a client request, we'll funnel it down to the next router close to the target router.
- if string.find(request, "$CLIENT") then
- request = string.gsub(request, "$CLIENT", "")
- local values = split(request, "-")
- -- Finding the path to the target router, to send it to the closest one.
- local routeId, dest = findTopConnector(tonumber(values[1]))
- if dest ~= "" then
- request = dest.."-"..values[2]
- else
- request = values[2]
- end
- rednet.send(routeId, request)
- -- If it's a server request, we'll send it to the right server.
- elseif string.find(request, "$SERVER") then
- local sent = false
- request = string.gsub(request, "$SERVER", "")
- -- Finding the server to forward the request to.
- for i = 1, #servers, 1 do
- local s, e = string.find(request, servers[i].name)
- if s == 2 then
- request = string.sub(request, e + 1)
- rednet.send(servers[i].id, request)
- sent = true
- break
- end
- end
- -- If no server is found, we ignore it.
- if not sent then print("No server with the requested name is registered on the network. Requested server: "..request) end
- -- If it's meant for the master server we'll process it ourselves.
- elseif string.find(request, "$MASTER") then
- request = string.gsub(request, "$MASTER", "")
- -- If we receive an add router request, this means the request has been through more than just the original router.
- if string.find(request, "$ADDROUTER") then
- request = string.gsub(request, "$ADDROUTER", "")
- local values = split(request, "-")
- -- We'll add the router to the children of the router we received the message from.
- addConnector(tonumber(values[1]), tonumber(values[2]), routers)
- print("Added new router.")
- printNetworkTree(routers, 0)
- -- We'll find the nearest router on the path to the newly added router, and send an ackowledged message back.
- local routeId, dest = findTopConnector(tonumber(values[1]))
- rednet.send(routeId, dest.."-$ACK")
- -- Adding a new server when receiving this request.
- elseif string.find(request, "$ADDSERVER") then
- request = string.gsub(request, "$ADDSERVER", "")
- local values = split(request, "-")
- table.insert(servers, {
- id = tonumber(values[1]),
- name = values[2]
- })
- print("Added new server: "..values[2])
- rednet.send(senderId, "$ACK")
- end
- -- If the message isn't recognized we'll ignore it.
- else
- print("Unrecognizable message received.")
- end
- end
- function printHeader()
- term.setCursorPos(1, 1)
- print(string.rep("-", w))
- term.setCursorPos(w/2 - #"MASTER SERVER"/2, 2)
- print("MASTER SERVER")
- term.setCursorPos(1, 3)
- print(string.rep("-", w))
- print("Open on ID "..myID)
- print("")
- end
- -- Main Logic
- if not fs.exists("gravinet/master/pref") then
- error("Master server not installed via installer, make sure to do that!")
- return
- end
- local pref = textutils.unserialise(readFromFile("gravinet/master/pref"))
- side = pref.side
- if fs.exists("gravinet/master/routers") then
- routers = textutils.unserialise(readFromFile("gravinet/master/routers"))
- end
- if fs.exists("gravinet/master/servers") then
- servers = textutils.unserialise(readFromFile("gravinet/master/servers"))
- end
- term.clear()
- rednet.open(side)
- printHeader()
- while true do
- local cx, cy = term.getCursorPos()
- printHeader()
- term.setCursorPos(cx, cy)
- print("Listening for request...")
- local requestID, request = rednet.receive()
- processRequest(request, requestID)
- end
- rednet.close()
Add Comment
Please, Sign In to add comment