Count ack per client and thus fix reconnect
Sadly reconnecting somehow crashes the client :( https://github.com/teeworlds/teeworlds/issues/3182
This commit is contained in:
parent
409f880f36
commit
09bd7bfebb
|
@ -40,9 +40,8 @@ class NetBase
|
|||
# Sends a packing setting the proper header for you
|
||||
#
|
||||
# @param payload [Array] The Integer list representing the data after the header
|
||||
# @param num_chunks [Integer] Amount of NetChunks in the payload
|
||||
# @param flags [Hash] Packet header flags for more details check the class +PacketFlags+
|
||||
def send_packet(payload, num_chunks = 1, opts = {})
|
||||
# @param opts [Hash] :chunks, :client and packet header flags for more details check the class +PacketFlags+
|
||||
def send_packet(payload, opts = { chunks: 1, client: nil, addr: nil })
|
||||
# unsigned char flags_ack; // 6bit flags, 2bit ack
|
||||
# unsigned char ack; // 8bit ack
|
||||
# unsigned char numchunks; // 8bit chunks
|
||||
|
@ -55,9 +54,21 @@ class NetBase
|
|||
# // TTTTTTTT
|
||||
# // TTTTTTTT
|
||||
flags_bits = PacketFlags.new(opts).bits
|
||||
ack = @ack
|
||||
ip = @ip
|
||||
port = @port
|
||||
unless opts[:client].nil?
|
||||
ack = opts[:client].ack
|
||||
ip = opts[:client].addr.ip
|
||||
port = opts[:client].addr.port
|
||||
end
|
||||
unless opts[:addr].nil?
|
||||
ip = opts[:addr].ip
|
||||
port = opts[:addr].port
|
||||
end
|
||||
# unused flags ack num chunks
|
||||
# ff ffff aa aaaa aaaa NNNN NNNN
|
||||
header_bits = "00#{flags_bits}#{@ack.to_s(2).rjust(10, '0')}#{num_chunks.to_s(2).rjust(8, '0')}"
|
||||
header_bits = "00#{flags_bits}#{ack.to_s(2).rjust(10, '0')}#{opts[:chunks].to_s(2).rjust(8, '0')}"
|
||||
|
||||
header = header_bits.chars.groups_of(8).map do |eight_bits|
|
||||
eight_bits.join.to_i(2)
|
||||
|
@ -65,12 +76,6 @@ class NetBase
|
|||
|
||||
header += str_bytes(@peer_token)
|
||||
data = (header + payload).pack('C*')
|
||||
ip = @ip
|
||||
port = @port
|
||||
unless opts[:addr].nil?
|
||||
ip = opts[:addr].ip
|
||||
port = opts[:addr].port
|
||||
end
|
||||
puts "send to #{ip}:#{port}"
|
||||
@s.send(data, 0, ip, port)
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ class TeeworldsClient
|
|||
# TODO: this is same in client and server
|
||||
# move to NetBase???
|
||||
def send_ctrl_close
|
||||
@netbase&.send_packet([NET_CTRLMSG_CLOSE], 0, control: true)
|
||||
@netbase&.send_packet([NET_CTRLMSG_CLOSE], chunks: 0, control: true)
|
||||
end
|
||||
|
||||
def disconnect
|
||||
|
@ -160,18 +160,18 @@ class TeeworldsClient
|
|||
end
|
||||
|
||||
def send_ctrl_keepalive
|
||||
@netbase.send_packet([NET_CTRLMSG_KEEPALIVE], 0, control: true)
|
||||
@netbase.send_packet([NET_CTRLMSG_KEEPALIVE], chunks: 0, control: true)
|
||||
end
|
||||
|
||||
def send_msg_connect
|
||||
msg = [NET_CTRLMSG_CONNECT] + str_bytes(@client_token) + Array.new(501, 0x00)
|
||||
@netbase.send_packet(msg, 0, control: true)
|
||||
@netbase.send_packet(msg, chunks: 0, control: true)
|
||||
end
|
||||
|
||||
def send_ctrl_with_token
|
||||
@state = NET_CONNSTATE_TOKEN
|
||||
msg = [NET_CTRLMSG_TOKEN] + str_bytes(@client_token) + Array.new(512, 0x00)
|
||||
@netbase.send_packet(msg, 0, control: true)
|
||||
@netbase.send_packet(msg, chunks: 0, control: true)
|
||||
end
|
||||
|
||||
def send_info
|
||||
|
@ -183,7 +183,7 @@ class TeeworldsClient
|
|||
[pack_msg_id(NETMSG_INFO, system: true)] +
|
||||
data
|
||||
|
||||
@netbase.send_packet(msg, 1)
|
||||
@netbase.send_packet(msg)
|
||||
end
|
||||
|
||||
def rcon_auth(name, password = nil)
|
||||
|
@ -210,7 +210,7 @@ class TeeworldsClient
|
|||
msg = NetChunk.create_header(vital: true, size: data.size + 1) +
|
||||
[pack_msg_id(NETMSG_RCON_AUTH, system: true)] +
|
||||
data
|
||||
@netbase.send_packet(msg, 1)
|
||||
@netbase.send_packet(msg)
|
||||
end
|
||||
|
||||
def rcon(command)
|
||||
|
@ -219,7 +219,7 @@ class TeeworldsClient
|
|||
msg = NetChunk.create_header(vital: true, size: data.size + 1) +
|
||||
[pack_msg_id(NETMSG_RCON_CMD, system: true)] +
|
||||
data
|
||||
@netbase.send_packet(msg, 1)
|
||||
@netbase.send_packet(msg)
|
||||
end
|
||||
|
||||
def send_msg_startinfo
|
||||
|
@ -288,7 +288,7 @@ class TeeworldsClient
|
|||
msg = NetChunk.create_header(vital: false, size: data.size + 1) +
|
||||
[pack_msg_id(NETMSG_INPUT, system: true)] +
|
||||
data
|
||||
@netbase.send_packet(msg, 1)
|
||||
@netbase.send_packet(msg)
|
||||
end
|
||||
|
||||
def on_msg_token(data)
|
||||
|
|
|
@ -17,11 +17,13 @@ require_relative 'token'
|
|||
|
||||
class Client
|
||||
attr_accessor :id, :addr, :vital_sent, :last_recv_time, :token, :player
|
||||
attr_reader :ack
|
||||
|
||||
def initialize(attr = {})
|
||||
@id = attr[:id]
|
||||
@addr = attr[:addr]
|
||||
@vital_sent = 0
|
||||
@ack = 0
|
||||
@last_recv_time = Time.now
|
||||
@player = Player.new(
|
||||
id: @id,
|
||||
|
@ -35,6 +37,10 @@ class Client
|
|||
SecurityToken.validate(@token)
|
||||
end
|
||||
|
||||
def bump_ack
|
||||
@ack = (@ack + 1) % NET_MAX_SEQUENCE
|
||||
end
|
||||
|
||||
# TODO: use or remove
|
||||
# not sure if its cool
|
||||
# one can make vital_sent read only
|
||||
|
@ -123,11 +129,19 @@ class TeeworldsServer
|
|||
end
|
||||
|
||||
def on_client_packet(packet)
|
||||
client = packet.client
|
||||
if client.nil?
|
||||
# TODO: turn this into a silent return
|
||||
# otherwise bad actors can easily trigger this
|
||||
# with handcrafted packets
|
||||
puts 'Error: got client packet from unknown client'
|
||||
exit 1
|
||||
end
|
||||
chunks = BigChungusTheChunkGetter.get_chunks(packet.payload)
|
||||
chunks.each do |chunk|
|
||||
if chunk.flags_vital && !chunk.flags_resend
|
||||
@netbase.ack = (@netbase.ack + 1) % NET_MAX_SEQUENCE
|
||||
puts "got ack: #{@netbase.ack}" if @verbose
|
||||
packet.client.bump_ack
|
||||
puts "got ack: #{packet.client.ack}" if @verbose
|
||||
end
|
||||
process_chunk(chunk, packet)
|
||||
end
|
||||
|
@ -157,14 +171,14 @@ class TeeworldsServer
|
|||
msg = [NET_CTRLMSG_CLOSE]
|
||||
msg += Packer.pack_str(reason) unless reason.nil?
|
||||
@netbase.set_peer_token(client.token)
|
||||
@netbase.send_packet(msg, 0, control: true, addr: client.addr)
|
||||
@netbase.send_packet(msg, chunks: 0, control: true, client:)
|
||||
# @netbase.set_peer_token(@server_token)
|
||||
end
|
||||
|
||||
def send_ctrl_with_token(addr, token)
|
||||
msg = [NET_CTRLMSG_TOKEN] + str_bytes(@server_token)
|
||||
@netbase.set_peer_token(token)
|
||||
@netbase.send_packet(msg, 0, control: true, addr:)
|
||||
@netbase.send_packet(msg, chunks: 0, control: true, addr:)
|
||||
# @netbase.set_peer_token(@server_token)
|
||||
end
|
||||
|
||||
|
@ -179,33 +193,33 @@ class TeeworldsServer
|
|||
msg = NetChunk.create_header(vital: true, size: data.size + 1, client:) +
|
||||
[pack_msg_id(NETMSG_MAP_CHANGE, system: true)] +
|
||||
data
|
||||
@netbase.send_packet(msg, 1, addr: client.addr)
|
||||
@netbase.send_packet(msg, chunks: 1, client:)
|
||||
end
|
||||
|
||||
def send_ready(client)
|
||||
msg = NetChunk.create_header(vital: true, size: 1, client:) +
|
||||
[pack_msg_id(NETMSG_CON_READY, system: true)]
|
||||
@netbase.send_packet(msg, 1, addr: client.addr)
|
||||
@netbase.send_packet(msg, chunks: 1, client:)
|
||||
end
|
||||
|
||||
def send_ready_to_enter(client)
|
||||
msg = NetChunk.create_header(vital: true, size: 1, client:) +
|
||||
[pack_msg_id(NETMSGTYPE_SV_READYTOENTER, system: false)]
|
||||
@netbase.send_packet(msg, 1, addr: client.addr)
|
||||
@netbase.send_packet(msg, chunks: 1, client:)
|
||||
end
|
||||
|
||||
def send_server_info(client, server_info)
|
||||
msg = NetChunk.create_header(vital: true, size: 1 + server_info.size, client:) +
|
||||
[pack_msg_id(NETMSG_SERVERINFO, system: true)] +
|
||||
server_info
|
||||
@netbase.send_packet(msg, 1, addr: client.addr)
|
||||
@netbase.send_packet(msg, chunks: 1, client:)
|
||||
end
|
||||
|
||||
def send_game_info(client, data)
|
||||
msg = NetChunk.create_header(vital: true, size: 1 + data.size, client:) +
|
||||
[pack_msg_id(NETMSGTYPE_SV_GAMEINFO, system: false)] +
|
||||
data
|
||||
@netbase.send_packet(msg, 1, addr: client.addr)
|
||||
@netbase.send_packet(msg, chunks: 1, client:)
|
||||
end
|
||||
|
||||
def on_ctrl_token(packet)
|
||||
|
@ -247,7 +261,7 @@ class TeeworldsServer
|
|||
puts "got connection, sending accept (client token: #{token})"
|
||||
client = Client.new(id:, addr: packet.addr, token:)
|
||||
@clients[id] = client
|
||||
@netbase.send_packet([NET_CTRLMSG_ACCEPT], 0, control: true, addr: packet.addr)
|
||||
@netbase.send_packet([NET_CTRLMSG_ACCEPT], chunks: 0, control: true, client:)
|
||||
end
|
||||
|
||||
def on_packet(packet)
|
||||
|
@ -283,7 +297,7 @@ class TeeworldsServer
|
|||
[pack_msg_id(NETMSG_SNAPEMPTY, system: true)] +
|
||||
data
|
||||
@clients.each do |_id, client|
|
||||
@netbase.send_packet(msg_snap_empty, 1, addr: client.addr)
|
||||
@netbase.send_packet(msg_snap_empty, chunks: 1, client:)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue