Basic networking implemented, currently non functional

This commit is contained in:
2019-11-19 14:48:12 -06:00
parent b17842ab75
commit 82db9dd14d
14 changed files with 283 additions and 14 deletions

52
lib/networking/client.rb Normal file
View File

@@ -0,0 +1,52 @@
class IMICRTS
class Networking
class Client
attr_reader :packets_sent, :packets_received,
:data_sent, :data_received
def initialize(socket)
@socket = socket
@packets_sent, @packets_received = 0, 0
@data_sent, @data_received = 0, 0
@read_queue = []
@write_queue = []
end
def update
if connected?
buffer = @socket.recv_nonblock(Networking::Protocol.max_packet_length, exception: false)
if buffer.is_a?(String)
order = buffer.split(Protocol::END_OF_MESSAGE).first.strip
end
until(@write_queue.size == 0)
packet = @write_queue.shift
@socket.write_nonblock(packet + Protocol::END_OF_MESSAGE, exception: false)
end
end
end
def connected?
!@socket.closed?
end
def close(packet = nil)
@socket.write(Networking::Packet.pack(packet) + Protocol::END_OF_MESSAGE) if packet
@socket.close
end
def write(data)
packet = Networking::Packet.new(type: Protocol::RELIABLE, client_id: 0, data: data)
@write_queue << Networking::Packet.pack(packet)
end
def read
return @read_queue.shift
end
end
end
end

View File

@@ -0,0 +1,25 @@
class IMICRTS
class Networking
class Connection
def initialize(director:, hostname:, port:)
@director = director
@hostname = hostname
@port = port
@client = Networking::Client.new(TCPSocket.new(@hostname, @port))
end
def connected?
@client.connected?
end
def update
@client.update
end
def close
@client.close
end
end
end
end

42
lib/networking/packet.rb Normal file
View File

@@ -0,0 +1,42 @@
class IMICRTS
class Networking
class Packet
# Packet
# [
# header_packet_type,
# header_packet_length,
# header_packet_sequence_id,
# header_packet_client_id,
#
# data
# ]
attr_reader :type, :sequence_id, :client_id, :data
def initialize(type:, sequence_id: nil, client_id:, data:)
@type = type
@sequence_id = sequence_id
@client_id = client_id
@data = data
end
def self.pack(packet)
header = nil
# Packet Type: Char => "C"
# Packet Sequence ID: 32-bit unsigned Integer => "N"
# Packet Client ID: 16-bit unsigned Integer => "n"
if packet.sequence_id
header = [packet.type, packet.sequence_id, packet.client_id].pack("CNn")
else
header = [packet.type, packet.client_id].pack("Cn")
end
header += packet.data
end
def self.unpack(raw_string)
pp raw_string.unpack("Cn")
end
end
end
end

View File

@@ -0,0 +1,32 @@
class IMICRTS
class Networking
module Protocol
VERSION = 0x01
END_OF_MESSAGE = "\r\r\r\n"
ACKNOWLEDGE = 0x01
CONNECT = 0x02
VERIFY_CONNECT = 0x03
DISCONNECT = 0x04
PING = 0x05
RELIABLE = 0x20
UNRELIABLE = 0x21
UNSEQUENCED = 0x22
FRAGMENT = 0x23
UNRELIABLE_FRAGMENT = 0x24
BANDWIDTH_LIMIT = 0x40
THROTTLE_CONFIGURE = 0x41
COUNT = 0x42
MASK = 0x43
HEADER_FLAG_COMPRESSED = 0x00
HEADER_FLAG_SENT_TIME = 0x01
def self.max_packet_length
1024 # => 1 Kb
end
end
end
end

51
lib/networking/server.rb Normal file
View File

@@ -0,0 +1,51 @@
class IMICRTS
class Networking
class Server
def initialize(director:, hostname:, port:, max_peers: 8)
@director = director
@hostname, @port = hostname, port
@max_peers = max_peers
@socket = TCPServer.new(hostname, port)
@clients = []
end
def update
new_client = @socket.accept_nonblock(exception: false)
if new_client != :wait_readable
handle_client(new_client)
end
@clients.each do |client|
client.update
end
end
def handle_client(client)
if @clients.size < @max_peers
@clients << Networking::Client.new(client)
else
client.write("\u00000128")
client.close
end
end
def broadcast(packet)
@clients.each do |client|
client.write(packet)
end
end
def write(client_id, packet)
client = @clients.find { |cl| cl.uid == client_id }
client.write(packet) if client
end
def stop
@socket.close if @socket
end
end
end
end