teeworlds_network/lib/net_base.rb

72 lines
1.9 KiB
Ruby
Raw Normal View History

2022-11-05 16:47:47 +00:00
# frozen_string_literal: true
##
# NetBase
#
# Lowest network layer logic. Sends packets via udp.
# Also adding the teeworlds protocol packet header.
2022-11-01 13:25:56 +00:00
class NetBase
2022-11-08 15:20:46 +00:00
attr_accessor :peer_token, :ack
2022-11-01 13:25:56 +00:00
2022-11-11 12:42:11 +00:00
def initialize(opts = {})
@verbose = opts[:verbose] || false
2022-11-01 13:25:56 +00:00
@ip = nil
@port = nil
@s = nil
@ack = 0
2022-11-11 13:37:41 +00:00
@peer_token = [0xFF, 0xFF, 0xFF, 0xFF].map { |b| b.to_s(16).rjust(2, '0') }.join
2022-11-08 15:20:46 +00:00
end
def bind(socket)
@s = socket
2022-11-01 13:25:56 +00:00
end
def connect(socket, ip, port)
@s = socket
@ip = ip
@port = port
@ack = 0
end
##
# Sends a packing setting the proper header for you
#
# @param payload [Array] The Integer list representing the data after the header
2022-11-05 16:47:47 +00:00
# @param num_chunks [Integer] Amount of NetChunks in the payload
2022-11-01 13:25:56 +00:00
# @param flags [Hash] Packet header flags for more details check the class +PacketFlags+
2022-11-08 15:20:46 +00:00
def send_packet(payload, num_chunks = 1, opts = {})
2022-11-01 13:25:56 +00:00
# unsigned char flags_ack; // 6bit flags, 2bit ack
# unsigned char ack; // 8bit ack
# unsigned char numchunks; // 8bit chunks
# unsigned char token[4]; // 32bit token
# // ffffffaa
# // aaaaaaaa
# // NNNNNNNN
# // TTTTTTTT
# // TTTTTTTT
# // TTTTTTTT
# // TTTTTTTT
2022-11-08 15:20:46 +00:00
flags_bits = PacketFlags.new(opts).bits
2022-11-05 16:47:47 +00:00
# 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')}"
2022-11-01 13:25:56 +00:00
header = header_bits.chars.groups_of(8).map do |eight_bits|
2022-11-05 16:57:12 +00:00
eight_bits.join.to_i(2)
2022-11-01 13:25:56 +00:00
end
2022-11-08 15:20:46 +00:00
header += str_bytes(@peer_token)
2022-11-01 13:25:56 +00:00
data = (header + payload).pack('C*')
2022-11-08 15:20:46 +00:00
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)
2022-11-01 13:25:56 +00:00
2022-11-08 15:20:46 +00:00
puts Packet.new(data, '>').to_s if @verbose || opts[:test]
2022-11-01 13:25:56 +00:00
end
end