Reach old connection state with less hacks
This commit is contained in:
parent
d68be4eb68
commit
4544bb3e1a
99
lib/chunk.rb
Normal file
99
lib/chunk.rb
Normal file
|
@ -0,0 +1,99 @@
|
|||
require_relative 'array'
|
||||
require_relative 'network'
|
||||
require_relative 'bytes'
|
||||
|
||||
class NetChunk
|
||||
attr_reader :next, :data, :msg, :sys
|
||||
|
||||
def initialize(data)
|
||||
@next = nil
|
||||
@flags = {}
|
||||
@size = 0
|
||||
parse_header(data[0..2])
|
||||
chunk_end = CHUNK_HEADER_SIZE + @size
|
||||
# puts "data[0]: " + str_hex(data[0])
|
||||
@data = data[CHUNK_HEADER_SIZE...chunk_end]
|
||||
@msg = @data[0].unpack("C*").first
|
||||
@sys = @msg & 1 == 1 ? true : false
|
||||
@msg >>= 1
|
||||
@next = data[chunk_end..] if data.size > chunk_end
|
||||
end
|
||||
|
||||
def parse_header(data)
|
||||
# flags
|
||||
flags = data[0].unpack("B*").first
|
||||
flags = flags[0..1]
|
||||
@flags[:resend] = flags[0] == "1"
|
||||
@flags[:vital] = flags[1] == "1"
|
||||
|
||||
# size
|
||||
size = data[0..1].unpack("B*").first
|
||||
size_bytes = size.chars.groups_of(8)
|
||||
# trim first 2 bits of both bytes
|
||||
# Size: 2 bytes (..00 0000 ..00 0010)
|
||||
size_bytes.map! {|b| b[2..].join('') }
|
||||
@size = size_bytes.join('').to_i(2)
|
||||
|
||||
# sequence number
|
||||
# in da third byte but who needs seq?!
|
||||
end
|
||||
end
|
||||
|
||||
MAX_NUM_CHUNKS = 1024
|
||||
|
||||
class BigChungusTheChunkGetter
|
||||
def self.get_chunks(data)
|
||||
chunks = []
|
||||
chunk = NetChunk.new(data)
|
||||
chunks.push(chunk)
|
||||
while chunk.next
|
||||
chunk = NetChunk.new(chunk.next)
|
||||
chunks.push(chunk)
|
||||
if chunks.size > MAX_NUM_CHUNKS
|
||||
# inf loop guard case
|
||||
puts "Warning: abort due to max num chunks bein reached"
|
||||
break
|
||||
end
|
||||
end
|
||||
chunks
|
||||
end
|
||||
end
|
||||
|
||||
def todo_make_this_an_rspec_test
|
||||
# handcrafted fake packet
|
||||
# two empty motd chunks
|
||||
data = [
|
||||
0x40, 0x02, 0x02, 0x02, 0x00,
|
||||
0x40, 0x02, 0x02, 0x02, 0x00
|
||||
].pack("C*")
|
||||
chunks = BigChungusTheChunkGetter.get_chunks(data)
|
||||
p chunks.size == 2
|
||||
p chunks[0].msg == NETMSGTYPE_SV_MOTD
|
||||
p chunks[1].msg == NETMSGTYPE_SV_MOTD
|
||||
p chunks[0].sys == false
|
||||
|
||||
# actual packet server sends
|
||||
data = [
|
||||
0x40, 0x02, 0x02, 0x02, 0x00, # motd
|
||||
0x40, 0x07, 0x03, 0x22, 0x01, 0x00, 0x01, 0x00, 0x01, 0x08, # server settings
|
||||
0x40, 0x01, 0x04, 0x0b # ready
|
||||
].pack("C*")
|
||||
chunks = BigChungusTheChunkGetter.get_chunks(data)
|
||||
p chunks.size == 3
|
||||
p chunks[0].msg == NETMSGTYPE_SV_MOTD
|
||||
p chunks[1].msg == NETMSGTYPE_SV_SERVERSETTINGS
|
||||
|
||||
# actual mapchange the server sends
|
||||
map_change = [
|
||||
0x40, 0x32, 0x01, 0x05, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x00,
|
||||
0xee, 0xcb, 0xd0, 0xd7, 0x02, 0x9c, 0x0e, 0x08, 0xa8, 0x15, 0x1a, 0xb3, 0xbb, 0xb1, 0xd4, 0x04,
|
||||
0x75, 0x68, 0xec, 0xe3, 0x41, 0x6e, 0x83, 0x20, 0xaf, 0x97, 0x0f, 0x49, 0xbe, 0x4f, 0x3c, 0x61,
|
||||
0x04, 0xf4, 0xbe, 0x60, 0xd2, 0x87, 0x39, 0x91, 0x59, 0xab
|
||||
].pack("C*")
|
||||
chunks = BigChungusTheChunkGetter.get_chunks(map_change)
|
||||
p chunks.size == 1
|
||||
p chunks[0].sys == true
|
||||
end
|
||||
|
||||
# todo_make_this_an_rspec_test
|
||||
|
|
@ -31,6 +31,48 @@ NETMSG_RCON_LINE = 13 # line that should be printed to the remote console
|
|||
NETMSG_RCON_CMD_ADD = 14
|
||||
NETMSG_RCON_CMD_REM = 15
|
||||
|
||||
NETMSG_INVALID = 0
|
||||
NETMSGTYPE_SV_MOTD = 1
|
||||
NETMSGTYPE_SV_BROADCAST = 2
|
||||
NETMSGTYPE_SV_CHAT = 3
|
||||
NETMSGTYPE_SV_TEAM = 4
|
||||
NETMSGTYPE_SV_KILLMSG = 5
|
||||
NETMSGTYPE_SV_TUNEPARAMS = 6
|
||||
NETMSGTYPE_SV_EXTRAPROJECTILE = 7
|
||||
NETMSGTYPE_SV_READYTOENTER = 8
|
||||
NETMSGTYPE_SV_WEAPONPICKUP = 19
|
||||
NETMSGTYPE_SV_EMOTICON = 10
|
||||
NETMSGTYPE_SV_VOTECLEAROPTIONS = 11
|
||||
NETMSGTYPE_SV_VOTEOPTIONLISTADD = 12
|
||||
NETMSGTYPE_SV_VOTEOPTIONADD = 13
|
||||
NETMSGTYPE_SV_VOTEOPTIONREMOVE = 14
|
||||
NETMSGTYPE_SV_VOTESET = 15
|
||||
NETMSGTYPE_SV_VOTESTATUS = 16
|
||||
NETMSGTYPE_SV_SERVERSETTINGS = 17
|
||||
NETMSGTYPE_SV_CLIENTINFO = 18
|
||||
NETMSGTYPE_SV_GAMEINFO = 19
|
||||
NETMSGTYPE_SV_CLIENTDROP = 20
|
||||
NETMSGTYPE_SV_GAMEMSG = 21
|
||||
NETMSGTYPE_DE_CLIENTENTER = 22
|
||||
NETMSGTYPE_DE_CLIENTLEAVE = 23
|
||||
NETMSGTYPE_CL_SAY = 24
|
||||
NETMSGTYPE_CL_SETTEAM = 25
|
||||
NETMSGTYPE_CL_SETSPECTATORMODE = 26
|
||||
NETMSGTYPE_CL_STARTINFO = 27
|
||||
NETMSGTYPE_CL_KILL = 28
|
||||
NETMSGTYPE_CL_READYCHANGE = 29
|
||||
NETMSGTYPE_CL_EMOTICON = 30
|
||||
NETMSGTYPE_CL_VOTE = 31
|
||||
NETMSGTYPE_CL_CALLVOTE = 32
|
||||
NETMSGTYPE_SV_SKINCHANGE = 33
|
||||
NETMSGTYPE_CL_SKINCHANGE = 34
|
||||
NETMSGTYPE_SV_RACEFINISH = 35
|
||||
NETMSGTYPE_SV_CHECKPOINT = 36
|
||||
NETMSGTYPE_SV_COMMANDINFO = 37
|
||||
NETMSGTYPE_SV_COMMANDINFOREMOVE = 38
|
||||
NETMSGTYPE_CL_COMMAND = 39
|
||||
NUM_NETMSGTYPES = 40
|
||||
|
||||
NET_CTRLMSG_CONNECT = 0x01
|
||||
NET_CTRLMSG_ACCEPT = 0x02
|
||||
NET_CTRLMSG_CLOSE = 0x04
|
||||
|
|
75
teeworlds.rb
75
teeworlds.rb
|
@ -7,6 +7,7 @@ require_relative 'lib/array'
|
|||
require_relative 'lib/bytes'
|
||||
require_relative 'lib/network'
|
||||
require_relative 'lib/packet'
|
||||
require_relative 'lib/chunk'
|
||||
|
||||
class ServerInfo
|
||||
attr_reader :version, :name, :map, :gametype
|
||||
|
@ -216,35 +217,28 @@ class TwClient
|
|||
end
|
||||
end
|
||||
|
||||
def process_chunk(chunk)
|
||||
if !chunk.sys
|
||||
puts "todo non sys chunks. skipped msg: #{chunk.msg}"
|
||||
return
|
||||
end
|
||||
puts "proccess chunk with msg: #{chunk.msg}"
|
||||
case chunk.msg
|
||||
when NETMSG_MAP_CHANGE
|
||||
send_msg_ready
|
||||
when NETMSG_CON_READY
|
||||
send_msg_startinfo
|
||||
else
|
||||
puts "Unsupported system msg: #{chunk.msg}"
|
||||
exit(1)
|
||||
end
|
||||
end
|
||||
|
||||
def process_server_packet(data)
|
||||
puts "server packet with payload:"
|
||||
puts str_hex(data)
|
||||
|
||||
# todo: getting flags and size out of the chunk header is a must
|
||||
# the server responds to the clients ready packet with a compressed payload
|
||||
# the content are 3 chunks
|
||||
# - game.sv_motd
|
||||
# - game.sv_server_settings
|
||||
# - sys.con_ready
|
||||
#
|
||||
# The decompressed payload looks like this:
|
||||
# 40 02 02 02 00 40 07 03 22 01 00 01 00 01 08 40 01 04 0B
|
||||
# < SV MOTD > < SV SERVER SETTINGS > < READY >
|
||||
# size=2 size=7 size=1
|
||||
# msg=motd kickvote=true msg = 0B
|
||||
# payload="" kickmin... v
|
||||
# 5
|
||||
|
||||
# msg = data[CHUNK_HEADER_SIZE].unpack("C*").first
|
||||
# msg >>= 1
|
||||
# puts "msg: #{msg} type: #{msg.class}"
|
||||
# case msg
|
||||
# when NETMSG_MAP_CHANGE
|
||||
# send_msg_ready
|
||||
# else
|
||||
# puts "Unsupported msg: #{msg}"
|
||||
# exit(1)
|
||||
# end
|
||||
chunks = BigChungusTheChunkGetter.get_chunks(data)
|
||||
chunks.each do |chunk|
|
||||
process_chunk(chunk)
|
||||
end
|
||||
end
|
||||
|
||||
def tick
|
||||
|
@ -268,31 +262,6 @@ class TwClient
|
|||
else # process non-connless packets
|
||||
process_server_packet(packet.payload)
|
||||
end
|
||||
|
||||
# # check flags properly instead
|
||||
# if get_byte(data, 0) == '00'
|
||||
# # parse msg with bit flips instead
|
||||
# on_message(msg, data[(header_size + 1)..])
|
||||
# elsif get_byte(data, 0) == '10' # size 7 flags compression
|
||||
# payload = data[header_size..]
|
||||
# # puts "payload compressed: " + str_hex(payload)
|
||||
# payload = @huffman.decompress(payload.unpack("C*"))
|
||||
# # puts "payload decompressed: " + str_hex(payload.pack("C*"))
|
||||
|
||||
# # debug this datatype
|
||||
# # the byte 0x11 is being sent
|
||||
# # the tw server somehow reads 8 as NETMSG_SNAPSINGLE
|
||||
# # and ruby gets 17 here which is the decimal of 0x11
|
||||
# msg = payload[2]
|
||||
# puts "msg=#{msg} msgtype=#{msg.class} payloadtype=#{payload.class}"
|
||||
# if @server_info.nil?
|
||||
# send_msg_startinfo
|
||||
# else # assume snap reply with input to keep alive
|
||||
# send_input
|
||||
# end
|
||||
# else
|
||||
# on_ctrl_message(msg.to_i(16), data[(header_size + 1)..])
|
||||
# end
|
||||
end
|
||||
|
||||
def disconnect
|
||||
|
|
Loading…
Reference in a new issue