Files
timecrafters_configuration_…/lib/tacnet/packet_handler.rb

232 lines
7.9 KiB
Ruby

module TAC
class TACNET
class PacketHandler
TAG = "TACNET|PacketHandler"
def initialize(host_is_a_connection: false)
@host_is_a_connection = host_is_a_connection
end
def handle(message)
packet = Packet.from_stream(message)
if packet
log.i(TAG, "Received packet of type: #{packet.type}")
hand_off(packet)
else
log.d(TAG, "Rejected raw packet: #{message}")
end
end
def hand_off(packet)
case packet.type
when :handshake
handle_handshake(packet)
when :heartbeat
handle_heartbeat(packet)
when :error
handle_error(packet)
when :download_config
handle_download_config(packet)
when :upload_config
handle_upload_config(packet)
when :list_configs
handle_list_configs(packet)
when :select_config
handle_select_config(packet)
when :add_config
handle_add_config(packet)
when :update_config # rename config/file
handle_update_config(packet)
when :delete_config
handle_delete_config(packet)
else
log.d(TAG, "No hand off available for packet type: #{packet.type}")
end
end
def handle_handshake(packet)
if @host_is_a_connection
CyberarmEngine::Window.instance.backend.tacnet.client.uuid = packet.body
end
end
# TODO: Reset socket timeout
def handle_heartbeat(packet)
end
# TODO: Handle errors
def handle_error(packet)
if @host_is_a_connection
title, message = packet.body.split(Packet::PROTOCOL_SEPERATOR, 2)
CyberarmEngine::Window.instance.push_state(TAC::Dialog::TACNETDialog, title: title, message: message)
else
log.e(TAG, "Remote error: #{title}: #{message}")
end
end
def handle_upload_config(packet)
begin
config_name, json = packet.body.split(Packet::PROTOCOL_SEPERATOR, 2)
data = JSON.parse(json, symbolize_names: true)
if data.is_a?(Hash) && data.dig(:config, :spec_version) == TAC::CONFIG_SPEC_VERSION
File.open("#{TAC::CONFIGS_PATH}/#{config_name}.json", "w") { |f| f.write json }
if CyberarmEngine::Window.instance.backend.config&.name == config_name
CyberarmEngine::Window.instance.backend.load_config(config_name)
end
else
CyberarmEngine::Window.instance.push_state(TAC::Dialog::AlertDialog, title: "Invalid Config", message: "Supported config spec: v#{TAC::CONFIG_SPEC_VERSION} got v#{data.dig(:config, :spec_version)}")
end
rescue JSON::ParserError => e
log.e(TAG, "JSON parsing error: #{e}")
end
end
def handle_download_config(packet)
config_name = packet.body
log.i(TAG, config_name)
pkt = nil
if File.exist?("#{TAC::CONFIGS_PATH}/#{config_name}.json")
pkt = PacketHandler.packet_upload_config(config_name, Config.new(config_name).to_json)
else
pkt = PacketHandler.packet_error("Remote config not found", "The requested config #{config_name} does not exist over here.")
end
if @host_is_a_connection
CyberarmEngine::Window.instance.backend.tacnet.puts(pkt)
else
$server.active_client.puts(pkt)
end
end
def handle_list_configs(packet)
if @host_is_a_connection # Download new or updated configs
list = packet.body.split(Packet::PROTOCOL_SEPERATOR).map { |part| part.split(",") }
remote_configs = list.map { |l| l.first }
local_configs = Dir.glob("#{TAC::CONFIGS_PATH}/*.json").map { |f| File.basename(f, ".json") }
_diff = local_configs - remote_configs
list.each do |name, revision|
revision = Integer(revision)
path = "#{TAC::CONFIGS_PATH}/#{name}.json"
if File.exist?(path)
config = Config.new(name)
if config.configuration.revision < revision
CyberarmEngine::Window.instance.backend.tacnet.puts( PacketHandler.packet_download_config(name) )
elsif config.configuration.revision > revision
CyberarmEngine::Window.instance.backend.tacnet.puts( PacketHandler.packet_upload_config(name, JSON.dump( config )) )
end
else
CyberarmEngine::Window.instance.backend.tacnet.puts( PacketHandler.packet_download_config(name) )
end
end
_diff.each do |name|
config = Config.new(name)
CyberarmEngine::Window.instance.backend.tacnet.puts( PacketHandler.packet_upload_config(name, JSON.dump( config )) )
end
else
if $server.active_client && $server.active_client.connected?
$server.active_client.puts(PacketHandler.packet_list_configs)
end
end
end
def handle_select_config(packet)
config_name = packet.body
CyberarmEngine::Window.instance.backend.settings.config = config_name
CyberarmEngine::Window.instance.backend.save_settings
CyberarmEngine::Window.instance.backend.load_config(config_name)
end
def handle_add_config(packet)
config_name = packet.body
if CyberarmEngine::Window.instance.backend.configs_list.include?(config_name)
unless @host_is_a_connection
if $server.active_client&.connected?
$server.active_client.puts(PacketHandler.packet_error("Config already exists!", "A config with the name #{config_name} already exists over here."))
end
end
else
CyberarmEngine::Window.instance.backend.write_new_config(config_name)
end
end
def handle_update_config(packet)
old_config_name, new_config_name = packet.body.split(PROTOCOL_SEPERATOR, 2)
if CyberarmEngine::Window.instance.backend.configs_list.include?(config_name)
unless @host_is_a_connection
if $server.active_client&.connected?
$server.active_client.puts(PacketHandler.packet_error("Config already exists!", "A config with the name #{config_name} already exists over here."))
end
end
else
CyberarmEngine::Window.instance.backend.move_config(old_config_name, new_config_name)
end
end
def handle_delete_config(packet)
config_name = packet.body
CyberarmEngine::Window.instance.backend.delete_config(config_name)
end
def self.packet_handshake(client_uuid)
Packet.create(Packet::PACKET_TYPES[:handshake], client_uuid)
end
def self.packet_heartbeat
Packet.create(Packet::PACKET_TYPES[:heartbeat], Packet::PROTOCOL_HEARTBEAT)
end
def self.packet_error(error_code, message)
Packet.create(Packet::PACKET_TYPES[:error], error_code.to_s, message.to_s)
end
def self.packet_download_config(config_name)
Packet.create(Packet::PACKET_TYPES[:download_config], "#{config_name}")
end
def self.packet_upload_config(config_name, json)
string = "#{config_name}#{Packet::PROTOCOL_SEPERATOR}#{json.gsub("\n", " ")}"
Packet.create(Packet::PACKET_TYPES[:upload_config], string)
end
def self.packet_list_configs
files = Dir.glob("#{TAC::CONFIGS_PATH}/*.json")
list = files.map do |file|
name = File.basename(file, ".json")
config = Config.new(name)
"#{name},#{config.configuration.revision}"
end.join(Packet::PROTOCOL_SEPERATOR)
Packet.create(
Packet::PACKET_TYPES[:list_configs],
list
)
end
def self.packet_select_config(config_name)
Packet.create(Packet::PACKET_TYPES[:select_config], config_name)
end
def self.packet_delete_config(config_name)
Packet.create(Packet::PACKET_TYPES[:delete_config], config_name)
end
end
end
end