teeworlds_network/lib/packet.rb

78 lines
1.9 KiB
Ruby
Raw Permalink Normal View History

2022-11-05 16:27:13 +00:00
# frozen_string_literal: true
require_relative 'models/net_addr'
require_relative 'models/packet_flags'
2022-11-08 15:20:46 +00:00
2022-10-29 11:17:42 +00:00
require 'huffman_tw'
# Class holding the parsed packet data
class Packet
2022-11-08 15:20:46 +00:00
attr_reader :flags, :payload, :addr
2022-11-12 10:18:12 +00:00
attr_accessor :client_id, :client
2022-10-30 10:18:15 +00:00
def initialize(data, prefix = '')
2022-10-29 11:17:42 +00:00
# @data and @payload
# are strings representing the raw bytes
2022-10-30 10:18:15 +00:00
#
# @prefix is a String that will be displayed
# when printing the packet
# use '>' and '<' for example to indicate
# network direction (client/server)
@prefix = prefix
2022-11-08 15:20:46 +00:00
@addr = NetAddr.new(nil, nil)
2022-10-29 11:17:42 +00:00
@huffman = Huffman.new
@client_id = nil
2022-11-12 10:18:12 +00:00
@client = nil
2022-10-30 10:18:15 +00:00
@data = data
2022-11-05 16:19:05 +00:00
flags_byte = @data[0].unpack('B*')
2022-10-30 18:00:13 +00:00
@flags = PacketFlags.new(flags_byte.first[2..5]).hash
2022-10-30 10:18:15 +00:00
@payload = @data[PACKET_HEADER_SIZE..]
2024-01-20 14:33:25 +00:00
return unless flags_compressed
2022-11-05 16:57:12 +00:00
@payload = @huffman.decompress(@payload.unpack('C*'))
2024-01-22 15:21:50 +00:00
@payload = if @payload.nil?
''
else
@payload.pack('C*')
end
end
def annotate_first_row(bytes)
header = bytes[0..2].join(' ').yellow
token = bytes[3..6].join(' ').green
payload = bytes[7..].join(' ')
2022-10-30 10:18:15 +00:00
puts @prefix + " data: #{[header, token, payload].join(' ')}"
2022-11-05 16:27:13 +00:00
print "#{@prefix} "
2022-11-05 16:19:05 +00:00
print 'header'.ljust(3 * 3, ' ').yellow
print 'token'.ljust(4 * 3, ' ').green
puts 'data'
end
2022-11-05 16:19:05 +00:00
def to_s
2022-11-05 16:27:13 +00:00
puts "#{@prefix}Packet"
2022-10-30 10:18:15 +00:00
puts @prefix + " flags: #{@flags}"
2022-11-05 16:57:12 +00:00
bytes = str_hex(@data).split
2022-11-05 16:19:05 +00:00
# TODO: check terminal size?
max_width = 14
rows = bytes.groups_of(max_width)
annotate_first_row(rows.first)
rows[1..].each do |row|
2022-11-05 16:27:13 +00:00
print "#{@prefix} "
puts row.join(' ')
end
2022-11-05 16:19:05 +00:00
puts ''
end
2022-11-05 16:19:05 +00:00
def flags_compressed
2022-10-29 11:17:42 +00:00
@flags[:compressed]
end
2022-11-05 16:19:05 +00:00
def flags_connless
@flags[:connection] == false
end
2022-11-05 16:19:05 +00:00
def flags_control
@flags[:control]
end
end