You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
4.2 KiB

-- For testing
modem = require("modem")
-- For deployment
-- modem = require("component").modem
serializer = require("serialization")
Queue = {first = 0, last = -1}
function Queue:new()
local o = {}
setmetatable(o, self)
self.__index = self
return o
end
function Queue:insert(value)
local last = self.last + 1
self.last = last
self[last] = value
end
function Queue:isempty()
return self.first > self.last
end
function Queue:remove()
local first = self.first
if self:isempty() then
error("Queue is empty")
end
local value = self[first]
self[first] = nil
self.first = first + 1
return value
end
message_type = {
request_noun = 1,
call_verb = 2,
noun_response = 3,
hello = 4,
goodbye = 5,
hello_response = 6,
}
CFG_PORT = 1234
bc = {}
function bc:init(my_address, local_nouns, local_verbs)
local o = {}
setmetatable(o, self)
self.__index = self
o.queue = Queue:new()
o.remote_verbs = {}
o.remote_nouns = {}
-- Modem listener
function modem_listener(localAddress, remoteAddress, port, dist, message)
dbg = message
message = serializer.unserialize(message)
if port == CFG_PORT then
if message.ty == message_type.request_noun then
msg = {ty=message_type.noun_response,
noun=message.noun,
value=o.local_nouns[message.noun]
}
o.modem:send(remoteAddress, port, serializer.serialize(msg))
elseif message.ty == message_type.noun_response then
-- TODO: Make this a bit better, this is dumb
o._nr = message.value
elseif message.ty == message_type.call_verb then
o.local_verbs[message.verb](o, message.param)
elseif message.ty == message_type.hello then
for i,verb in ipairs(message.verbs) do
o.remote_verbs[verb] = remoteAddress
end
for i,noun in ipairs(message.nouns) do
o.remote_nouns[noun] = remoteAddress
end
-- Respond with own verbs and nouns
local mynouns = {}
for noun in pairs(o.local_nouns) do
table.insert(mynouns, noun)
end
local myverbs = {}
for verb in pairs(o.local_verbs) do
table.insert(myverbs, verb)
end
o.modem:send(remoteAddress, port, serializer.serialize({ty=message_type.hello_response, verbs=myverbs, nouns=mynouns}))
elseif message.ty == message_type.hello_response then
for i,verb in ipairs(message.verbs) do
o.remote_verbs[verb] = remoteAddress
end
for i,noun in ipairs(message.nouns) do
o.remote_nouns[noun] = remoteAddress
end
end
end
end
-- Change this for deployment VVV
o.modem = modem:init(my_address, modem_listener)
-- Init local stuff
o.local_verbs = local_verbs
o.local_nouns = local_nouns
-- Send own nouns and verbs and request all remotes to send theirs
local mynouns = {}
for noun in pairs(local_nouns) do
table.insert(mynouns, noun)
end
local myverbs = {}
for verb in pairs(local_verbs) do
table.insert(myverbs, verb)
end
o.modem:broadcast(CFG_PORT, serializer.serialize({ty=message_type.hello, verbs=myverbs, nouns=mynouns}))
return o
end
function bc:get_noun(n)
if self.local_nouns[n] ~= nil then -- This noun is local, makes it easy
return self.local_nouns[n]
elseif self.remote_nouns[n] ~= nil then -- This noun is remote
self.modem:send(self.remote_nouns[n], CFG_PORT, serializer.serialize({ty=message_type.request_noun, noun=n}))
while self._nr == nil do
-- Nothing, wait for response, TODO: Research performance impact
end
local value = self._nr
self._nr = nil -- Reset
return value
else
error("Noun not found, Node might be offline")
end
end
function bc:set_noun(n, value)
if self.local_nouns[n] ~= nil then
self.local_nouns[n] = value
else
error("Can't set remote nouns")
end
end
function bc:call_verb(v, param)
if self.local_verbs[v] ~= nil then
self.local_verbs[v](self, param)
elseif self.remote_verbs[v] ~= nil then
self.modem:send(self.remote_verbs[v], CFG_PORT, serializer.serialize({ty=message_type.call_verb, verb=v, param=param}))
else
error("Verb not found, Node might be offline")
end
end
return bc