Files
i-mic-fps/lib/networking/backend/packet_handler.rb
2020-12-02 17:37:48 -06:00

141 lines
4.6 KiB
Ruby

# frozen_string_literal: true
module CyberarmEngine
module Networking
module PacketHandler
def self.type_to_name(type:)
Protocol.constants.select { |const| const.to_s.start_with?("PACKET_") }
.find { |const| Protocol.const_get(const) == type }
end
def self.handle(host:, raw:, peer:)
packet = Packet.decode(raw)
type = packet.message.unpack1("C")
puts "#{host.class} received #{type_to_name(type: type)}"
pp raw
case type
when Protocol::PACKET_CONTROL
handle_control_packet(host, packet, peer)
when Protocol::PACKET_RAW
handle_raw_packet(packet)
when Protocol::PACKET_RELIABLE
handle_reliable_packet(host, packet, peer)
else
raise NotImplementedError, "A Packet handler for #{type_to_name(type: type)}[#{type}] is not implemented!"
end
end
def self.handle_control_packet(host, packet, peer)
pkt = ControlPacket.decode(packet.message)
case pkt.control_type
when Protocol::CONTROL_CONNECT # TOSERVER only
if (peer_id = host.available_peer_id)
peer.id = peer_id
host.peers << peer
peer.write_queue << create_control_packet(peer: peer, control_type: Protocol::CONTROL_SET_PEER_ID, message: [peer_id].pack("n"))
host.peer_connected(peer: peer)
else
host.write(
peer: peer,
packet: PacketHandler.create_control_packet(
peer: peer,
control_type: Protocol::CONTROL_DISCONNECT,
message: "ERROR: max number of clients already connected"
)
)
end
when Protocol::CONTROL_SET_PEER_ID # TOCLIENT only
peer.id = pkt.message.unpack1("n")
host.connected
when Protocol::CONTROL_DISCONNECT
if host.is_a?(Server)
host.peer_disconnected(peer: peer)
else
host.disconnected(reason: pkt.message)
end
when Protocol::CONTROL_HEARTBEAT
when Protocol::CONTROL_PING
peer.write_queue << PacketHandler.create_control_packet(
peer: peer, control_type: Protocol::CONTROL_PONG,
reliable: true,
message: [Networking.milliseconds].pack("Q") # Uint64, native endian
)
when Protocol::CONTROL_PONG
sent_time = pkt.message.unpack1("Q")
difference = Networking.milliseconds - sent_time
peer.ping = difference
end
nil
end
def self.handle_raw_packet(packet)
RawPacket.decode(packet.message)
end
def self.handle_reliable_packet(host, packet, peer)
# TODO: Preserve delivery order of reliable packets
pkt = ReliablePacket.decode(packet.message)
peer.write_queue << create_control_packet(
peer: peer,
control_type: Protocol::CONTROL_ACKNOWLEDGE,
message: [pkt.sequence_number].pack("n")
)
handle(host: host, raw: pkt.message, peer: peer)
end
def self.create_control_packet(peer:, control_type:, message: nil, reliable: false, channel: 0)
message_packet = nil
if reliable
warn "Reliable packets are not yet implemented!"
packet = Packet.new(
protocol_version: Protocol::PROTOCOL_VERSION,
peer_id: peer.id,
channel: channel,
message: ControlPacket.new(control_type: control_type, message: message).encode
)
message_packet = ReliablePacket.new(sequence_number: peer.next_reliable_sequence_number, message: packet.encode)
else
message_packet = ControlPacket.new(control_type: control_type, message: message)
end
Packet.new(
protocol_version: Protocol::PROTOCOL_VERSION,
peer_id: peer.id,
channel: channel,
message: message_packet.encode
)
end
def self.create_raw_packet(peer:, message:, reliable: false, channel: 0)
message_packet = nil
if reliable
warn "Reliable packets are not yet implemented!"
packet = RawPacket.new(message: message)
message_packet = ReliablePacket.new(sequence_number: peer.next_reliable_sequence_number, message: packet.encode)
else
message_packet = RawPacket.new(message: message)
end
Packet.new(
protocol_version: Protocol::PROTOCOL_VERSION,
peer_id: peer.id,
channel: channel,
message: message_packet.encode
)
end
end
end
end