Skip to content

Commit

Permalink
GERTi v1.4 - Release (#73)
Browse files Browse the repository at this point in the history
* GERTi v1.2.1 with feeling

Finish properly sending arguments in GERTi.send and update the version number

* GERTi v1.2.2

I hate Lua dynamic typing. Fixes a problem with floats that should be integers.

* Add an RC version of GERTiMNC

Adds a RC version of GERTiMNC for an alternative method of autoloading it on boot and having it run in the background

* Rename file

Apparently, GitHub only loads Readme.md

* GERTi v1.3 Build 1

Begin cleanup of functions and start shrinking size. At this point, still compatible with v1.2, but this will change.

Completely untested and likely contains bugs.

* GERTi v1.3 - Build 2

Continued cleanup of the route opening logic and the startup logic. This is now protocol incompatible with v1.2.

Fixed at least one bug in Build 1, but still untested and likely broken.

* GERTiClient v1.3 - Build 3

Finish all the theoretical changes to GERTiClient to simplify route opening from 3 functions down to 2. Socket opening changed to reflect this.

Only remaining work is bugtesting and GERTiMNC feature addition

* GERTiMNC v1.3 - Build 3

-- Change: GERTiMNC now solely resides as an RC service in /etc/rc.d

--Change: Configuration files have moved to /etc

-- Feature Addition: triggering the loadAddress command will have the MNC reload the list of addresses. This way, you can change the modem address tied to a certain GERTi address without restarting the entire network. The GERTiClient for that node must be restarted for it to take effect.

* GERTi v1.3 - Build 4

Fix some errors that result in the Client failing to boot or obtain an address. More errors likely await in connection handling.

* GERTiClient v1.3 - Build 5

Now comes with the ability to open connections at least to neighbors. With the exception of GERTi.send(), data transmission is still bugged

* GERTi v1.3 - Build 6

Data transmission now works between neighbors at least. Final testing will involve linked cards and multiple hops.

* GERTi v1.3 - Build 7

Fixes a bug that prevents users from closing connections

* GERTi v1.3 Release

After testing and bugfixing, GERTi is now stable. Protocol incompatible with v1.2, but API compatible

* Update Reserved GERTe numbers.txt

* Update Reserved GERTe numbers.txt

* Cleanup

* GERTeAPI v1.3 - Build 1

Update the GERTeAPI to fit the GERTiMNC RC daemon. Pending testing.

* GERTi v1.3.1

Update GERTiMNC to resolve performance drop with incoming GERTe packets

* GERTi v1.4 Build 1

Lifts the linked and modem card combination limits. Completely untested and likely has bugs

* GERTi v1.4 Build 2

More bugfixes. Now it will
1) Actually load
2) Support multiple cards on the MNC properly
3) Actually open connections

* GERTi v1.4 Build 3

All known currently existing bugs have been patched. This should be suitable for temporary deployment. Subsequent builds will likely include more bugs.

* GERTi v1.4 RC 1

This addition includes all planned features and has been bugtested. It is suitable for deployment across networks.

Release candidate instead of final only because a slight change to Data handling may occur where computers may be able to silently re-add connections to their connection tables, thus allowing for more graceful handling of hard power restarts.

* GERTi v1.4 - Release

Fixed a bug with GERTiMNC address assignment
Added a feature allowing the receiving end of a connection to automatically regenerate the connection if it reboots improperly without executing the shutdown or reboot command.
  • Loading branch information
MajorGeneralRelativity authored Mar 25, 2021
1 parent 9ec327e commit 01bc21b
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 154 deletions.
186 changes: 107 additions & 79 deletions GERTi/GERTiClient.lua
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
-- GERT v1.3
-- GERT v1.4
local GERTi = {}
local component = require("component")
local computer = require("computer")
local event = require("event")
local serialize = require("serialization")
local modem
local tunnel
local mTable, tTable

if (component.isAvailable("modem")) then
modem = component.modem
modem.open(4378)
if (component.modem.isWireless()) then
modem.setStrength(500)
mTable = {}
for address, value in component.list("modem") do
mTable[address] = component.proxy(address)
mTable[address].open(4378)
if (mTable[address].isWireless()) then
mTable[address].setStrength(500)
end
end
end
if (component.isAvailable("tunnel")) then
tunnel = component.tunnel
tTable = {}
for address, value in component.list("tunnel") do
tTable[address] = component.proxy(address)
end
end
if not (modem or tunnel) then
io.stderr:write("This program requires a network or linked card to run.")
if not (mTable or tTable) then
io.stderr:write("This program requires a network card or linked card to run.")
os.exit(1)
end

Expand All @@ -28,7 +33,7 @@ local tier = 3
local nodes = {}
local firstN = {}

-- connections[connectDex][data/order] Connections are established at any point along a route
-- Connections are established at any point along a route
local connections = {}
local cPend = {}
local rPend = {}
Expand All @@ -43,23 +48,21 @@ local function waitWithCancel(timeout, cancelCheck)
end
end

local function storeNodes(gAddress, sendingModem, port, nTier)
nodes[gAddress] = {add = sendingModem, port = tonumber(port), tier = nTier}
local function storeNodes(gAddress, receiverM, sendM, port, nTier)
nodes[gAddress] = {add = sendM, receiveM = receiverM, port = tonumber(port), tier = nTier}
if (not firstN["tier"]) or nTier < firstN["tier"] then
tier = nTier+1
firstN = nodes[gAddress]
firstN["gAdd"] = gAddress
end
end
local function storeConnection(origin, ID, GAdd, nextHop, port)
local function storeConnection(origin, ID, GAdd, nextHop, sendM, port)
ID = math.floor(ID)
local connectDex = origin.."|"..GAdd.."|"..ID
connections[connectDex] = {}
connections[connectDex]["origin"]=origin
connections[connectDex]["dest"]=GAdd
connections[connectDex]["ID"]=ID
connections[connectDex] = {["origin"]=origin, ["dest"]=GAdd, ["ID"]=ID}
if GAdd ~= iAdd then
connections[connectDex]["nextHop"]=nextHop
connections[connectDex]["sendM"] = sendM
connections[connectDex]["port"]=port
else
connections[connectDex]["data"]={}
Expand All @@ -80,148 +83,170 @@ local function storeData(connectDex, data, order)
computer.pushSignal("GERTData", connections[connectDex]["origin"], connections[connectDex]["ID"])
end

local function transInfo(sendTo, port, ...)
if modem and port ~= 0 then
modem.send(sendTo, port, ...)
elseif tunnel then
tunnel.send(...)
local function transInfo(sendTo, localM, port, ...)
if mTable and mTable[localM] then
mTable[localM].send(sendTo, port, ...)
elseif tTable and tTable[localM] then
tTable[localM].send(...)
end
end

local handler = {}
handler.CloseConnection = function(sendingModem, port, connectDex)
handler.CloseConnection = function(_, _, port, connectDex)
if connections[connectDex]["nextHop"] then
transInfo(connections[connectDex]["nextHop"], connections[connectDex]["port"], "CloseConnection", connectDex)
transInfo(connections[connectDex]["nextHop"], connections[connectDex]["sendM"], connections[connectDex]["port"], "CloseConnection", connectDex)
else
computer.pushSignal("GERTConnectionClose", connections[connectDex]["origin"], connections[connectDex]["dest"], connections[connectDex]["ID"])
end
connections[connectDex] = nil
end

handler.Data = function (sendingModem, port, data, connectDex, order, origin)
handler.Data = function (_, _, port, data, connectDex, order, origin)
if connectDex == -1 then
return computer.pushSignal("GERTData", origin, -1, data)
end
if connections[connectDex] then
if connections[connectDex]["dest"] == iAdd then
storeData(connectDex, data, order)
else
transInfo(connections[connectDex]["nextHop"], connections[connectDex]["port"], "Data", data, connectDex, order)
transInfo(connections[connectDex]["nextHop"], connections[connectDex]["sendM"], connections[connectDex]["port"], "Data", data, connectDex, order)
end
else
origin = string.sub(connectDex, 1, string.find(connectDex, "|")-1)
local dest = string.sub(connectDex, #origin+2, string.find(connectDex, "|", #origin+2)-1)
local ID = string.sub(connectDex, #origin+#dest+3)
origin = tonumber(origin)
dest = tonumber(dest)
ID = tonumber(ID)
if dest == iAdd then
storeConnection(origin, ID, dest)
handler.Data(_, _, port, data, connectDex, order)
end
end
end

handler.NewNode = function (sendingModem, port, gAddress, nTier)
handler.NewNode = function (receiveM, sendM, port, gAddress, nTier)
if gAddress then
storeNodes(tonumber(gAddress), sendingModem, port, nTier)
storeNodes(tonumber(gAddress), receiveM, sendM, port, nTier)
else
transInfo(sendingModem, port, "NewNode", iAdd, tier)
transInfo(sendM, receiveM, port, "NewNode", iAdd, tier)
end
end
local function sendOK(bHop, recPort, dest, origin, ID)
local function sendOK(bHop, receiveM, recPort, dest, origin, ID)
if dest==iAdd then
computer.pushSignal("GERTConnectionID", origin, ID)
end
if origin ~= iAdd then
transInfo(bHop, recPort, "RouteOpen", dest, origin, ID)
transInfo(bHop, receiveM, recPort, "RouteOpen", dest, origin, ID)
end
end
handler.OpenRoute = function (sendingModem, port, dest, intermediary, origin, ID)
handler.OpenRoute = function (receiveM, sendM, port, dest, intermediary, origin, ID)
if dest == iAdd then
storeConnection(origin, ID, dest)
sendOK(sendingModem, port, dest, origin, ID)
sendOK(sendM, receiveM, port, dest, origin, ID)
elseif nodes[dest] then
transInfo(nodes[dest]["add"], nodes[dest]["port"], "OpenRoute", dest, nil, origin, ID)
transInfo(nodes[dest]["add"], nodes[dest]["receiveM"], nodes[dest]["port"], "OpenRoute", dest, nil, origin, ID)
elseif not intermediary then
transInfo(firstN["add"], firstN["port"], "OpenRoute", dest, nil, origin, ID)
transInfo(firstN["add"], firstN["receiveM"], firstN["port"], "OpenRoute", dest, nil, origin, ID)
else
local nextHop = tonumber(string.sub(intermediary, 1, string.find(intermediary, "|")-1))
intermediary = string.sub(intermediary, string.find(intermediary, "|")+1)
transInfo(nodes[nextHop]["add"], nodes[nextHop]["port"], "OpenRoute", dest, intermediary, origin, ID)
transInfo(nodes[nextHop]["add"], nodes[nextHop]["receiveM"], nodes[nextHop]["port"], "OpenRoute", dest, intermediary, origin, ID)
end
cPend[dest..origin]={["bHop"]=sendingModem, ["port"]=port}
cPend[dest..origin]={["bHop"]=sendM, ["port"]=port, ["receiveM"]=receiveM}
end
handler.RegisterComplete = function(sender, port, target, newG)
if (modem and target == modem.address) or (tunnel and target == tunnel.address) then
handler.RegisterComplete = function(receiveM, _, port, target, newG)
if (mTable and mTable[target]) or (tTable and tTable[target]) then
iAdd = tonumber(newG)
elseif rPend[target] then
transInfo(rPend[target]["add"], rPend[target]["port"], "RegisterComplete", target, newG)
transInfo(rPend[target]["add"], rPend[target]["receiveM"], rPend[target]["port"], "RegisterComplete", target, newG)
rPend[target] = nil
end
end
handler.RegisterNode = function (sender, sPort, origin, nTier, serialTable)
transInfo(firstN["add"], firstN["port"], "RegisterNode", origin, nTier, serialTable)
rPend[origin] = {}
rPend[origin]["add"] = sender
rPend[origin]["port"] = sPort
handler.RegisterNode = function (receiveM, sendM, sPort, origin, nTier, serialTable)
transInfo(firstN["add"], firstN["receiveM"], firstN["port"], "RegisterNode", origin, nTier, serialTable)
rPend[origin] = {["receiveM"]=receiveM, ["add"]=sendM, ["port"] = sPort}
end

handler.RemoveNeighbor = function (sendingModem, port, origination)
handler.RemoveNeighbor = function (receiveM, _, port, origination)
if nodes[origination] then
nodes[origination] = nil
end
transInfo(firstN["add"], firstN["port"], "RemoveNeighbor", origination)
transInfo(firstN["add"], receiveM, firstN["port"], "RemoveNeighbor", origination)
end

handler.RouteOpen = function (sModem, sPort, pktDest, pktOrig, ID)
handler.RouteOpen = function (receiveM, sendM, sPort, pktDest, pktOrig, ID)
if cPend[pktDest..pktOrig] then
sendOK(cPend[pktDest..pktOrig]["bHop"], cPend[pktDest..pktOrig]["port"], pktDest, pktOrig, ID)
storeConnection(pktOrig, ID, pktDest, sModem, sPort)
sendOK(cPend[pktDest..pktOrig]["bHop"], cPend[pktDest..pktOrig]["receiveM"], cPend[pktDest..pktOrig]["port"], pktDest, pktOrig, ID)
storeConnection(pktOrig, ID, pktDest, sendM, receiveM, sPort)
cPend[pktDest..pktOrig] = nil
end
end
local function receivePacket(eventName, receivingModem, sendingModem, port, distance, code, ...)
local function receivePacket(_, receiveM, sendM, port, distance, code, ...)
if handler[code] then
handler[code](sendingModem, port, ...)
handler[code](receiveM, sendM, port, ...)
end
end

------------------------------------------
event.listen("modem_message", receivePacket)
if tunnel then
tunnel.send("NewNode")
if tTable then
for key, value in pairs(tTable) do
tTable[key].send("NewNode")
end
end
if modem then
modem.broadcast(4378, "NewNode")
if mTable then
for key, value in pairs(mTable) do
mTable[key].broadcast(4378, "NewNode")
end
end
os.sleep(2)

-- forward neighbor table up the line
local serialTable = serialize.serialize(nodes)
if serialTable ~= "{}" then
local mncUnavailable = true
local addr = (modem or tunnel).address
transInfo(firstN["add"], firstN["port"], "RegisterNode", addr, tier, serialTable)
local addr
transInfo(firstN["add"], firstN["receiveM"], firstN["port"], "RegisterNode", firstN["receiveM"], tier, serialTable)
waitWithCancel(5, function () return iAdd end)
if not iAdd then
print("Unable to contact the MNC. Functionality will be impaired.")
end
end

if tunnel then
tunnel.send("NewNode", iAdd, tier)
if tTable then
for key, value in pairs(tTable) do
tTable[key].send("NewNode", iAdd, tier)
end
end
if modem then
modem.broadcast(4378, "NewNode", iAdd, tier)
if mTable then
for key, value in pairs(mTable) do
mTable[key].broadcast(4378, "NewNode", iAdd, tier)
end
end

--Listen to computer.shutdown to allow for better network leaves
local function safedown()
for key, value in pairs(connections) do
handler.CloseConnection((modem or tunnel).address, 4378, key)
handler.CloseConnection(_, _, 4378, key)
end
if tunnel then
tunnel.send("RemoveNeighbor", iAdd)
if tTable then
for key, value in pairs(tTable) do
tTable[key].send("RemoveNeighbor", iAdd)
end
if modem then
modem.broadcast(4378, "RemoveNeighbor", iAdd)
end
if mTable then
for key, value in pairs(mTable) do
mTable[key].broadcast(4378, "RemoveNeighbor", iAdd)
end
end
end
event.listen("shutdown", safedown)

-------------------
local function writeData(self, data)
if type(data) ~= "table" or type(data) ~= "function" then
transInfo(self.nextHop, self.outPort, "Data", data, self.outDex, self.order)
if type(data) ~= "table" and type(data) ~= "function" then
transInfo(self.nextHop, self.receiveM, self.outPort, "Data", data, self.outDex, self.order)
self.order=self.order+1
end
end
Expand All @@ -239,30 +264,32 @@ local function readData(self, doPeek)
end

local function closeSock(self)
handler.CloseConnection((modem or tunnel).address, 4378, self.outDex)
handler.CloseConnection(_, _, 4378, self.outDex)
end
function GERTi.openSocket(gAddress, doEvent, outID)
if type(doEvent) ~= "boolean" then
outID = doEvent
end
local port, add
local port, add, receiveM
if not outID then
outID = #connections + 1
end
outID = math.floor(outID)
if nodes[gAddress] then
port = nodes[gAddress]["port"]
add = nodes[gAddress]["add"]
handler.OpenRoute((modem or tunnel).address, 4378, gAddress, nil, iAdd, outID)
receiveM = nodes[gAddress]["receiveM"]
handler.OpenRoute(receiveM, receiveM, 4378, gAddress, nil, iAdd, outID)
else
handler.OpenRoute((modem or tunnel).address, 4378, gAddress, nil, iAdd, outID)
handler.OpenRoute(firstN["receiveM"], firstN["receiveM"], 4378, gAddress, nil, iAdd, outID)
end
waitWithCancel(3, function () return (not cPend[gAddress..iAdd]) end)
if not cPend[gAddress..iAdd] then
local socket = {origination = iAdd,
destination = gAddress,
outPort = port or firstN["port"],
nextHop = add or firstN["add"],
receiveM = receiveM or firstN["receiveM"],
ID = outID,
order = 1,
outDex=iAdd.."|"..gAddress.."|"..outID,
Expand All @@ -276,13 +303,13 @@ function GERTi.openSocket(gAddress, doEvent, outID)
end
end
function GERTi.broadcast(data)
if modem and (type(data) ~= "table" or type(data) ~= "function") then
modem.broadcast(4378, data, -1, iAdd, -1)
if mTable and (type(data) ~= "table" and type(data) ~= "function") then
component.modem.broadcast(4378, "Data", data, -1, 0, iAdd)
end
end
function GERTi.send(dest, data)
if nodes[dest] and (type(data) ~= "table" or type(data) ~= "function") then
transInfo(nodes[dest]["add"], nodes[dest]["port"], "Data", data, -1, 0, iAdd)
if nodes[dest] and (type(data) ~= "table" and type(data) ~= "function") then
transInfo(nodes[dest]["add"], nodes[dest]["receiveM"], nodes[dest]["port"], "Data", data, -1, 0, iAdd)
end
end
function GERTi.getConnections()
Expand All @@ -293,6 +320,7 @@ function GERTi.getConnections()
tempTable[key]["destination"] = value["dest"]
tempTable[key]["ID"] = value["ID"]
tempTable[key]["nextHop"] = value["nextHop"]
tempTable[key]["receiveM"] = value["receiveM"]
tempTable[key]["port"] = value["port"]
tempTable[key]["order"] = value["order"]
end
Expand All @@ -307,6 +335,6 @@ function GERTi.getAddress()
return iAdd
end
function GERTi.getVersion()
return "v1.3", "1.3 Release"
return "v1.4", "1.4"
end
return GERTi
Loading

0 comments on commit 01bc21b

Please sign in to comment.