From e253a7b4ff72aaa726f75927ff4ea4ba6bb29326 Mon Sep 17 00:00:00 2001 From: Mikayla Fischler Date: Tue, 3 May 2022 17:25:31 -0400 Subject: [PATCH] supervisor PLC session closing, re-requesting status cache if missing --- supervisor/session/plc.lua | 59 +++++++++++++++++++++++-------- supervisor/session/svsessions.lua | 35 +++++++++--------- supervisor/startup.lua | 2 +- 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index b4fbdd9..09aa033 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -7,6 +7,11 @@ local PROTOCOLS = comms.PROTOCOLS local RPLC_TYPES = comms.RPLC_TYPES local SCADA_MGMT_TYPES = comms.SCADA_MGMT_TYPES +local print = util.print +local println = util.println +local print_ts = util.print_ts +local println_ts = util.println_ts + -- retry time constants in ms local INITIAL_WAIT = 1500 local RETRY_PERIOD = 1000 @@ -38,6 +43,7 @@ function new_session(id, for_reactor, in_queue, out_queue) r_seq_num = nil, connected = true, received_struct = false, + received_status_cache = false, plc_conn_watchdog = util.new_watchdog(3), last_rtt = 0, -- periodic messages @@ -48,6 +54,7 @@ function new_session(id, for_reactor, in_queue, out_queue) -- when to next retry one of these requests retry_times = { struct_req = (util.time() + 500), + status_req = (util.time() + 500), scram_req = 0, enable_req = 0, burn_rate_req = 0, @@ -257,6 +264,7 @@ function new_session(id, for_reactor, in_queue, out_queue) local status = pcall(_copy_status, pkt.data[6]) if status then -- copied in status data OK + self.received_status_cache = true else -- error copying status data log._error(log_header .. "failed to parse status packet data") @@ -365,18 +373,6 @@ function new_session(id, for_reactor, in_queue, out_queue) -- get the session database local get_db = function () return self.sDB end - -- close the connection - local close = function () - self.plc_conn_watchdog.cancel() - self.connected = false - _send_mgmt(SCADA_MGMT_TYPES.CLOSE, {}) - end - - -- check if a timer matches this session's watchdog - local check_wd = function (timer) - return timer == self.plc_conn_watchdog.get_timer() - end - -- get the reactor structure local get_struct = function () if self.received_struct then @@ -386,6 +382,29 @@ function new_session(id, for_reactor, in_queue, out_queue) end end + -- get the reactor structure + local get_status = function () + if self.received_status_cache then + return self.sDB.mek_status + else + return nil + end + end + + -- check if a timer matches this session's watchdog + local check_wd = function (timer) + return timer == self.plc_conn_watchdog.get_timer() + end + + -- close the connection + local close = function () + self.plc_conn_watchdog.cancel() + self.connected = false + _send_mgmt(SCADA_MGMT_TYPES.CLOSE, {}) + println("connection to reactor " .. self.for_reactor .. " PLC closed by server") + log._info(log_header .. "session closed by server") + end + -- iterate the session local iterate = function () if self.connected then @@ -442,6 +461,8 @@ function new_session(id, for_reactor, in_queue, out_queue) -- exit if connection was closed if not self.connected then + self.plc_conn_watchdog.cancel() + println("connection to reactor " .. self.for_reactor .. " PLC closed by remote host") log._info(log_header .. "session closed by remote host") return self.connected end @@ -479,6 +500,15 @@ function new_session(id, for_reactor, in_queue, out_queue) end end + -- status cache request retry + + if not self.received_status_cache then + if rtimes.status_req - util.time() <= 0 then + _send(RPLC_TYPES.MEK_STATUS, {}) + rtimes.status_req = util.time() + RETRY_PERIOD + end + end + -- SCRAM request retry if not self.acks.scram then @@ -522,9 +552,10 @@ function new_session(id, for_reactor, in_queue, out_queue) return { get_id = get_id, get_db = get_db, - close = close, - check_wd = check_wd, get_struct = get_struct, + get_status = get_status, + check_wd = check_wd, + close = close, iterate = iterate } end diff --git a/supervisor/session/svsessions.lua b/supervisor/session/svsessions.lua index c111093..6612730 100644 --- a/supervisor/session/svsessions.lua +++ b/supervisor/session/svsessions.lua @@ -91,6 +91,22 @@ function establish_plc_session(local_port, remote_port, for_reactor) end end +-- cleanly close a session +local function _shutdown(session) + session.open = false + session.instance.close() + + -- send packets in out queue (namely the close packet) + while session.out_queue.ready() do + local msg = session.out_queue.pop() + if msg.qtype == mqueue.TYPE.PACKET then + self.modem.transmit(session.r_port, session.l_port, msg.message.raw_sendable()) + end + end + + log._debug("closed session " .. session.instance.get_id() .. " on remote port " .. session.r_port) +end + -- check if a watchdog timer event matches that of one of the provided sessions local function _check_watchdogs(sessions, timer_event) for i = 1, #sessions do @@ -98,9 +114,8 @@ local function _check_watchdogs(sessions, timer_event) if session.open then local triggered = session.instance.check_wd(timer_event) if triggered then - log._debug("watchdog closing session " .. session.instance.get_id() .. " on remote port " .. session.r_port) - session.open = false - session.instance.close() + log._debug("watchdog closing session " .. session.instance.get_id() .. " on remote port " .. session.r_port .. "...") + _shutdown(session) end end end @@ -134,7 +149,6 @@ local function _iterate(sessions) end else session.open = false - session.instance.close() end end end @@ -189,18 +203,7 @@ local function _close(sessions) for i = 1, #sessions do local session = sessions[i] if session.open then - session.open = false - session.instance.close() - - -- send packets in out queue (namely the close packet) - while session.out_queue.ready() do - local msg = session.out_queue.pop() - if msg.qtype == mqueue.TYPE.PACKET then - self.modem.transmit(session.r_port, session.l_port, msg.message.raw_sendable()) - end - end - - log._debug("closed session " .. session.instance.get_id() .. " on remote port " .. session.r_port) + _shutdown(session) end end end diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 8d174d4..53f6cfc 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -18,7 +18,7 @@ os.loadAPI("session/svsessions.lua") os.loadAPI("supervisor.lua") -local SUPERVISOR_VERSION = "alpha-v0.1.12" +local SUPERVISOR_VERSION = "alpha-v0.2.0" local print = util.print local println = util.println