mirror of
https://github.com/cyberarm/i-mic-rts.git
synced 2025-12-15 15:52:34 +00:00
Basic networking implemented, currently non functional
This commit is contained in:
52
lib/networking/client.rb
Normal file
52
lib/networking/client.rb
Normal 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
|
||||
25
lib/networking/connection.rb
Normal file
25
lib/networking/connection.rb
Normal 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
42
lib/networking/packet.rb
Normal 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
|
||||
32
lib/networking/protocol.rb
Normal file
32
lib/networking/protocol.rb
Normal 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
51
lib/networking/server.rb
Normal 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
|
||||
Reference in New Issue
Block a user