chore: init base

This commit is contained in:
Guillaume ARM 2022-07-15 10:25:29 +02:00
commit 9c0f7a79dc
5 changed files with 314 additions and 0 deletions

139
apis/net.lua Normal file
View File

@ -0,0 +1,139 @@
-- Network API v1.0.1
local DEFAULT_TIMEOUT_WAIT_MESSAGE = 0.5; -- in seconds
local DEFAULT_ROUTING_CHANNEL = 10;
-- Utilitaire pour savoir si un payload nous est destiné.
-- le parametre 'payload' est une table avec les champs suivants:
-- - sourceId: l'id de la machine qui a envoyé le message
-- - destId: l'id du destinataire, si l'id est nil le message est routé a tout le monde
-- - routerId: l'id du routeur qui s'est occupé de transmettre le message
-- - message: le contenu du message (qui sera le plus souvent une table)
-- return un boolean
local function isPayloadOk(payload)
if type(payload) ~= "table" then
return false;
end
if not payload.routerId or not payload.sourceId then
return false;
end
if payload.sourceId == os.getComputerID() then
return false;
end
if payload.destId == nil then
return true;
end
if type(payload.destId) == 'number' and payload.destId == os.getComputerID() then
return true;
end
if type(payload.destId) == 'string' and payload.destId == os.getComputerLabel() then
return true;
end
return false;
end
-- Une simple fonction pour chercher une valeur dans une table
local function find(predicate, values)
for k, v in ipairs(values) do
if predicate(v, k) then
return v;
end
end
return nil;
end
-- Fonction utilitaire pour pouvoir pull plusieurs events (modem_message et timer par exemple)
local function pullMultipleEvents(...)
local eventNames = table.pack(...);
while true do
local payload = table.pack(os.pullEvent());
local eventName = payload[1]
-- TODO index events
if find(function(e) return e == eventName end, eventNames) then
return table.unpack(payload);
end
end
end
-- -- Example: implementation simple de ping
--
--
-- local createNet = require('apis/net');
-- net = createNet();
--
-- -- envoyer un message sur le canal 9
-- net.send(9, 'ping');
--
-- -- recevoir et afficher un message sur le canal 9
-- local message = net.waitMessage(9);
-- if message == 'pong' then
-- print('pong recu');
-- end
--
local function createNetwork(modem, routingChannel, timeoutInSec)
modem = modem or peripheral.find("modem") or error("modem not found");
routingChannel = routingChannel or DEFAULT_ROUTING_CHANNEL;
timeoutInSec = timeoutInSec or DEFAULT_TIMEOUT_WAIT_MESSAGE;
-- net.send function
local function send(channel, message, destId)
local payload = {
sourceId = os.getComputerID(),
sourceLabel = os.getComputerLabel(),
routerId = nil,
destId = destId,
message = message
}
modem.transmit(routingChannel, channel, payload);
end
-- net.waitMessage function
local function waitMessage(channelToListen)
local receivedPayload;
modem.open(channelToListen);
local timerId = os.startTimer(timeoutInSec);
local timedOut = false;
repeat
local messageType, timerIdOrSide, channel, _, payload = pullMultipleEvents("modem_message", "timer");
local channelOk, payloadOk;
if messageType == "modem_message" then
receivedPayload = payload;
channelOk = channel == channelToListen;
payloadOk = isPayloadOk(payload);
elseif messageType == 'timer' and timerIdOrSide == timerId then
timedOut = true;
end
until channelOk and payloadOk or timedOut
if timedOut then
return nil;
end
if receivedPayload then
return receivedPayload.message, receivedPayload;
end
return nil;
end
return {
send = send,
waitMessage = waitMessage
}
end
return createNetwork;

30
ping-server.lua Normal file
View File

@ -0,0 +1,30 @@
-- ping-server v1.0.0
-- -- Example: implementation simple de ping-server
local PING_CHANNEL = 9;
local MODEM_DETECTION_TIME = 3; -- in seconds
local createNet = require('apis/net');
local modem = peripheral.find('modem');
if not modem then
print("Warning: modem not found!");
end
-- on attend le modem
while not modem do
modem = peripheral.find('modem');
os.sleep(MODEM_DETECTION_TIME);
end
local net = createNet(modem);
while true do
local message, payload = net.waitMessage(PING_CHANNEL);
if message == 'ping' then
-- le troisième parametre de la fonction `net.send` est pour router un message a une machine specifique
net.send(PING_CHANNEL, 'pong', payload.sourceId);
end
end

33
ping.lua Normal file
View File

@ -0,0 +1,33 @@
-- ping v1.2.0
local PING_CHANNEL = 9;
local createNet = require('apis/net');
local net = createNet();
local args = table.pack(...);
local targetComputerId = tonumber(args[1]) or args[1];
local sourceId = os.getComputerID()
local sourceLabel = os.getComputerLabel();
-- gérer les pongs locales
if targetComputerId == nil or targetComputerId == sourceId or targetComputerId == sourceLabel then
print("=> local pong from " .. tostring(sourceId)
.. (sourceLabel and " (label=" .. tostring(sourceLabel) .. ")" or ""));
end
-- envoyer un message sur le canal 9 à la machine cible
net.send(PING_CHANNEL, "ping", targetComputerId);
-- recevoir et afficher un message sur le canal 9
while true do
local message, payload = net.waitMessage(PING_CHANNEL);
if message == "pong" then
print("=> pong from " .. tostring(payload.sourceId)
.. (payload.sourceLabel and " (label=" .. tostring(payload.sourceLabel) .. ")" or ""));
elseif message == nil then
break
end
end

71
router.lua Normal file
View File

@ -0,0 +1,71 @@
-- router v1.1.0
local ROUTER_CHANNEL = 10;
local VERBOSE = true;
local modem = peripheral.find("modem") or error("modem not found");
modem.open(ROUTER_CHANNEL);
local routerId = os.getComputerID();
local function isPingForServer(payload)
if payload.message ~= 'ping' then
return false;
end
if payload.destId == routerId or payload.destId == os.getComputerLabel() then
return true;
end
if payload.destId == nil then
return true;
end
return false;
end
while true do
local channel, replyChannel, payload, pingForServer;
repeat
_, _, channel, replyChannel, payload = os.pullEvent("modem_message");
pingForServer = isPingForServer(payload)
local channelOk = channel == ROUTER_CHANNEL;
local payloadOk = type(payload) == 'table' and not payload.routerId or pingForServer;
local loopFinished = channelOk and payloadOk;
until loopFinished
if payload and not payload.routerId then
if pingForServer then
local responseRouterPayload = {
sourceId = os.getComputerID(),
sourceLabel = os.getComputerLabel(),
routerId = routerId,
destId = payload.sourceId,
message = 'pong'
}
modem.transmit(replyChannel, replyChannel, responseRouterPayload)
end
if not pingForServer or payload.destId == nil then
payload.routerId = routerId;
modem.transmit(replyChannel, replyChannel, payload);
end
end
if VERBOSE then
if payload.destId then
if pingForServer then
print('ping for server received!');
else
print("Routed message from " .. tostring(payload.sourceId)
.. " to " .. tostring(payload.destId)
.. " using channel " .. tostring(replyChannel));
end
else
print("Broadcasted message from " .. tostring(payload.sourceId)
.. " using channel " .. tostring(replyChannel));
end
end
end

41
startup/servers.lua Normal file
View File

@ -0,0 +1,41 @@
-- Server Launcher v1.0.0
local SERVERS = {
"ping-server",
};
local function shellFn()
os.sleep(0.1);
shell.run("shell");
end
local function getServerFns(serverList)
local servers = {};
for k, v in ipairs(serverList) do
local serverName = serverList[k];
servers[k] = function()
if serverName then
shell.run(serverName);
end
end
end
return servers;
end
local servers = getServerFns(SERVERS);
print("\nStarting servers...");
for _, v in ipairs(SERVERS) do
print("\t\t" .. v)
end
parallel.waitForAny(shellFn, table.unpack(servers));
print("Servers stopped, reboot the machine...");
os.sleep(1);
os.reboot();