2022-11-05 16:27:13 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2022-11-08 15:20:46 +00:00
|
|
|
require_relative 'net_addr'
|
2022-11-11 09:21:48 +00:00
|
|
|
require_relative 'packet_flags'
|
2022-11-08 15:20:46 +00:00
|
|
|
|
2022-10-29 11:17:42 +00:00
|
|
|
require 'huffman_tw'
|
|
|
|
|
2022-10-29 10:09:10 +00:00
|
|
|
# Class holding the parsed packet data
|
|
|
|
class Packet
|
2022-11-08 15:20:46 +00:00
|
|
|
attr_reader :flags, :payload, :addr
|
2022-11-11 09:21:48 +00:00
|
|
|
attr_accessor :client_id
|
2022-10-29 10:09:10 +00:00
|
|
|
|
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
|
2022-11-11 09:21:48 +00:00
|
|
|
@client_id = 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..]
|
2022-11-05 16:57:12 +00:00
|
|
|
return unless flags_compressed
|
|
|
|
|
|
|
|
@payload = @huffman.decompress(@payload.unpack('C*'))
|
|
|
|
@payload = @payload.pack('C*')
|
2022-10-29 10:09:10 +00:00
|
|
|
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'
|
2022-10-29 10:09:10 +00:00
|
|
|
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?
|
2022-10-29 10:09:10 +00:00
|
|
|
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} "
|
2022-10-29 10:09:10 +00:00
|
|
|
puts row.join(' ')
|
|
|
|
end
|
2022-11-05 16:19:05 +00:00
|
|
|
puts ''
|
2022-10-29 10:09:10 +00:00
|
|
|
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
|
2022-10-29 10:09:10 +00:00
|
|
|
@flags[:connection] == false
|
|
|
|
end
|
|
|
|
|
2022-11-05 16:19:05 +00:00
|
|
|
def flags_control
|
2022-10-29 10:09:10 +00:00
|
|
|
@flags[:control]
|
|
|
|
end
|
|
|
|
end
|