More todos than progress
This commit is contained in:
parent
f0762eee9d
commit
d68be4eb68
50
lib/network.rb
Normal file
50
lib/network.rb
Normal file
|
@ -0,0 +1,50 @@
|
|||
# randomize this
|
||||
MY_TOKEN = [0x73, 0x34, 0xB4, 0xA0]
|
||||
|
||||
MSG_TOKEN = [0x04, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x05] + MY_TOKEN + Array.new(512, 0x00)
|
||||
MSG_INFO = [0x40, 0x19, 0x01, 0x03, 0x30, 0x2E, 0x37, 0x20, 0x38, 0x30, 0x32, 0x66, # @...0.7 802f
|
||||
0x31, 0x62, 0x65, 0x36, 0x30, 0x61, 0x30, 0x35, 0x36, 0x36, 0x35, 0x66, # 1be60a05665f
|
||||
0x00, 0x00, 0x85, 0x1C]
|
||||
MSG_STARTINFO = [0x41, 0x19, 0x03, 0x36, 0x6E, 0x61, 0x6D, 0x65 , 0x6C, 0x65, 0x73, 0x73, # A..6nameless
|
||||
0x20, 0x6D, 0x65, 0x00, 0x00, 0x40, 0x67, 0x72 , 0x65, 0x65, 0x6E, 0x73, # me..@greens
|
||||
0x77, 0x61, 0x72, 0x64, 0x00, 0x64, 0x75, 0x6F , 0x64, 0x6F, 0x6E, 0x6E, # ward.duodonn
|
||||
0x79, 0x00, 0x00, 0x73, 0x74, 0x61, 0x6E, 0x64 , 0x61, 0x72, 0x64, 0x00, # y..standard
|
||||
0x73, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64 , 0x00, 0x73, 0x74, 0x61, # standard.sta
|
||||
0x6E, 0x64, 0x61, 0x72, 0x64, 0x00, 0x01, 0x01 , 0x00, 0x00, 0x00, 0x00, # ndard.......
|
||||
0x80, 0xFC, 0xAF, 0x05, 0xEB, 0x83, 0xD0, 0x0A , 0x80, 0xFE, 0x07, 0x80, # ............
|
||||
0xFE, 0x07, 0x80, 0xFE, 0x07, 0x80, 0xFE, 0x07]
|
||||
|
||||
NETMSG_NULL = 0
|
||||
NETMSG_INFO = 1
|
||||
NETMSG_MAP_CHANGE = 2 # sent when client should switch map
|
||||
NETMSG_MAP_DATA = 3 # map transfer, contains a chunk of the map file
|
||||
NETMSG_SERVERINFO = 4
|
||||
NETMSG_CON_READY = 5 # connection is ready, client should send start info
|
||||
NETMSG_SNAP = 6 # normal snapshot, multiple parts
|
||||
NETMSG_SNAPEMPTY = 7 # empty snapshot
|
||||
NETMSG_SNAPSINGLE = 8 # ?
|
||||
NETMSG_SNAPSMALL = 9
|
||||
NETMSG_INPUTTIMING = 10 # reports how off the input was
|
||||
NETMSG_RCON_AUTH_ON = 11 # rcon authentication enabled
|
||||
NETMSG_RCON_AUTH_OFF = 12 # rcon authentication disabled
|
||||
NETMSG_RCON_LINE = 13 # line that should be printed to the remote console
|
||||
NETMSG_RCON_CMD_ADD = 14
|
||||
NETMSG_RCON_CMD_REM = 15
|
||||
|
||||
NET_CTRLMSG_CONNECT = 0x01
|
||||
NET_CTRLMSG_ACCEPT = 0x02
|
||||
NET_CTRLMSG_CLOSE = 0x04
|
||||
NET_CTRLMSG_TOKEN = 0x05
|
||||
|
||||
NET_CONNSTATE_OFFLINE = 0
|
||||
NET_CONNSTATE_TOKEN = 1
|
||||
NET_CONNSTATE_CONNECT = 2
|
||||
NET_CONNSTATE_PENDING = 3
|
||||
NET_CONNSTATE_ONLINE = 4
|
||||
NET_CONNSTATE_ERROR = 5
|
||||
|
||||
NET_MAX_PACKETSIZE = 1400
|
||||
|
||||
PACKET_HEADER_SIZE = 7
|
||||
CHUNK_HEADER_SIZE = 3
|
||||
|
|
@ -1,12 +1,23 @@
|
|||
require 'huffman_tw'
|
||||
|
||||
# Class holding the parsed packet data
|
||||
class Packet
|
||||
attr_reader :flags
|
||||
attr_reader :payload
|
||||
|
||||
def initialize(data)
|
||||
# @data and @payload
|
||||
# are strings representing the raw bytes
|
||||
@data = data
|
||||
@huffman = Huffman.new
|
||||
@flags = {}
|
||||
flags_byte = data[0].unpack("B*")
|
||||
parse_flags(flags_byte.first[2..5])
|
||||
@payload = data[PACKET_HEADER_SIZE..]
|
||||
if flags_compressed
|
||||
@payload = @huffman.decompress(@payload.unpack("C*"))
|
||||
@payload = @payload.pack("C*")
|
||||
end
|
||||
end
|
||||
|
||||
def annotate_first_row(bytes)
|
||||
|
@ -43,12 +54,16 @@ class Packet
|
|||
# and creates a hash out of it
|
||||
@flags = {}
|
||||
@flags[:connection] = four_bit_str[0] == '1'
|
||||
@flags[:not_compressed] = four_bit_str[1] == '1'
|
||||
@flags[:no_resend] = four_bit_str[2] == '1'
|
||||
@flags[:compressed] = four_bit_str[1] == '1'
|
||||
@flags[:resend] = four_bit_str[2] == '1'
|
||||
@flags[:control] = four_bit_str[3] == '1'
|
||||
@flags
|
||||
end
|
||||
|
||||
def flags_compressed()
|
||||
@flags[:compressed]
|
||||
end
|
||||
|
||||
def flags_connless()
|
||||
@flags[:connection] == false
|
||||
end
|
||||
|
|
72
teeworlds.rb
72
teeworlds.rb
|
@ -2,46 +2,12 @@
|
|||
|
||||
require 'socket'
|
||||
|
||||
require 'huffman_tw'
|
||||
|
||||
require_relative 'lib/string'
|
||||
require_relative 'lib/array'
|
||||
require_relative 'lib/bytes'
|
||||
require_relative 'lib/network'
|
||||
require_relative 'lib/packet'
|
||||
|
||||
# randomize this
|
||||
MY_TOKEN = [0x73, 0x34, 0xB4, 0xA0]
|
||||
|
||||
MSG_TOKEN = [0x04, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x05] + MY_TOKEN + Array.new(512, 0x00)
|
||||
MSG_INFO = [0x40, 0x19, 0x01, 0x03, 0x30, 0x2E, 0x37, 0x20, 0x38, 0x30, 0x32, 0x66, # @...0.7 802f
|
||||
0x31, 0x62, 0x65, 0x36, 0x30, 0x61, 0x30, 0x35, 0x36, 0x36, 0x35, 0x66, # 1be60a05665f
|
||||
0x00, 0x00, 0x85, 0x1C]
|
||||
MSG_STARTINFO = [0x41, 0x19, 0x03, 0x36, 0x6E, 0x61, 0x6D, 0x65 , 0x6C, 0x65, 0x73, 0x73, # A..6nameless
|
||||
0x20, 0x6D, 0x65, 0x00, 0x00, 0x40, 0x67, 0x72 , 0x65, 0x65, 0x6E, 0x73, # me..@greens
|
||||
0x77, 0x61, 0x72, 0x64, 0x00, 0x64, 0x75, 0x6F , 0x64, 0x6F, 0x6E, 0x6E, # ward.duodonn
|
||||
0x79, 0x00, 0x00, 0x73, 0x74, 0x61, 0x6E, 0x64 , 0x61, 0x72, 0x64, 0x00, # y..standard
|
||||
0x73, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64 , 0x00, 0x73, 0x74, 0x61, # standard.sta
|
||||
0x6E, 0x64, 0x61, 0x72, 0x64, 0x00, 0x01, 0x01 , 0x00, 0x00, 0x00, 0x00, # ndard.......
|
||||
0x80, 0xFC, 0xAF, 0x05, 0xEB, 0x83, 0xD0, 0x0A , 0x80, 0xFE, 0x07, 0x80, # ............
|
||||
0xFE, 0x07, 0x80, 0xFE, 0x07, 0x80, 0xFE, 0x07]
|
||||
|
||||
|
||||
NET_CTRLMSG_CONNECT = 0x01
|
||||
NET_CTRLMSG_ACCEPT = 0x02
|
||||
NET_CTRLMSG_CLOSE = 0x04
|
||||
NET_CTRLMSG_TOKEN = 0x05
|
||||
|
||||
NET_CONNSTATE_OFFLINE = 0
|
||||
NET_CONNSTATE_TOKEN = 1
|
||||
NET_CONNSTATE_CONNECT = 2
|
||||
NET_CONNSTATE_PENDING = 3
|
||||
NET_CONNSTATE_ONLINE = 4
|
||||
NET_CONNSTATE_ERROR = 5
|
||||
|
||||
NET_MAX_PACKETSIZE = 1400
|
||||
|
||||
CONTROL_HEADER_SIZE = 7
|
||||
|
||||
class ServerInfo
|
||||
attr_reader :version, :name, :map, :gametype
|
||||
|
||||
|
@ -67,7 +33,6 @@ class TwClient
|
|||
@state = NET_CONNSTATE_OFFLINE
|
||||
@ip = 'localhost'
|
||||
@port = 8303
|
||||
@huffman = Huffman.new
|
||||
@packet_flags = {}
|
||||
end
|
||||
|
||||
|
@ -252,8 +217,34 @@ class TwClient
|
|||
end
|
||||
|
||||
def process_server_packet(data)
|
||||
puts "server packet with 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
|
||||
end
|
||||
|
||||
def tick
|
||||
|
@ -269,14 +260,13 @@ class TwClient
|
|||
|
||||
packet = Packet.new(data)
|
||||
puts packet.to_s
|
||||
gets
|
||||
|
||||
# process connless packets data
|
||||
if packet.flags_control
|
||||
msg = data[CONTROL_HEADER_SIZE].unpack("C*").first
|
||||
on_ctrl_message(msg, data[(CONTROL_HEADER_SIZE + 1)..])
|
||||
msg = data[PACKET_HEADER_SIZE].unpack("C*").first
|
||||
on_ctrl_message(msg, data[(PACKET_HEADER_SIZE + 1)..])
|
||||
else # process non-connless packets
|
||||
process_server_packet(data)
|
||||
process_server_packet(packet.payload)
|
||||
end
|
||||
|
||||
# # check flags properly instead
|
||||
|
|
Loading…
Reference in a new issue