package onyx_net
-// @CLEANUP
-use package core
Host :: struct {
socket : net.Socket;
Socket_Binding_Failed;
}
-host_create :: (addr: ^net.Socket_Address, peer_count: u32) -> (^Host, Host_Creation_Error) {
+host_create :: (addr: &net.Socket_Address, peer_count: u32) -> (&Host, Host_Creation_Error) {
errored := false;
host := new(Host);
defer if errored do cfree(host);
host.peers = make([] Peer, peer_count);
- defer if errored do delete(^host.peers);
+ defer if errored do delete(&host.peers);
host.connected_peers = 0;
if socket, err := net.socket_create(.Inet, .Dgram); err != .None {
} else {
host.socket = socket;
}
- defer if errored do net.socket_close(^host.socket);
+ defer if errored do net.socket_close(&host.socket);
if addr != null {
sa: net.Socket_Address;
- net.make_ipv4_address(^sa, 0, addr.port);
- if !(host.socket->bind(^sa)) {
+ net.make_ipv4_address(&sa, 0, addr.port);
+ if !(host.socket->bind(&sa)) {
errored = true;
return null, .Socket_Binding_Failed;
}
host.no_ack_disconnect_timeout = 10000;
host.current_time = ~~ (os.time() & cast(u64) 0xFFFFFFFF);
- for^ peer: host.peers {
+ for& peer: host.peers {
peer.host = host;
peer.state = .Disconnected;
peer.channels = .{ null, 0 };
return host, .None;
}
-host_connect :: (host: ^Host, addr: ^net.Socket_Address, channel_count: u32) -> ^Peer {
- peer: ^Peer;
+host_connect :: (host: &Host, addr: &net.Socket_Address, channel_count: u32) -> &Peer {
+ peer: &Peer;
// Find first peer that is in the disconnected state.
- for^ host.peers do if it.state == .Disconnected {
+ for& host.peers do if it.state == .Disconnected {
peer = it;
break;
}
peer.mtu = Host_Default_MTU;
peer.last_acknowledge_time = host.current_time;
- for^ peer.channels do peer_setup_channel(peer, it);
+ for& peer.channels do peer_setup_channel(peer, it);
command := new(Protocol_Connect);
command.command = .Connect;
return peer;
}
-host_free :: (host: ^Host) {
- net.socket_close(^host.socket);
- delete(^host.peers);
- delete(host);
+host_free :: (host: &Host) {
+ net.socket_close(&host.socket);
+ delete(&host.peers);
+ cfree(host);
}
-host_broadcast :: (host: ^Host, channel: Channel_ID, packet: ^Packet) {
- for ^peer: host.peers {
+host_broadcast :: (host: &Host, channel: Channel_ID, packet: &Packet) {
+ for &peer: host.peers {
if peer.state != .Connected do continue;
peer_send(peer, channel, packet);
}
}
-host_pulse :: (host: ^Host, timeout: u32 = 0) -> bool {
+host_pulse :: (host: &Host, timeout: u32 = 0) -> bool {
host.produced_event = false;
host.current_time = ~~ (os.time() & cast(u64) 0xFFFFFFFF);
return host.produced_event;
}
-host_send_commands :: (host: ^Host) -> bool {
- for ^peer: host.peers {
+host_send_commands :: (host: &Host) -> bool {
+ for &peer: host.peers {
//
// Skip over peers that are dead or disconnected.
if peer.state == .Disconnected || peer.state == .Zombie {
}
}
-host_receive_commands :: (host: ^Host, timeout: u32 = 0) -> bool {
+host_receive_commands :: (host: &Host, timeout: u32 = 0) -> bool {
if timeout > 0 {
- check_sockets := (^net.Socket).[ ^host.socket ];
+ check_sockets := (&net.Socket).[ &host.socket ];
changed_buffer := alloc.array_from_stack(net.Socket_Poll_Status, 1);
net.socket_poll_all(check_sockets, timeout, changed_buffer);
return host_handle_incoming_commands(host);
}
-host_handle_incoming_commands :: (host: ^Host) -> bool {
- header: ^Protocol_Header = ~~ host.received_data.data;
+host_handle_incoming_commands :: (host: &Host) -> bool {
+ header: &Protocol_Header = ~~ host.received_data.data;
current_data := host.received_data;
peer_id := cast(u32) net.network_to_host(header.peer_id);
- peer: ^Peer;
+ peer: &Peer;
if peer_id == 0xffff --- // a Peer Id of 0xffff is used for a newly connecting peer.
elseif peer_id >= host.peers.count || peer_id >= host.peers.count {
return false;
} else {
- peer = ^host.peers[peer_id];
+ peer = &host.peers[peer_id];
}
if peer != null {
if peer.addr.port != host.received_addr.port do return false;
}
- string.advance(^current_data, sizeof typeof *header);
+ string.advance(¤t_data, sizeof typeof *header);
return_block :: macro () {
return host.event.type != .None;
while current_data.count >= sizeof Protocol_Command_Header {
if host.produced_event do break;
- command := cast(^Protocol_Command_Header) current_data.data;
+ command := cast(&Protocol_Command_Header) current_data.data;
command_id := command_get_effective(command.command);
command.seq_number = net.network_to_host(command.seq_number);
// printf("Received command: {} {} {*p}\n", command_sizes[command_id], cast(Command) command_id, command);
- string.advance(^current_data, command_sizes[command_id]);
+ string.advance(¤t_data, command_sizes[command_id]);
switch command_id {
case .Acknowledge {
case .Send_Reliable, .Send_Unreliable {
if peer == null do return_block();
- host_handle_send_reliable_command(host, peer, ~~ command, ^current_data);
+ host_handle_send_reliable_command(host, peer, ~~ command, ¤t_data);
}
case .Send_Fragment {
if peer == null do return_block();
- host_handle_send_fragment_command(host, peer, ~~ command, ^current_data);
+ host_handle_send_fragment_command(host, peer, ~~ command, ¤t_data);
}
}
return host.produced_event;
}
-host_get_events :: (host: ^Host, timeout: u32 = 0) -> Iterator(^Event) {
+host_get_events :: (host: &Host, timeout: u32 = 0) -> Iterator(&Event) {
Context :: struct {
- host: ^Host;
+ host: &Host;
timeout: u32 = 0;
}
- next :: (use ctx: ^Context) -> (^Event, bool) {
+ next :: (use ctx: &Context) -> (&Event, bool) {
if host_pulse(host, timeout) {
- return ^host.event, true;
+ return &host.event, true;
}
return null, false;
return .{ ctx, next, cfree };
}
-#local host_notify_connect :: (host: ^Host, peer: ^Peer) {
+#local host_notify_connect :: (host: &Host, peer: &Peer) {
host.event.type = .Connection;
host.event.peer = peer;
host.event.channel_id = 255; // Magic constant
host.produced_event = true;
}
-#local host_notify_disconnect :: (host: ^Host, peer: ^Peer) {
+#local host_notify_disconnect :: (host: &Host, peer: &Peer) {
host.event.type = .Disconnection;
host.event.peer = peer;
host.event.channel_id = 255; // Magic constant
host.produced_event = true;
}
-#local host_notify_message :: (host: ^Host, peer: ^Peer, channel_id: u8, data: [] u8) {
+#local host_notify_message :: (host: &Host, peer: &Peer, channel_id: u8, data: [] u8) {
host.event.type = .Message;
host.event.peer = peer;
host.event.channel_id = channel_id;
host.produced_event = true;
}
-#local host_handle_acknowledge_command :: (host: ^Host, peer: ^Peer, command: ^Protocol_Acknowledge) {
+#local host_handle_acknowledge_command :: (host: &Host, peer: &Peer, command: &Protocol_Acknowledge) {
if peer.state == .Disconnected || peer.state == .Zombie do return;
//
}
}
-#local host_handle_connect_command :: (host: ^Host, command: ^Protocol_Connect) -> ^Peer {
- peer: ^Peer;
+#local host_handle_connect_command :: (host: &Host, command: &Protocol_Connect) -> &Peer {
+ peer: &Peer;
- for^ host.peers {
+ for& host.peers {
if it.state == .Disconnected {
peer = it;
break;
channel_count := net.network_to_host(command.channel_count);
peer.channels = make([] Channel, channel_count);
- for ^peer.channels do peer_setup_channel(peer, it);
+ for &peer.channels do peer_setup_channel(peer, it);
peer.state = .Acknowledging_Connection;
peer.connect_id = net.network_to_host(command.connect_id);
return peer;
}
-#local host_handle_verify_connect_command :: (host: ^Host, peer: ^Peer, command: ^Protocol_Verify_Connect) {
+#local host_handle_verify_connect_command :: (host: &Host, peer: &Peer, command: &Protocol_Verify_Connect) {
if net.network_to_host(command.connect_id) != peer.connect_id do return;
channel_count := net.network_to_host(command.channel_count);
return;
}
-#local host_handle_disconnect_command :: (host: ^Host, peer: ^Peer, command: ^Protocol_Disconnect) {
+#local host_handle_disconnect_command :: (host: &Host, peer: &Peer, command: &Protocol_Disconnect) {
peer.state = .Disconnected;
host_notify_disconnect(host, peer);
}
//
// This is slightly misnamed, as it is actually handling a received reliable message.
-#local host_handle_send_reliable_command :: (host: ^Host, peer: ^Peer, command: ^Protocol_Send, data: ^[] u8) {
+#local host_handle_send_reliable_command :: (host: &Host, peer: &Peer, command: &Protocol_Send, data: &[] u8) {
if ~~command.channel > peer.channels.count || (peer.state != .Connected && peer.state != .Disconnect_Later) {
return;
}
defer string.advance(data, data_length);
if command_get_effective(command.command) == .Send_Reliable {
- channel := ^peer.channels[command.channel];
+ channel := &peer.channels[command.channel];
for channel.reliable_windows {
if command.seq_number == it do return;
}
host_notify_message(host, peer, command.channel, *data);
}
-#local host_handle_send_fragment_command :: (host: ^Host, peer: ^Peer, command: ^Protocol_Send_Fragment, data: ^[] u8) {
+#local host_handle_send_fragment_command :: (host: &Host, peer: &Peer, command: &Protocol_Send_Fragment, data: &[] u8) {
if ~~command.channel > peer.channels.count || (peer.state != .Connected && peer.state != .Disconnect_Later) {
return;
}
defer string.advance(data, data_length);
// @CopyPaste
- channel := ^peer.channels[command.channel];
+ channel := &peer.channels[command.channel];
for channel.reliable_windows {
if command.seq_number == it do return;
}
channel.reliable_windows_cursor %= channel.reliable_windows.count;
fragment_id := net.network_to_host(command.fragment_id);
- fragment: ^Fragmented_Data = array.first(channel.pending_fragments, #(it.fragment_id == fragment_id));
+ fragment: &Fragmented_Data = array.first(channel.pending_fragments, #(it.fragment_id == fragment_id));
if fragment == null {
- fragment = array.alloc_one(^channel.pending_fragments);
+ fragment = array.alloc_one(&channel.pending_fragments);
fragment.fragment_id = fragment_id;
fragment.fragments_remaining = net.network_to_host(command.fragment_count);
fragment.data = make([] u8, net.network_to_host(command.total_length));
if fragment.fragments_remaining == 0 {
host_notify_message(host, peer, command.channel, fragment.data);
- for iter.as_iter(^channel.pending_fragments, by_pointer=true) {
+ for iter.as_iter(&channel.pending_fragments, by_pointer=true) {
if it.fragment_id == fragment_id {
#remove;
break;
}
type: Type;
- peer: ^Peer;
+ peer: &Peer;
channel_id: Channel_ID;
timestamp: u32;
data: [] u8;
}
Peer :: struct {
- host: ^Host;
+ host: &Host;
state: Peer_State;
addr: net.Socket_Address;
incoming_reliable_seq_number: u16;
outgoing_unsequenced_group: u32;
- outgoing_commands: [..] ^Outgoing_Command;
- incoming_commands: [..] ^Incoming_Command;
+ outgoing_commands: [..] &Outgoing_Command;
+ incoming_commands: [..] &Incoming_Command;
acknowledgements: [..] Acknowledgement;
- sent_reliable_commands: [..] ^Outgoing_Command;
+ sent_reliable_commands: [..] &Outgoing_Command;
}
-peer_destroy :: (peer: ^Peer) {
- if peer.channels.data != null do delete(^peer.channels);
- if peer.outgoing_commands.data != null do delete(^peer.outgoing_commands);
- if peer.incoming_commands.data != null do delete(^peer.incoming_commands);
+peer_destroy :: (peer: &Peer) {
+ if peer.channels.data != null do delete(&peer.channels);
+ if peer.outgoing_commands.data != null do delete(&peer.outgoing_commands);
+ if peer.incoming_commands.data != null do delete(&peer.incoming_commands);
}
-peer_disconnect :: (peer: ^Peer) {
+peer_disconnect :: (peer: &Peer) {
if peer.state == .Disconnected do return;
peer.state = .Disconnected;
peer_destroy(peer);
}
-peer_setup_channel :: (peer: ^Peer, channel: ^Channel) {
+peer_setup_channel :: (peer: &Peer, channel: &Channel) {
channel.id = ~~((cast(u32) channel - cast(u32) peer.channels.data) / 4);
channel.outgoing_reliable_seq_number = 0;
channel.reliable_windows_cursor = 0;
}
peer_queue_outgoing_command :: #match {
- (peer: ^Peer, command: ^Protocol_Command_Header, packet: ^Packet = null) -> ^Outgoing_Command {
+ (peer: &Peer, command: &Protocol_Command_Header, packet: &Packet = null) -> &Outgoing_Command {
out := new(Outgoing_Command);
out.command = command;
out.packet = packet;
}
}
-peer_setup_outgoing_command :: (peer: ^Peer, command: ^Outgoing_Command) {
+peer_setup_outgoing_command :: (peer: &Peer, command: &Outgoing_Command) {
if command.command.channel == 255 {
peer.outgoing_reliable_seq_number += 1;
command.reliable_seq_number = peer.outgoing_reliable_seq_number;
command.unreliable_seq_number = 0;
} else {
- channel := ^peer.channels[command.command.channel];
+ channel := &peer.channels[command.command.channel];
// Oof... That's a long chain of command.
if (command.command.command & .Flag_Acknowledge) != 0 {
peer.outgoing_commands << command;
}
-peer_send :: (peer: ^Peer, channel_id: Channel_ID, packet: ^Packet) -> bool {
+peer_send :: (peer: &Peer, channel_id: Channel_ID, packet: &Packet) -> bool {
if peer.state != .Connected || ~~channel_id > peer.channels.count {
return false;
}
- channel := ^peer.channels[channel_id];
+ channel := &peer.channels[channel_id];
if packet.data.count > peer.mtu - sizeof Protocol_Header - sizeof Protocol_Send {
data_per_packet := peer.mtu - sizeof Protocol_Header - sizeof Protocol_Send_Fragment;
return peer_queue_outgoing_command(peer, command, packet) != null;
}
-peer_queue_acknowledgement :: (peer: ^Peer, command: ^Protocol_Command_Header, sent_time: u16) {
+peer_queue_acknowledgement :: (peer: &Peer, command: &Protocol_Command_Header, sent_time: u16) {
peer.acknowledgements << .{ sent_time, command };
}
-peer_check_outgoing_commands :: (peer: ^Peer) {
- for iter.as_iter(^peer.sent_reliable_commands) {
+peer_check_outgoing_commands :: (peer: &Peer) {
+ for iter.as_iter(&peer.sent_reliable_commands) {
time_diff := math.abs(cast(i64) it.sent_time - cast(i64) peer.host.current_time);
if time_diff >= ~~ peer.no_ack_resend_timeout {
peer.outgoing_commands << it;
}
}
-peer_flush_outgoing_commands :: (peer: ^Peer) -> i32 {
+peer_flush_outgoing_commands :: (peer: &Peer) -> i32 {
send_buffer := alloc.array_from_stack(u8, 65535);
total_sent := 0;
to_send, success := it->pack_into_buffer(peer, send_buffer);
if !success do continue;
- sent_bytes := peer.host.socket->sendto(to_send, ^peer.addr);
+ sent_bytes := peer.host.socket->sendto(to_send, &peer.addr);
if sent_bytes < 0 {
return -1;
}
}
}
- array.clear(^peer.outgoing_commands);
+ array.clear(&peer.outgoing_commands);
return total_sent;
}
-peer_send_acknowledgements :: (peer: ^Peer) {
+peer_send_acknowledgements :: (peer: &Peer) {
send_buffer: [65535] u8;
bytes_to_be_sent := 0;
- for ^ack: peer.acknowledgements {
+ for &ack: peer.acknowledgements {
seq_num := net.host_to_network(ack.command.seq_number);
command: Protocol_Acknowledge;
command.recv_sent_time = net.host_to_network(ack.sent_time);
out: Outgoing_Command;
- out.command = ^command;
+ out.command = &command;
to_send, success := out->pack_into_buffer(peer, send_buffer[bytes_to_be_sent..65535]);
if !success do continue;
bytes_to_be_sent += to_send.count;
if bytes_to_be_sent >= peer.mtu - sizeof Protocol_Acknowledge {
- sent_bytes := peer.host.socket->sendto(send_buffer[0 .. bytes_to_be_sent], ^peer.addr);
+ sent_bytes := peer.host.socket->sendto(send_buffer[0 .. bytes_to_be_sent], &peer.addr);
if sent_bytes < 0 do return;
bytes_to_be_sent = 0;
}
if bytes_to_be_sent > 0 {
- sent_bytes := peer.host.socket->sendto(send_buffer[0 .. bytes_to_be_sent], ^peer.addr);
+ sent_bytes := peer.host.socket->sendto(send_buffer[0 .. bytes_to_be_sent], &peer.addr);
if sent_bytes < 0 do return;
}
- array.clear(^peer.acknowledgements);
+ array.clear(&peer.acknowledgements);
}
-peer_send_ping :: (peer: ^Peer) {
+peer_send_ping :: (peer: &Peer) {
for peer.sent_reliable_commands {
if command_get_effective(it.command.command) == .Ping do return;
}
peer_queue_outgoing_command(peer, ping);
}
-peer_send_disconnect :: (peer: ^Peer) {
+peer_send_disconnect :: (peer: &Peer) {
disconnect := new(Protocol_Disconnect);
disconnect.command = .Disconnect;
disconnect.channel = 255;
peer_queue_outgoing_command(peer, disconnect);
}
-peer_remove_sent_reliable_command :: (peer: ^Peer, seq_num: u16, channel: Channel_ID) -> Command {
- command: ^Outgoing_Command;
- for iter.as_iter(^peer.sent_reliable_commands) {
+peer_remove_sent_reliable_command :: (peer: &Peer, seq_num: u16, channel: Channel_ID) -> Command {
+ command: &Outgoing_Command;
+ for iter.as_iter(&peer.sent_reliable_commands) {
if it.reliable_seq_number == seq_num && it.command.channel == channel {
command = it;
#remove;
return command_get_effective(command.command.command);
}
-peer_free_outgoing_command :: (peer: ^Peer, command: ^Outgoing_Command) {
+peer_free_outgoing_command :: (peer: &Peer, command: &Outgoing_Command) {
if command.packet != null {
command.packet.reference_count -= 1;
if command.packet.reference_count <= 0 {