Skip to content

Commit

Permalink
Add a proper send mode for Notify messages
Browse files Browse the repository at this point in the history
  • Loading branch information
tom-weiland committed Nov 24, 2023
1 parent 7484431 commit 4b42723
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 43 deletions.
9 changes: 2 additions & 7 deletions RiptideNetworking/RiptideNetworking/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,13 +291,8 @@ protected override void Handle(Message message, MessageHeader header, Connection
}

/// <summary>Sends a message to the server.</summary>
/// <param name="message">The message to send.</param>
/// <param name="shouldRelease">Whether or not to return the message to the pool after it is sent.</param>
/// <remarks>
/// If you intend to continue using the message instance after calling this method, you <i>must</i> set <paramref name="shouldRelease"/>
/// to <see langword="false"/>. <see cref="Message.Release"/> can be used to manually return the message to the pool at a later time.
/// </remarks>
public void Send(Message message, bool shouldRelease = true) => connection.Send(message, shouldRelease);
/// <inheritdoc cref="Connection.Send(Message, bool)"/>
public ushort Send(Message message, bool shouldRelease = true) => connection.Send(message, shouldRelease);

/// <summary>Disconnects from the server.</summary>
public void Disconnect()
Expand Down
39 changes: 19 additions & 20 deletions RiptideNetworking/RiptideNetworking/Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,25 @@ public void ResetTimeout()
}

/// <summary>Sends a message.</summary>
/// <inheritdoc cref="Client.Send(Message, bool)"/>
internal void Send(Message message, bool shouldRelease = true)
/// <param name="message">The message to send.</param>
/// <param name="shouldRelease">Whether or not to return the message to the pool after it is sent.</param>
/// <returns>For reliable and notify messages, the sequence ID that the message was sent with. 0 for unreliable messages.</returns>
/// <remarks>
/// If you intend to continue using the message instance after calling this method, you <i>must</i> set <paramref name="shouldRelease"/>
/// to <see langword="false"/>. <see cref="Message.Release"/> can be used to manually return the message to the pool at a later time.
/// </remarks>
public ushort Send(Message message, bool shouldRelease = true)
{
if (message.SendMode == MessageSendMode.Unreliable)
ushort sequenceId = 0;
if (message.SendMode == MessageSendMode.Notify)
{
sequenceId = notify.InsertHeader(message);
int byteAmount = message.BytesInUse;
Buffer.BlockCopy(message.Data, 0, Message.ByteBuffer, 0, byteAmount);
Send(Message.ByteBuffer, byteAmount);
Metrics.SentNotify(byteAmount);
}
else if (message.SendMode == MessageSendMode.Unreliable)
{
int byteAmount = message.BytesInUse;
Buffer.BlockCopy(message.Data, 0, Message.ByteBuffer, 0, byteAmount);
Expand All @@ -157,29 +172,13 @@ internal void Send(Message message, bool shouldRelease = true)
}
else
{
ushort sequenceId = reliable.NextSequenceId;
sequenceId = reliable.NextSequenceId;
PendingMessage pendingMessage = PendingMessage.Create(sequenceId, message, this);
pendingMessages.Add(sequenceId, pendingMessage);
pendingMessage.TrySend();
Metrics.ReliableUniques++;
}

if (shouldRelease)
message.Release();
}

/// <summary>Sends a notify message.</summary>
/// <param name="message">The message to send.</param>
/// <param name="shouldRelease">Whether or not to return the message to the pool after it is sent.</param>
/// <returns>The sequence ID of the sent message.</returns>
public ushort SendNotify(Message message, bool shouldRelease = true)
{
ushort sequenceId = notify.InsertHeader(message);
int byteAmount = message.BytesInUse;
Buffer.BlockCopy(message.Data, 0, Message.ByteBuffer, 0, byteAmount);
Send(Message.ByteBuffer, byteAmount);
Metrics.SentNotify(byteAmount);

if (shouldRelease)
message.Release();

Expand Down
25 changes: 15 additions & 10 deletions RiptideNetworking/RiptideNetworking/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ namespace Riptide
/// <summary>The send mode of a <see cref="Message"/>.</summary>
public enum MessageSendMode : byte
{
/// <summary>Unreliable send mode.</summary>
/// <summary>Guarantees order but not delivery. Notifies the sender of what happened via the <see cref="Connection.NotifyDelivered"/> and <see cref="Connection.NotifyLost"/>
/// events. The receiver must handle notify messages via the <see cref="Connection.NotifyReceived"/> event, <i>which is different from the other two send modes</i>.</summary>
Notify = MessageHeader.Notify,
/// <summary>Guarantees neither delivery nor order.</summary>
Unreliable = MessageHeader.Unreliable,
/// <summary>Reliable send mode.</summary>
/// <summary>Guarantees delivery but not order.</summary>
Reliable = MessageHeader.Reliable,
}

Expand Down Expand Up @@ -137,6 +140,15 @@ public static Message Create()
}
/// <summary>Gets a message instance that can be used for sending.</summary>
/// <param name="sendMode">The mode in which the message should be sent.</param>
/// <returns>A message instance ready to be sent.</returns>
/// <remarks>This method is primarily intended for use with <see cref="MessageSendMode.Notify"/> as notify messages don't have a built-in message ID, and unlike
/// <see cref="Create(MessageSendMode, ushort)"/> and <see cref="Create(MessageSendMode, Enum)"/>, this overload does not add a message ID to the message.</remarks>
public static Message Create(MessageSendMode sendMode)
{
return RetrieveFromPool().Init((MessageHeader)sendMode);
}
/// <summary>Gets a message instance that can be used for sending.</summary>
/// <param name="sendMode">The mode in which the message should be sent.</param>
/// <param name="id">The message ID.</param>
/// <returns>A message instance ready to be sent.</returns>
public static Message Create(MessageSendMode sendMode, ushort id)
Expand All @@ -157,13 +169,6 @@ internal static Message Create(MessageHeader header)
return RetrieveFromPool().Init(header);
}

/// <summary>Gets a notify message instance that can be used for sending.</summary>
/// <returns>A notify message instance ready to be sent.</returns>
public static Message CreateNotify()
{
return RetrieveFromPool().Init(MessageHeader.Notify);
}

#region Pooling
/// <summary>Trims the message pool to a more appropriate size for how many <see cref="Server"/> and/or <see cref="Client"/> instances are currently running.</summary>
public static void TrimPool()
Expand Down Expand Up @@ -246,7 +251,7 @@ private void SetHeader(MessageHeader header)
{
readBit = NotifyHeaderBits;
writeBit = NotifyHeaderBits;
SendMode = MessageSendMode.Unreliable; // Technically it's different but notify messages *are* still unreliable
SendMode = MessageSendMode.Notify;
}
else if (header >= MessageHeader.Reliable)
{
Expand Down
2 changes: 1 addition & 1 deletion RiptideNetworking/RiptideNetworking/Peer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ protected void HandleData(object _, DataReceivedEventArgs e)
{
Message message = Message.Create().Init(e.DataBuffer[0], e.Amount, out MessageHeader header);

if (header == MessageHeader.Notify)
if (message.SendMode == MessageSendMode.Notify)
{
if (e.Amount < Message.MinNotifyBytes)
return;
Expand Down
10 changes: 5 additions & 5 deletions RiptideNetworking/RiptideNetworking/Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ protected override void Handle(Message message, MessageHeader header, Connection
/// <param name="message">The message to send.</param>
/// <param name="toClient">The numeric ID of the client to send the message to.</param>
/// <param name="shouldRelease">Whether or not to return the message to the pool after it is sent.</param>
/// <inheritdoc cref="Client.Send(Message, bool)"/>
/// <inheritdoc cref="Connection.Send(Message, bool)"/>
public void Send(Message message, ushort toClient, bool shouldRelease = true)
{
if (clients.TryGetValue(toClient, out Connection connection))
Expand All @@ -357,13 +357,13 @@ public void Send(Message message, ushort toClient, bool shouldRelease = true)
/// <param name="message">The message to send.</param>
/// <param name="toClient">The client to send the message to.</param>
/// <param name="shouldRelease">Whether or not to return the message to the pool after it is sent.</param>
/// <inheritdoc cref="Client.Send(Message, bool)"/>
public void Send(Message message, Connection toClient, bool shouldRelease = true) => toClient.Send(message, shouldRelease);
/// <inheritdoc cref="Connection.Send(Message, bool)"/>
public ushort Send(Message message, Connection toClient, bool shouldRelease = true) => toClient.Send(message, shouldRelease);

/// <summary>Sends a message to all connected clients.</summary>
/// <param name="message">The message to send.</param>
/// <param name="shouldRelease">Whether or not to return the message to the pool after it is sent.</param>
/// <inheritdoc cref="Client.Send(Message, bool)"/>
/// <inheritdoc cref="Connection.Send(Message, bool)"/>
public void SendToAll(Message message, bool shouldRelease = true)
{
foreach (Connection client in clients.Values)
Expand All @@ -376,7 +376,7 @@ public void SendToAll(Message message, bool shouldRelease = true)
/// <param name="message">The message to send.</param>
/// <param name="exceptToClientId">The numeric ID of the client to <i>not</i> send the message to.</param>
/// <param name="shouldRelease">Whether or not to return the message to the pool after it is sent.</param>
/// <inheritdoc cref="Client.Send(Message, bool)"/>
/// <inheritdoc cref="Connection.Send(Message, bool)"/>
public void SendToAll(Message message, ushort exceptToClientId, bool shouldRelease = true)
{
foreach (Connection client in clients.Values)
Expand Down

0 comments on commit 4b42723

Please sign in to comment.