Skip to content

Commit

Permalink
Drop known chunks. Fixes duplicated chat messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
ChillerDragon committed Jun 24, 2024
1 parent deb679d commit 6fa0cc9
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 6 deletions.
13 changes: 10 additions & 3 deletions lib/chunk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
#
# https://chillerdragon.github.io/teeworlds-protocol/07/packet_layout.html
class NetChunk
attr_reader :next, :data, :msg, :sys, :flags, :header_raw, :full_raw
attr_reader :next, :data
attr_reader :msg, :sys, :flags, :seq
attr_reader :header_raw, :full_raw

@@sent_vital_chunks = 0

def initialize(data)
@next = nil
@flags = {}
@seq = 0
@size = 0
parse_header(data[0..2])
header_size = if flags_vital
Expand Down Expand Up @@ -135,8 +138,12 @@ def parse_header(data)
size_bytes.map! { |b| b[2..].join }
@size = size_bytes.join.to_i(2)

# sequence number
# in da third byte but who needs seq?!
if @flags[:vital]
data = data[0..2].bytes
@seq = data[1]&0xC0<<2 | data[2]
else
@seq = 0
end
end

# @return [Boolean]
Expand Down
21 changes: 21 additions & 0 deletions lib/connection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

##
# Only used for chunks where the sequence number does not match the expected value
# to decide wether to drop known chunks silently or request resend if something got lost
#
# true - if the sequence number is already known and the chunk should be dropped
# false - if the sequence number is off and we need to request a resend of lost chunks
#
# @return [Boolean]
def seq_in_backroom?(seq, ack)
bottom = ack - NET_MAX_SEQUENCE / 2
if bottom.negative?
return true if seq <= ack
return true if seq >= (bottom + NET_MAX_SEQUENCE)
else
return true if seq <= ack && seq >= bottom
end
return false
end

17 changes: 14 additions & 3 deletions lib/teeworlds_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
require_relative 'models/player'
require_relative 'game_client'
require_relative 'config'
require_relative 'connection'

class TeeworldsClient
attr_reader :state, :hooks, :game_client, :verbose_snap
Expand Down Expand Up @@ -445,9 +446,19 @@ def process_server_packet(packet)
end
chunks = BigChungusTheChunkGetter.get_chunks(data)
chunks.each do |chunk|
if chunk.flags_vital && !chunk.flags_resend && chunk.msg != NETMSG_NULL
@netbase.ack = (@netbase.ack + 1) % NET_MAX_SEQUENCE
puts "got ack: #{@netbase.ack}" if @verbose
if chunk.flags_vital
if chunk.seq == (@netbase.ack + 1) % NET_MAX_SEQUENCE
# in sequence
@netbase.ack = (@netbase.ack + 1) % NET_MAX_SEQUENCE
else
puts "warning: got chunk out of sequence! seq=#{chunk.seq} expected_seq=#{(@netbase.ack+1)%NET_MAX_SEQUENCE}"
if seq_in_backroom?(chunk.seq, @netbase.ack)
puts " dropping known chunk ..."
next
end
# TODO: request resend
puts " REQUESTING RESEND NOT IMPLEMENTED"
end
end
process_chunk(chunk)
end
Expand Down

0 comments on commit 6fa0cc9

Please sign in to comment.