Packages

ENet - Reliable UDP networking library

Current section

Files

Jump to
enet src enet_command.erl
Raw

src/enet_command.erl

-module(enet_command).
-include("enet_commands.hrl").
-include("enet_protocol.hrl").
-export([
acknowledge/2,
connect/12,
verify_connect/8,
sequenced_disconnect/0,
unsequenced_disconnect/0,
ping/0,
send_unsequenced/2,
send_unreliable/3,
send_reliable/3
]).
acknowledge(H = #command_header{}, SentTime) ->
#command_header{
channel_id = ChannelID,
reliable_sequence_number = N
} = H,
{
#command_header{
command = ?COMMAND_ACKNOWLEDGE,
channel_id = ChannelID
},
#acknowledge{
received_reliable_sequence_number = N,
received_sent_time = SentTime
}
}.
connect(
OutgoingPeerID,
IncomingSessionID,
OutgoingSessionID,
ChannelCount,
MTU,
IncomingBandwidth,
OutgoingBandwidth,
PacketThrottleInterval,
PacketThrottleAcceleration,
PacketThrottleDeceleration,
ConnectID,
OutgoingReliableSequenceNumber
) ->
WindowSize = calculate_initial_window_size(OutgoingBandwidth),
{
#command_header{
command = ?COMMAND_CONNECT,
please_acknowledge = 1,
reliable_sequence_number = OutgoingReliableSequenceNumber
},
#connect{
outgoing_peer_id = OutgoingPeerID,
incoming_session_id = IncomingSessionID,
outgoing_session_id = OutgoingSessionID,
mtu = MTU,
window_size = WindowSize,
channel_count = ChannelCount,
incoming_bandwidth = IncomingBandwidth,
outgoing_bandwidth = OutgoingBandwidth,
packet_throttle_interval = PacketThrottleInterval,
packet_throttle_acceleration = PacketThrottleAcceleration,
packet_throttle_deceleration = PacketThrottleDeceleration,
connect_id = ConnectID,
%% What is this used for?
data = 0
}
}.
verify_connect(
C = #connect{},
OutgoingPeerID,
IncomingSessionID,
OutgoingSessionID,
HostChannelLimit,
IncomingBandwidth,
OutgoingBandwidth,
OutgoingReliableSequenceNumber
) ->
WindowSize =
calculate_window_size(IncomingBandwidth, C#connect.window_size),
ISID =
calculate_session_id(C#connect.incoming_session_id, OutgoingSessionID),
OSID =
calculate_session_id(C#connect.outgoing_session_id, IncomingSessionID),
{
#command_header{
command = ?COMMAND_VERIFY_CONNECT,
please_acknowledge = 1,
reliable_sequence_number = OutgoingReliableSequenceNumber
},
#verify_connect{
outgoing_peer_id = OutgoingPeerID,
incoming_session_id = ISID,
outgoing_session_id = OSID,
mtu = clamp(C#connect.mtu, ?MAX_MTU, ?MIN_MTU),
window_size = WindowSize,
channel_count = min(C#connect.channel_count, HostChannelLimit),
incoming_bandwidth = IncomingBandwidth,
outgoing_bandwidth = OutgoingBandwidth,
packet_throttle_interval = C#connect.packet_throttle_interval,
packet_throttle_acceleration =
C#connect.packet_throttle_acceleration,
packet_throttle_deceleration =
C#connect.packet_throttle_deceleration,
connect_id = C#connect.connect_id
}
}.
sequenced_disconnect() ->
{
#command_header{
please_acknowledge = 1,
command = ?COMMAND_DISCONNECT
},
#disconnect{}
}.
unsequenced_disconnect() ->
{
#command_header{
unsequenced = 1,
command = ?COMMAND_DISCONNECT
},
#disconnect{}
}.
ping() ->
{
#command_header{
unsequenced = 1,
command = ?COMMAND_PING
},
#ping{}
}.
send_unsequenced(ChannelID, Data) ->
{
#command_header{
unsequenced = 1,
command = ?COMMAND_SEND_UNSEQUENCED,
channel_id = ChannelID
},
#unsequenced{
data = Data
}
}.
send_unreliable(ChannelID, SequenceNumber, Data) ->
{
#command_header{
command = ?COMMAND_SEND_UNRELIABLE,
channel_id = ChannelID
},
#unreliable{
sequence_number = SequenceNumber,
data = Data
}
}.
send_reliable(ChannelID, ReliableSequenceNumber, Data) ->
{
#command_header{
please_acknowledge = 1,
command = ?COMMAND_SEND_RELIABLE,
channel_id = ChannelID,
reliable_sequence_number = ReliableSequenceNumber
},
#reliable{
data = Data
}
}.
%%%
%%% Internal functions
%%%
clamp(X, Max, Min) ->
max(Min, min(Max, X)).
select_smallest(A, B, Max, Min) ->
clamp(min(A, B), Max, Min).
calculate_window_size(0, ConnectWindowSize) ->
clamp(ConnectWindowSize, ?MAX_WINDOW_SIZE, ?MIN_WINDOW_SIZE);
calculate_window_size(IncomingBandwidth, ConnectWindowSize) ->
InitialWindowSize =
?MIN_WINDOW_SIZE * IncomingBandwidth / ?PEER_WINDOW_SIZE_SCALE,
select_smallest(
InitialWindowSize,
ConnectWindowSize,
?MAX_WINDOW_SIZE,
?MIN_WINDOW_SIZE
).
calculate_initial_window_size(0) ->
?MAX_WINDOW_SIZE;
calculate_initial_window_size(OutgoingBandwidth) ->
InitialWindowSize =
?MAX_WINDOW_SIZE * OutgoingBandwidth / ?PEER_WINDOW_SIZE_SCALE,
clamp(InitialWindowSize, ?MAX_WINDOW_SIZE, ?MIN_WINDOW_SIZE).
calculate_session_id(ConnectSessionID, PeerSessionID) ->
InitialSessionID =
case ConnectSessionID of
16#FF -> PeerSessionID;
_ -> ConnectSessionID
end,
case (InitialSessionID + 1) band 2#11 of
PeerSessionID -> (PeerSessionID + 1) band 2#11;
IncomingSessionID -> IncomingSessionID
end.