improve shutdown of host by sending out notice to clients

This commit is contained in:
payonel 2015-09-11 20:58:17 -07:00
parent bdee4aa7a5
commit 3be687ef91
2 changed files with 82 additions and 25 deletions

View File

@ -155,33 +155,37 @@ function modem_host.sendPacket(client, packet)
end end
function modem_host.broadcast(packet) function modem_host.broadcast(packet)
-- only host broadcasts -- we assume packet.target == 0
-- this method will be hit for all broadcasted messages
-- but nonhosting clients will simply not repeat the broadcast
if modem_host.hosting then if modem_host.hosting then
local datagram = modem_host.packetToDatagram(packet)
for addr,client in pairs(modem_host.clients) do for addr,client in pairs(modem_host.clients) do
modem_host.sendDatagram(client, datagram) packet.target = addr
modem_host.sendPacket(client, packet)
end end
-- and self
packet.target = modem_host.id
modem_host.dispatchPacket(packet)
else
-- let host broadcast to all clients
modem_host.sendPacket(modem_host.socket, packet)
end end
end end
function modem_host.validTarget(target) function modem_host.validTarget(target)
if target == 0 then if target == 0 then
return true return true -- broadcast
end end
if target == modem_host.id then if target == modem_host.id then
return true return true -- dispatch will add to machine signals
end end
if not modem_host.hosting then if not modem_host.hosting then
return false return true -- dispatch can handle sending to host
end end
for address,client in pairs(modem_host.clients) do for address,client in pairs(modem_host.clients) do
if address == target then if address == target then
return true return true -- we are hosting and know about this target
end end
end end
@ -201,9 +205,9 @@ end
function modem_host.dispatchPacket(packet) function modem_host.dispatchPacket(packet)
if packet.target == modem_host.id then if packet.target == modem_host.id then
if obj.isOpen(packet.port) then if obj.isOpen(packet.port) then
table.insert(machine.signals, modem_host.packetToPacketArray(packet)) table.insert(machine.signals, modem_host.packetToPacketArray(packet))
end end
elseif modem_host.hosting then -- if hosting we will route elseif modem_host.hosting then -- if hosting we will route
for source,client in pairs(modem_host.clients) do for source,client in pairs(modem_host.clients) do
if source == packet.target then if source == packet.target then
@ -223,27 +227,27 @@ function modem_host.processPendingMessages()
return return
end end
modem_host.acceptPendingClients()
modem_host.recvPendingMessages() modem_host.recvPendingMessages()
for _,packet in pairs(modem_host.messages) do for _,packet in ipairs(modem_host.messages) do
if packet.type == 'modem_message' then if packet.type == 'modem_message' then
-- broadcast if no target -- broadcast if no target
if packet.target == 0 then if packet.target == 0 then
modem_host.broadcast(packet) -- ignored by clients modem_host.broadcast(packet)
else
-- clean up for broadcasting to self modem_host.dispatchPacket(packet)
packet.target = modem_host.id
end end
elseif packet.type == 'host_shutdown' then
modem_host.dispatchPacket(packet) modem_host.host_shutdown = true
end end
end end
modem_host.messages = {} modem_host.messages = {}
end end
function modem_host.recvPendingMessages() function modem_host.acceptPendingClients()
if modem_host.hosting then if modem_host.hosting then
while true do while true do
local client = modem_host.socket:accept() local client = modem_host.socket:accept()
@ -279,8 +283,11 @@ function modem_host.recvPendingMessages()
end end
end end
end end
end
end
-- recv all pending packets function modem_host.recvPendingMessages()
if modem_host.hosting then
for source, client in pairs(modem_host.clients) do for source, client in pairs(modem_host.clients) do
local packet, err = modem_host.readPacket(client) local packet, err = modem_host.readPacket(client)
if packet then if packet then
@ -296,6 +303,13 @@ function modem_host.recvPendingMessages()
if packet then if packet then
modem_host.pushMessage(packet) modem_host.pushMessage(packet)
else else
if err ~= "timeout" then
if not modem_host.host_shutdown then
error("modem host was unexpectedly lost")
end
modem_host.connected = false
modem_host.connectMessageBoard()
end
break break
end end
end end
@ -339,6 +353,15 @@ function modem_host.connectMessageBoard()
return true return true
end end
if modem_host.host_shutdown then
modem_host.socket:close()
end
modem_host.socket = nil
modem_host.clients = {}
modem_host.messages = {}
modem_host.host_shutdown = nil
-- computer address seems to be applied late -- computer address seems to be applied late
if modem_host.id == nil then if modem_host.id == nil then
modem_host.id = component.list("computer",true)() modem_host.id = component.list("computer",true)()
@ -361,12 +384,37 @@ function modem_host.connectMessageBoard()
modem_host.socket:settimeout(0, 't') -- accept calls must be already pending modem_host.socket:settimeout(0, 't') -- accept calls must be already pending
modem_host.connected = true modem_host.connected = true
modem_host.clients = {}
modem_host.messages = {}
return true return true
end end
function modem_host.halt(bReboot)
compCheckArg(1,bReboot,"boolean")
obj.close() -- close all virtual ports
-- if only rebooting, pending messages don't need to be pumped and no one needs to be notified
if modem_host.connected and not bReboot then
if modem_host.hosting then
for addr,csocket in pairs(modem_host.clients) do
local notification = modem_host.createPacketArray("host_shutdown", addr, -1);
modem_host.sendPacketArray(csocket, notification)
end
-- close all client connections
for _,c in pairs(modem_host.clients) do
c:close()
end
modem_host.hosting = false
modem_host.clients = {} -- forget client socket data
end
-- close real port
modem_host.socket:close()
end
end
local wakeMessage local wakeMessage
local strength local strength
if wireless then if wireless then
@ -385,9 +433,15 @@ function obj.send(address, port, ...) -- Sends the specified data to the specifi
compCheckArg(2,port,"number") compCheckArg(2,port,"number")
port=checkPort(port) port=checkPort(port)
-- we cannot send unless we are connected to the message board
if not modem_host.connectMessageBoard() then
return false
end
local packed = modem_host.createPacketArray("modem_message", address, port, ...) local packed = modem_host.createPacketArray("modem_message", address, port, ...)
local packet = modem_host.packetArrayToPacket(packed) local packet = modem_host.packetArrayToPacket(packed)
return modem_host.dispatchPacket(packet) modem_host.pushMessage(packet)
return true
end end
function obj.getWakeMessage() -- Get the current wake-up message. function obj.getWakeMessage() -- Get the current wake-up message.
@ -474,7 +528,8 @@ function obj.broadcast(port, ...) -- Broadcasts the specified data on the specif
local packed = modem_host.createPacketArray("modem_message", 0, port, ...) local packed = modem_host.createPacketArray("modem_message", 0, port, ...)
local packet = modem_host.packetArrayToPacket(packed) local packet = modem_host.packetArrayToPacket(packed)
return modem_host.dispatchPacket(packet) modem_host.pushMessage(packet)
return true
end end
local cec = {} local cec = {}

View File

@ -294,8 +294,10 @@ function resume_thread(...)
machine.deadline = elsa.timer.getTime() + results[2] machine.deadline = elsa.timer.getTime() + results[2]
elseif type(results[2]) == "boolean" then elseif type(results[2]) == "boolean" then
if results[2] then if results[2] then
modem_host.halt(true)
boot_machine() boot_machine()
else else
modem_host.halt(false)
elsa.quit() elsa.quit()
error("Machine power off",0) error("Machine power off",0)
end end