diff --git a/coordinator/coordinator.lua b/coordinator/coordinator.lua index 094bf5b..e6c7671 100644 --- a/coordinator/coordinator.lua +++ b/coordinator/coordinator.lua @@ -520,7 +520,7 @@ function coordinator.comms(version, nic, sv_watchdog) if self.sv_r_seq_num == nil then self.sv_r_seq_num = packet.scada_frame.seq_num() + 1 elseif self.sv_r_seq_num ~= packet.scada_frame.seq_num() then - log.warning("sequence out-of-order: last = " .. self.sv_r_seq_num .. ", new = " .. packet.scada_frame.seq_num()) + log.warning("sequence out-of-order: next = " .. self.sv_r_seq_num .. ", new = " .. packet.scada_frame.seq_num()) return false elseif self.sv_linked and src_addr ~= self.sv_addr then log.debug("received packet from unknown computer " .. src_addr .. " while linked; channel in use by another system?") diff --git a/coordinator/session/pocket.lua b/coordinator/session/pocket.lua index c554c64..5b5e7ce 100644 --- a/coordinator/session/pocket.lua +++ b/coordinator/session/pocket.lua @@ -106,7 +106,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout) local function _handle_packet(pkt) -- check sequence number if self.r_seq_num ~= pkt.scada_frame.seq_num() then - log.warning(log_header .. "sequence out-of-order: last = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num()) + log.warning(log_header .. "sequence out-of-order: next = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num()) return else self.r_seq_num = pkt.scada_frame.seq_num() + 1 @@ -186,6 +186,10 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout) elseif pkt.type == MGMT_TYPE.CLOSE then -- close the session _close() + elseif pkt.type == MGMT_TYPE.ESTABLISH then + -- something is wrong, kill the session + _close() + log.warning(log_header .. "terminated session due to an unexpected ESTABLISH packet") else log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type) end diff --git a/coordinator/startup.lua b/coordinator/startup.lua index cb7d92b..8fb6173 100644 --- a/coordinator/startup.lua +++ b/coordinator/startup.lua @@ -19,7 +19,7 @@ local renderer = require("coordinator.renderer") local sounder = require("coordinator.sounder") local threads = require("coordinator.threads") -local COORDINATOR_VERSION = "v1.5.5" +local COORDINATOR_VERSION = "v1.5.6" local CHUNK_LOAD_DELAY_S = 30.0 diff --git a/pocket/pocket.lua b/pocket/pocket.lua index 5ca6349..dc9fa28 100644 --- a/pocket/pocket.lua +++ b/pocket/pocket.lua @@ -610,7 +610,7 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav) if self.api.r_seq_num == nil then self.api.r_seq_num = packet.scada_frame.seq_num() + 1 elseif self.api.r_seq_num ~= packet.scada_frame.seq_num() then - log.warning("sequence out-of-order (API): last = " .. self.api.r_seq_num .. ", new = " .. packet.scada_frame.seq_num()) + log.warning("sequence out-of-order (API): next = " .. self.api.r_seq_num .. ", new = " .. packet.scada_frame.seq_num()) return elseif self.api.linked and (src_addr ~= self.api.addr) then log.debug("received packet from unknown computer " .. src_addr .. " while linked (API expected " .. self.api.addr .. @@ -697,24 +697,24 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav) else log.debug("received coordinator establish allow without facility configuration") end - elseif est_ack == ESTABLISH_ACK.DENY then - if self.api.last_est_ack ~= est_ack then - log.info("coordinator connection denied") - end - elseif est_ack == ESTABLISH_ACK.COLLISION then - if self.api.last_est_ack ~= est_ack then - log.info("coordinator connection denied due to collision") - end - elseif est_ack == ESTABLISH_ACK.BAD_VERSION then - if self.api.last_est_ack ~= est_ack then - log.info("coordinator comms version mismatch") - end - elseif est_ack == ESTABLISH_ACK.BAD_API_VERSION then - if self.api.last_est_ack ~= est_ack then - log.info("coordinator api version mismatch") - end else - log.debug("coordinator SCADA_MGMT establish packet reply unsupported") + if self.api.last_est_ack ~= est_ack then + if est_ack == ESTABLISH_ACK.DENY then + log.info("coordinator connection denied") + elseif est_ack == ESTABLISH_ACK.COLLISION then + log.info("coordinator connection denied due to collision") + elseif est_ack == ESTABLISH_ACK.BAD_VERSION then + log.info("coordinator comms version mismatch") + elseif est_ack == ESTABLISH_ACK.BAD_API_VERSION then + log.info("coordinator api version mismatch") + else + log.debug("coordinator SCADA_MGMT establish packet reply unsupported") + end + end + + -- unlink + self.api.addr = comms.BROADCAST + self.api.linked = false end self.api.last_est_ack = est_ack @@ -730,7 +730,7 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav) if self.sv.r_seq_num == nil then self.sv.r_seq_num = packet.scada_frame.seq_num() + 1 elseif self.sv.r_seq_num ~= packet.scada_frame.seq_num() then - log.warning("sequence out-of-order (SVR): last = " .. self.sv.r_seq_num .. ", new = " .. packet.scada_frame.seq_num()) + log.warning("sequence out-of-order (SVR): next = " .. self.sv.r_seq_num .. ", new = " .. packet.scada_frame.seq_num()) return elseif self.sv.linked and (src_addr ~= self.sv.addr) then log.debug("received packet from unknown computer " .. src_addr .. " while linked (SVR expected " .. self.sv.addr .. @@ -831,20 +831,22 @@ function pocket.comms(version, nic, sv_watchdog, api_watchdog, nav) else iocontrol.report_link_state(LINK_STATE.SV_LINK_ONLY, self.sv.addr, nil) end - elseif est_ack == ESTABLISH_ACK.DENY then - if self.sv.last_est_ack ~= est_ack then - log.info("supervisor connection denied") - end - elseif est_ack == ESTABLISH_ACK.COLLISION then - if self.sv.last_est_ack ~= est_ack then - log.info("supervisor connection denied due to collision") - end - elseif est_ack == ESTABLISH_ACK.BAD_VERSION then - if self.sv.last_est_ack ~= est_ack then - log.info("supervisor comms version mismatch") - end else - log.debug("supervisor SCADA_MGMT establish packet reply unsupported") + if self.sv.last_est_ack ~= est_ack then + if est_ack == ESTABLISH_ACK.DENY then + log.info("supervisor connection denied") + elseif est_ack == ESTABLISH_ACK.COLLISION then + log.info("supervisor connection denied due to collision") + elseif est_ack == ESTABLISH_ACK.BAD_VERSION then + log.info("supervisor comms version mismatch") + else + log.debug("supervisor SCADA_MGMT establish packet reply unsupported") + end + end + + -- unlink + self.sv.addr = comms.BROADCAST + self.sv.linked = false end self.sv.last_est_ack = est_ack diff --git a/pocket/startup.lua b/pocket/startup.lua index ed3f36f..d548b73 100644 --- a/pocket/startup.lua +++ b/pocket/startup.lua @@ -20,7 +20,7 @@ local pocket = require("pocket.pocket") local renderer = require("pocket.renderer") local threads = require("pocket.threads") -local POCKET_VERSION = "v0.11.6-alpha" +local POCKET_VERSION = "v0.11.7-alpha" local println = util.println local println_ts = util.println_ts diff --git a/reactor-plc/plc.lua b/reactor-plc/plc.lua index 5300bd9..36cb8ed 100644 --- a/reactor-plc/plc.lua +++ b/reactor-plc/plc.lua @@ -833,7 +833,7 @@ function plc.comms(version, nic, reactor, rps, conn_watchdog) if self.r_seq_num == nil then self.r_seq_num = packet.scada_frame.seq_num() + 1 elseif self.r_seq_num ~= packet.scada_frame.seq_num() then - log.warning("sequence out-of-order: last = " .. self.r_seq_num .. ", new = " .. packet.scada_frame.seq_num()) + log.warning("sequence out-of-order: next = " .. self.r_seq_num .. ", new = " .. packet.scada_frame.seq_num()) return elseif self.linked and (src_addr ~= self.sv_addr) then log.debug("received packet from unknown computer " .. src_addr .. " while linked (expected " .. self.sv_addr .. diff --git a/reactor-plc/startup.lua b/reactor-plc/startup.lua index b83f9df..f1cdae2 100644 --- a/reactor-plc/startup.lua +++ b/reactor-plc/startup.lua @@ -18,7 +18,7 @@ local plc = require("reactor-plc.plc") local renderer = require("reactor-plc.renderer") local threads = require("reactor-plc.threads") -local R_PLC_VERSION = "v1.8.5" +local R_PLC_VERSION = "v1.8.6" local println = util.println local println_ts = util.println_ts diff --git a/rtu/rtu.lua b/rtu/rtu.lua index ae09b01..daf9f22 100644 --- a/rtu/rtu.lua +++ b/rtu/rtu.lua @@ -444,7 +444,7 @@ function rtu.comms(version, nic, conn_watchdog) if self.r_seq_num == nil then self.r_seq_num = packet.scada_frame.seq_num() + 1 elseif self.r_seq_num ~= packet.scada_frame.seq_num() then - log.warning("sequence out-of-order: last = " .. self.r_seq_num .. ", new = " .. packet.scada_frame.seq_num()) + log.warning("sequence out-of-order: next = " .. self.r_seq_num .. ", new = " .. packet.scada_frame.seq_num()) return elseif rtu_state.linked and (src_addr ~= self.sv_addr) then log.debug("received packet from unknown computer " .. src_addr .. " while linked (expected " .. self.sv_addr .. diff --git a/rtu/startup.lua b/rtu/startup.lua index cbaada7..b978164 100644 --- a/rtu/startup.lua +++ b/rtu/startup.lua @@ -31,7 +31,7 @@ local sna_rtu = require("rtu.dev.sna_rtu") local sps_rtu = require("rtu.dev.sps_rtu") local turbinev_rtu = require("rtu.dev.turbinev_rtu") -local RTU_VERSION = "v1.10.5" +local RTU_VERSION = "v1.10.6" local RTU_UNIT_TYPE = types.RTU_UNIT_TYPE local RTU_UNIT_HW_STATE = databus.RTU_UNIT_HW_STATE diff --git a/supervisor/session/coordinator.lua b/supervisor/session/coordinator.lua index a135a44..99aa027 100644 --- a/supervisor/session/coordinator.lua +++ b/supervisor/session/coordinator.lua @@ -53,7 +53,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim -- print a log message to the terminal as long as the UI isn't running local function println(message) if not fp_ok then util.println_ts(message) end end - local log_header = "crdn_session(" .. id .. "): " + local log_tag = "crdn_session(" .. id .. "): " local self = { units = facility.get_units(), @@ -184,7 +184,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim local function _handle_packet(pkt) -- check sequence number if self.r_seq_num ~= pkt.scada_frame.seq_num() then - log.warning(log_header .. "sequence out-of-order: last = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num()) + log.warning(log_tag .. "sequence out-of-order: next = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num()) return else self.r_seq_num = pkt.scada_frame.seq_num() + 1 @@ -205,7 +205,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim self.last_rtt = srv_now - srv_start if self.last_rtt > 750 then - log.warning(log_header .. "COORD KEEP_ALIVE round trip time > 750ms (" .. self.last_rtt .. "ms)") + log.warning(log_tag .. "COORD KEEP_ALIVE round trip time > 750ms (" .. self.last_rtt .. "ms)") end -- log.debug(log_header .. "COORD RTT = " .. self.last_rtt .. "ms") @@ -213,13 +213,17 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim databus.tx_crd_rtt(self.last_rtt) else - log.debug(log_header .. "SCADA keep alive packet length mismatch") + log.debug(log_tag .. "SCADA keep alive packet length mismatch") end elseif pkt.type == MGMT_TYPE.CLOSE then -- close the session _close() + elseif pkt.type == MGMT_TYPE.ESTABLISH then + -- something is wrong, kill the session + _close() + log.warning(log_tag .. "terminated session due to an unexpected ESTABLISH packet") else - log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type) + log.debug(log_tag .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type) end elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_CRDN then ---@cast pkt crdn_frame @@ -252,7 +256,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim _send(CRDN_TYPE.FAC_CMD, { cmd, table.unpack(facility.auto_start(config)) }) else - log.debug(log_header .. "CRDN auto start (with configuration) packet length mismatch") + log.debug(log_tag .. "CRDN auto start (with configuration) packet length mismatch") end elseif cmd == FAC_COMMAND.ACK_ALL_ALARMS then facility.ack_all() @@ -261,25 +265,25 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim if pkt.length == 2 then _send(CRDN_TYPE.FAC_CMD, { cmd, facility.set_waste_product(pkt.data[2]) }) else - log.debug(log_header .. "CRDN set waste mode packet length mismatch") + log.debug(log_tag .. "CRDN set waste mode packet length mismatch") end elseif cmd == FAC_COMMAND.SET_PU_FB then if pkt.length == 2 then _send(CRDN_TYPE.FAC_CMD, { cmd, facility.set_pu_fallback(pkt.data[2]) }) else - log.debug(log_header .. "CRDN set pu fallback packet length mismatch") + log.debug(log_tag .. "CRDN set pu fallback packet length mismatch") end elseif cmd == FAC_COMMAND.SET_SPS_LP then if pkt.length == 2 then _send(CRDN_TYPE.FAC_CMD, { cmd, facility.set_sps_low_power(pkt.data[2]) }) else - log.debug(log_header .. "CRDN set sps low power packet length mismatch") + log.debug(log_tag .. "CRDN set sps low power packet length mismatch") end else - log.debug(log_header .. "CRDN facility command unknown") + log.debug(log_tag .. "CRDN facility command unknown") end else - log.debug(log_header .. "CRDN facility command packet length mismatch") + log.debug(log_tag .. "CRDN facility command packet length mismatch") end elseif pkt.type == CRDN_TYPE.UNIT_BUILDS then -- acknowledgement to coordinator receiving builds @@ -307,13 +311,13 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim if pkt.length == 3 then out_queue.push_data(SV_Q_DATA.SET_BURN, data) else - log.debug(log_header .. "CRDN unit command burn rate missing option") + log.debug(log_tag .. "CRDN unit command burn rate missing option") end elseif cmd == UNIT_COMMAND.SET_WASTE then if (pkt.length == 3) and (type(pkt.data[3]) == "number") and (pkt.data[3] > 0) and (pkt.data[3] <= 4) then unit.set_waste_mode(pkt.data[3]) else - log.debug(log_header .. "CRDN unit command set waste missing/invalid option") + log.debug(log_tag .. "CRDN unit command set waste missing/invalid option") end elseif cmd == UNIT_COMMAND.ACK_ALL_ALARMS then unit.ack_all() @@ -322,32 +326,32 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim if pkt.length == 3 then unit.ack_alarm(pkt.data[3]) else - log.debug(log_header .. "CRDN unit command ack alarm missing alarm id") + log.debug(log_tag .. "CRDN unit command ack alarm missing alarm id") end elseif cmd == UNIT_COMMAND.RESET_ALARM then if pkt.length == 3 then unit.reset_alarm(pkt.data[3]) else - log.debug(log_header .. "CRDN unit command reset alarm missing alarm id") + log.debug(log_tag .. "CRDN unit command reset alarm missing alarm id") end elseif cmd == UNIT_COMMAND.SET_GROUP then if (pkt.length == 3) and (type(pkt.data[3]) == "number") and (pkt.data[3] >= 0) and (pkt.data[3] <= 4) then facility.set_group(unit.get_id(), pkt.data[3]) _send(CRDN_TYPE.UNIT_CMD, { cmd, uid, pkt.data[3] }) else - log.debug(log_header .. "CRDN unit command set group missing group id") + log.debug(log_tag .. "CRDN unit command set group missing group id") end else - log.debug(log_header .. "CRDN unit command unknown") + log.debug(log_tag .. "CRDN unit command unknown") end else - log.debug(log_header .. "CRDN unit command invalid") + log.debug(log_tag .. "CRDN unit command invalid") end else - log.debug(log_header .. "CRDN unit command packet length mismatch") + log.debug(log_tag .. "CRDN unit command packet length mismatch") end else - log.debug(log_header .. "handler received unexpected SCADA_CRDN packet type " .. pkt.type) + log.debug(log_tag .. "handler received unexpected SCADA_CRDN packet type " .. pkt.type) end end end @@ -370,7 +374,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim _close() _send_mgmt(MGMT_TYPE.CLOSE, {}) println("connection to coordinator " .. id .. " closed by server") - log.info(log_header .. "session closed by server") + log.info(log_tag .. "session closed by server") end -- iterate the session @@ -437,14 +441,14 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim _send(CRDN_TYPE.FAC_BUILDS, { facility.get_build(cmd.val.type) }) end else - log.error(log_header .. "unsupported data command received in in_queue (this is a bug)", true) + log.error(log_tag .. "unsupported data command received in in_queue (this is a bug)", true) end end end -- max 100ms spent processing queue if util.time() - handle_start > 100 then - log.warning(log_header .. "exceeded 100ms queue process limit") + log.warning(log_tag .. "exceeded 100ms queue process limit") break end end @@ -452,7 +456,7 @@ function coordinator.new_session(id, s_addr, i_seq_num, in_queue, out_queue, tim -- exit if connection was closed if not self.connected then println("connection to coordinator closed by remote host") - log.info(log_header .. "session closed by remote host") + log.info(log_tag .. "session closed by remote host") return self.connected end diff --git a/supervisor/session/plc.lua b/supervisor/session/plc.lua index 301e9b3..f0394e0 100644 --- a/supervisor/session/plc.lua +++ b/supervisor/session/plc.lua @@ -58,7 +58,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, -- print a log message to the terminal as long as the UI isn't running local function println(message) if not fp_ok then util.println_ts(message) end end - local log_header = "plc_session(" .. id .. "): " + local log_tag = "plc_session(" .. id .. "): " local self = { commanded_state = false, @@ -184,7 +184,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, self.sDB.max_op_temp_H2O = max_burn * 2 * (JOULES_PER_MB * heat_cap ^ -1) + BASE_BOIL_TEMP self.sDB.max_op_temp_Na = max_burn * (JOULES_PER_MB * heat_cap ^ -1) + BASE_BOIL_TEMP - log.info(util.sprintf(log_header .. "computed maximum operational temperatures %.3fK (H2O) and %.3fK (Na)", + log.info(util.sprintf(log_tag .. "computed maximum operational temperatures %.3fK (H2O) and %.3fK (Na)", self.sDB.max_op_temp_H2O, self.sDB.max_op_temp_Na)) end @@ -289,12 +289,12 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, _copy_status(pkt.data[7]) self.received_status_cache = true else - log.error(log_header .. "RPLC status packet reactor data length mismatch") + log.error(log_tag .. "RPLC status packet reactor data length mismatch") end end end else - log.debug(log_header .. "RPLC status packet invalid") + log.debug(log_tag .. "RPLC status packet invalid") end end @@ -341,7 +341,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, if pkt.length == 1 then return pkt.data[1] else - log.debug(log_header .. "RPLC ACK length mismatch") + log.debug(log_tag .. "RPLC ACK length mismatch") return nil end end @@ -351,7 +351,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, local function _handle_packet(pkt) -- check sequence number if self.r_seq_num ~= pkt.scada_frame.seq_num() then - log.warning(log_header .. "sequence out-of-order: last = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num()) + log.warning(log_tag .. "sequence out-of-order: next = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num()) return else self.r_seq_num = pkt.scada_frame.seq_num() + 1 @@ -362,7 +362,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, ---@cast pkt rplc_frame -- check reactor ID if pkt.id ~= reactor_id then - log.warning(log_header .. "discarding RPLC packet with ID not matching reactor ID: reactor " .. reactor_id .. " != " .. pkt.id) + log.warning(log_tag .. "discarding RPLC packet with ID not matching reactor ID: reactor " .. reactor_id .. " != " .. pkt.id) return end @@ -375,7 +375,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, if pkt.length >= 5 then _handle_status(pkt) else - log.debug(log_header .. "RPLC status packet length mismatch") + log.debug(log_tag .. "RPLC status packet length mismatch") end elseif pkt.type == RPLC_TYPE.MEK_STRUCT then -- received reactor structure, record it @@ -385,7 +385,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, self.received_struct = true out_queue.push_data(svqtypes.SV_Q_DATA.PLC_BUILD_CHANGED, reactor_id) else - log.debug(log_header .. "RPLC struct packet length mismatch") + log.debug(log_tag .. "RPLC struct packet length mismatch") end elseif pkt.type == RPLC_TYPE.MEK_BURN_RATE then -- burn rate acknowledgement @@ -393,7 +393,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, if ack then self.acks.burn_rate = true elseif ack == false then - log.debug(log_header .. "burn rate update failed!") + log.debug(log_tag .. "burn rate update failed!") end -- send acknowledgement to coordinator @@ -408,7 +408,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, if ack then self.sDB.control_state = true elseif ack == false then - log.debug(log_header .. "enable failed!") + log.debug(log_tag .. "enable failed!") end -- send acknowledgement to coordinator @@ -424,7 +424,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, self.acks.disable = true self.sDB.control_state = false elseif ack == false then - log.debug(log_header .. "disable failed!") + log.debug(log_tag .. "disable failed!") end elseif pkt.type == RPLC_TYPE.RPS_SCRAM then -- manual SCRAM acknowledgement @@ -433,7 +433,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, self.acks.scram = true self.sDB.control_state = false elseif ack == false then - log.debug(log_header .. "manual SCRAM failed!") + log.debug(log_tag .. "manual SCRAM failed!") end -- send acknowledgement to coordinator @@ -449,7 +449,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, self.acks.ascram = true self.sDB.control_state = false elseif ack == false then - log.debug(log_header .. " automatic SCRAM failed!") + log.debug(log_tag .. " automatic SCRAM failed!") end elseif pkt.type == RPLC_TYPE.RPS_STATUS then -- RPS status packet received, copy data @@ -459,10 +459,10 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, -- copied in RPS status data OK else -- error copying RPS status data - log.error(log_header .. "failed to parse RPS status packet data") + log.error(log_tag .. "failed to parse RPS status packet data") end else - log.debug(log_header .. "RPLC RPS status packet length mismatch") + log.debug(log_tag .. "RPLC RPS status packet length mismatch") end elseif pkt.type == RPLC_TYPE.RPS_ALARM then -- RPS alarm @@ -472,10 +472,10 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, -- copied in RPS status data OK else -- error copying RPS status data - log.error(log_header .. "failed to parse RPS alarm status data") + log.error(log_tag .. "failed to parse RPS alarm status data") end else - log.debug(log_header .. "RPLC RPS alarm packet length mismatch") + log.debug(log_tag .. "RPLC RPS alarm packet length mismatch") end elseif pkt.type == RPLC_TYPE.RPS_RESET then -- RPS reset acknowledgement @@ -485,7 +485,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, self.sDB.rps_tripped = false self.sDB.rps_trip_cause = "ok" elseif ack == false then - log.debug(log_header .. "RPS reset failed") + log.debug(log_tag .. "RPS reset failed") end -- send acknowledgement to coordinator @@ -498,7 +498,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, -- RPS auto control reset acknowledgement local ack = _get_ack(pkt) if not ack then - log.debug(log_header .. "RPS auto reset failed") + log.debug(log_tag .. "RPS auto reset failed") end elseif pkt.type == RPLC_TYPE.AUTO_BURN_RATE then if pkt.length == 1 then @@ -506,18 +506,18 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, if ack == PLC_AUTO_ACK.FAIL then self.acks.burn_rate = false - log.debug(log_header .. "RPLC automatic burn rate set fail") + log.debug(log_tag .. "RPLC automatic burn rate set fail") elseif ack == PLC_AUTO_ACK.DIRECT_SET_OK or ack == PLC_AUTO_ACK.RAMP_SET_OK or ack == PLC_AUTO_ACK.ZERO_DIS_OK then self.acks.burn_rate = true else self.acks.burn_rate = false - log.debug(log_header .. "RPLC automatic burn rate ack unknown") + log.debug(log_tag .. "RPLC automatic burn rate ack unknown") end else - log.debug(log_header .. "RPLC automatic burn rate ack packet length mismatch") + log.debug(log_tag .. "RPLC automatic burn rate ack packet length mismatch") end else - log.debug(log_header .. "handler received unsupported RPLC packet type " .. pkt.type) + log.debug(log_tag .. "handler received unsupported RPLC packet type " .. pkt.type) end elseif pkt.scada_frame.protocol() == PROTOCOL.SCADA_MGMT then ---@cast pkt mgmt_frame @@ -530,7 +530,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, self.last_rtt = srv_now - srv_start if self.last_rtt > 750 then - log.warning(log_header .. "PLC KEEP_ALIVE round trip time > 750ms (" .. self.last_rtt .. "ms)") + log.warning(log_tag .. "PLC KEEP_ALIVE round trip time > 750ms (" .. self.last_rtt .. "ms)") end -- log.debug(log_header .. "PLC RTT = " .. self.last_rtt .. "ms") @@ -538,13 +538,17 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, databus.tx_plc_rtt(reactor_id, self.last_rtt) else - log.debug(log_header .. "SCADA keep alive packet length mismatch") + log.debug(log_tag .. "SCADA keep alive packet length mismatch") end elseif pkt.type == MGMT_TYPE.CLOSE then -- close the session _close() + elseif pkt.type == MGMT_TYPE.ESTABLISH then + -- something is wrong, kill the session + _close() + log.warning(log_tag .. "terminated session due to an unexpected ESTABLISH packet") else - log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type) + log.debug(log_tag .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type) end end end @@ -639,7 +643,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, _close() _send_mgmt(MGMT_TYPE.CLOSE, {}) println("connection to reactor " .. reactor_id .. " PLC closed by server") - log.info(log_header .. "session closed by server") + log.info(log_tag .. "session closed by server") end -- iterate the session @@ -696,7 +700,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, _send(RPLC_TYPE.RPS_AUTO_RESET, {}) end else - log.error(log_header .. "unsupported command received in in_queue (this is a bug)", true) + log.error(log_tag .. "unsupported command received in in_queue (this is a bug)", true) end elseif message.qtype == mqueue.TYPE.DATA then -- instruction with body @@ -745,14 +749,14 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, end end else - log.error(log_header .. "unsupported data command received in in_queue (this is a bug)", true) + log.error(log_tag .. "unsupported data command received in in_queue (this is a bug)", true) end end end -- max 100ms spent processing queue if util.time() - handle_start > 100 then - log.warning(log_header .. "exceeded 100ms queue process limit") + log.warning(log_tag .. "exceeded 100ms queue process limit") break end end @@ -760,7 +764,7 @@ function plc.new_session(id, s_addr, i_seq_num, reactor_id, in_queue, out_queue, -- exit if connection was closed if not self.connected then println("connection to reactor " .. reactor_id .. " PLC closed by remote host") - log.info(log_header .. "session closed by remote host") + log.info(log_tag .. "session closed by remote host") return self.connected end diff --git a/supervisor/session/pocket.lua b/supervisor/session/pocket.lua index 94a4467..fc7098e 100644 --- a/supervisor/session/pocket.lua +++ b/supervisor/session/pocket.lua @@ -40,7 +40,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, -- print a log message to the terminal as long as the UI isn't running local function println(message) if not fp_ok then util.println_ts(message) end end - local log_header = "pdg_session(" .. id .. "): " + local log_tag = "pdg_session(" .. id .. "): " local self = { -- connection properties @@ -95,7 +95,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, local function _handle_packet(pkt) -- check sequence number if self.r_seq_num ~= pkt.scada_frame.seq_num() then - log.warning(log_header .. "sequence out-of-order: last = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num()) + log.warning(log_tag .. "sequence out-of-order: next = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num()) return else self.r_seq_num = pkt.scada_frame.seq_num() + 1 @@ -116,7 +116,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, self.last_rtt = srv_now - srv_start if self.last_rtt > 750 then - log.warning(log_header .. "PDG KEEP_ALIVE round trip time > 750ms (" .. self.last_rtt .. "ms)") + log.warning(log_tag .. "PDG KEEP_ALIVE round trip time > 750ms (" .. self.last_rtt .. "ms)") end -- log.debug(log_header .. "PDG RTT = " .. self.last_rtt .. "ms") @@ -124,11 +124,15 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, databus.tx_pdg_rtt(id, self.last_rtt) else - log.debug(log_header .. "SCADA keep alive packet length mismatch") + log.debug(log_tag .. "SCADA keep alive packet length mismatch") end elseif pkt.type == MGMT_TYPE.CLOSE then -- close the session _close() + elseif pkt.type == MGMT_TYPE.ESTABLISH then + -- something is wrong, kill the session + _close() + log.warning(log_tag .. "terminated session due to an unexpected ESTABLISH packet") elseif pkt.type == MGMT_TYPE.DIAG_TONE_GET then -- get the state of alarm tones _send_mgmt(MGMT_TYPE.DIAG_TONE_GET, facility.get_alarm_tones()) @@ -145,13 +149,13 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, local allow_testing, test_tone_states = facility.diag_set_test_tone(pkt.data[1], pkt.data[2]) _send_mgmt(MGMT_TYPE.DIAG_TONE_SET, { allow_testing, test_tone_states }) else - log.debug(log_header .. "SCADA diag tone set packet data type mismatch") + log.debug(log_tag .. "SCADA diag tone set packet data type mismatch") end else - log.debug(log_header .. "SCADA diag tone set packet length mismatch") + log.debug(log_tag .. "SCADA diag tone set packet length mismatch") end else - log.debug(log_header .. "DIAG_TONE_SET is blocked without HMAC for security") + log.debug(log_tag .. "DIAG_TONE_SET is blocked without HMAC for security") end if not valid then _send_mgmt(MGMT_TYPE.DIAG_TONE_SET, { false }) end @@ -168,18 +172,18 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, local allow_testing, test_alarm_states = facility.diag_set_test_alarm(pkt.data[1], pkt.data[2]) _send_mgmt(MGMT_TYPE.DIAG_ALARM_SET, { allow_testing, test_alarm_states }) else - log.debug(log_header .. "SCADA diag alarm set packet data type mismatch") + log.debug(log_tag .. "SCADA diag alarm set packet data type mismatch") end else - log.debug(log_header .. "SCADA diag alarm set packet length mismatch") + log.debug(log_tag .. "SCADA diag alarm set packet length mismatch") end else - log.debug(log_header .. "DIAG_ALARM_SET is blocked without HMAC for security") + log.debug(log_tag .. "DIAG_ALARM_SET is blocked without HMAC for security") end if not valid then _send_mgmt(MGMT_TYPE.DIAG_ALARM_SET, { false }) end else - log.debug(log_header .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type) + log.debug(log_tag .. "handler received unsupported SCADA_MGMT packet type " .. pkt.type) end end end @@ -205,7 +209,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, _close() _send_mgmt(MGMT_TYPE.CLOSE, {}) println("connection to pocket diag session " .. id .. " closed by server") - log.info(log_header .. "session closed by server") + log.info(log_tag .. "session closed by server") end -- iterate the session @@ -236,7 +240,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, -- max 100ms spent processing queue if util.time() - handle_start > 100 then - log.warning(log_header .. "exceeded 100ms queue process limit") + log.warning(log_tag .. "exceeded 100ms queue process limit") break end end @@ -244,7 +248,7 @@ function pocket.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, -- exit if connection was closed if not self.connected then println("connection to pocket diag session " .. id .. " closed by remote host") - log.info(log_header .. "session closed by remote host") + log.info(log_tag .. "session closed by remote host") return self.connected end diff --git a/supervisor/session/rtu.lua b/supervisor/session/rtu.lua index 2a9a339..7d2494a 100644 --- a/supervisor/session/rtu.lua +++ b/supervisor/session/rtu.lua @@ -242,7 +242,7 @@ function rtu.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, ad local function _handle_packet(pkt) -- check sequence number if self.r_seq_num ~= pkt.scada_frame.seq_num() then - log.warning(log_tag .. "sequence out-of-order: last = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num()) + log.warning(log_tag .. "sequence out-of-order: next = " .. self.r_seq_num .. ", new = " .. pkt.scada_frame.seq_num()) return else self.r_seq_num = pkt.scada_frame.seq_num() + 1 @@ -283,6 +283,10 @@ function rtu.new_session(id, s_addr, i_seq_num, in_queue, out_queue, timeout, ad elseif pkt.type == MGMT_TYPE.CLOSE then -- close the session _close() + elseif pkt.type == MGMT_TYPE.ESTABLISH then + -- something is wrong, kill the session + _close() + log.warning(log_tag .. "terminated session due to an unexpected ESTABLISH packet") elseif pkt.type == MGMT_TYPE.RTU_ADVERT then -- RTU advertisement log.debug(log_tag .. "received updated advertisement") diff --git a/supervisor/startup.lua b/supervisor/startup.lua index 9a567ac..a8c0ecb 100644 --- a/supervisor/startup.lua +++ b/supervisor/startup.lua @@ -22,7 +22,7 @@ local supervisor = require("supervisor.supervisor") local svsessions = require("supervisor.session.svsessions") -local SUPERVISOR_VERSION = "v1.5.0" +local SUPERVISOR_VERSION = "v1.5.1" local println = util.println local println_ts = util.println_ts