From e4f58e4aef4b720187cfdf995653ff1a1b983524 Mon Sep 17 00:00:00 2001 From: Forest Date: Mon, 16 Jul 2018 13:12:21 -0700 Subject: [PATCH] Add send bytes subset overload for SendBytes --- Hazel.UnitTests/UdpConnectionTests.cs | 25 +++++++++- Hazel/Connection.cs | 17 +++++++ Hazel/Udp/UdpClientConnection.cs | 2 +- Hazel/Udp/UdpConnection.Fragmented.cs | 3 +- Hazel/Udp/UdpConnection.Reliable.cs | 24 ++++++++-- Hazel/Udp/UdpConnection.cs | 69 ++++++++++++++++++++++++--- 6 files changed, 124 insertions(+), 16 deletions(-) diff --git a/Hazel.UnitTests/UdpConnectionTests.cs b/Hazel.UnitTests/UdpConnectionTests.cs index 7216fb4..2adcd83 100644 --- a/Hazel.UnitTests/UdpConnectionTests.cs +++ b/Hazel.UnitTests/UdpConnectionTests.cs @@ -53,6 +53,27 @@ namespace Hazel.UnitTests } } + + [TestMethod] + public void UdpUnreliableDataSubsetSendTest() + { + using (UdpConnectionListener listener = new UdpConnectionListener(new NetworkEndPoint(IPAddress.Any, 4296, IPMode.IPv4))) + using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296, IPMode.IPv4))) + { + listener.Start(); + listener.NewConnection += delegate (object sender, NewConnectionEventArgs e) + { + e.Connection.DataReceived += delegate (object s, DataReceivedEventArgs evt) + { + Assert.IsTrue(Enumerable.SequenceEqual(evt.Bytes, new byte[] { 3, 4 })); + }; + }; + + connection.Connect(); + connection.SendBytes(new byte[] { 1, 2, 3, 4, 5, 6 }, 2, 2, SendOption.None); + } + } + /// /// Tests IPv4 connectivity. /// @@ -120,7 +141,7 @@ namespace Hazel.UnitTests using (UdpConnectionListener listener = new UdpConnectionListener(new NetworkEndPoint(IPAddress.Any, 4296))) using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { - TestHelper.RunServerToClientTest(listener, connection, (int)(connection.FragmentSize * 9.5), SendOption.FragmentedReliable); + TestHelper.RunServerToClientTest(listener, connection, (int)(UdpConnection.FragmentSize * 9.5), SendOption.FragmentedReliable); } } @@ -159,7 +180,7 @@ namespace Hazel.UnitTests using (UdpConnectionListener listener = new UdpConnectionListener(new NetworkEndPoint(IPAddress.Any, 4296))) using (UdpConnection connection = new UdpClientConnection(new NetworkEndPoint(IPAddress.Loopback, 4296))) { - TestHelper.RunClientToServerTest(listener, connection, (int)(connection.FragmentSize * 9.5), SendOption.FragmentedReliable); + TestHelper.RunClientToServerTest(listener, connection, (int)(UdpConnection.FragmentSize * 9.5), SendOption.FragmentedReliable); } } diff --git a/Hazel/Connection.cs b/Hazel/Connection.cs index 7bc9d57..12c35dd 100644 --- a/Hazel/Connection.cs +++ b/Hazel/Connection.cs @@ -158,6 +158,23 @@ namespace Hazel /// public abstract void SendBytes(byte[] bytes, SendOption sendOption = SendOption.None); + /// + /// Sends a number of bytes to the end point of the connection using the specified . + /// + /// The bytes of the message to send. + /// + /// + /// The option specifying how the message should be sent. + /// + /// + /// + /// The sendOptions parameter is only a request to use those options and the actual method used to send the + /// data is up to the implementation. There are circumstances where this parameter may be ignored but in + /// general any implementer should aim to always follow the user's request. + /// + /// + public abstract void SendBytes(byte[] bytes, int offset, int length, SendOption sendOption = SendOption.None); + /// /// Connects the connection to a server and begins listening. /// diff --git a/Hazel/Udp/UdpClientConnection.cs b/Hazel/Udp/UdpClientConnection.cs index 0291c02..2f5dfa1 100644 --- a/Hazel/Udp/UdpClientConnection.cs +++ b/Hazel/Udp/UdpClientConnection.cs @@ -202,7 +202,7 @@ namespace Hazel.Udp //Copy data to new array byte[] bytes = new byte[bytesReceived]; Buffer.BlockCopy(dataBuffer, 0, bytes, 0, bytesReceived); - + //Begin receiving again try { diff --git a/Hazel/Udp/UdpConnection.Fragmented.cs b/Hazel/Udp/UdpConnection.Fragmented.cs index 463fbef..209eb8d 100644 --- a/Hazel/Udp/UdpConnection.Fragmented.cs +++ b/Hazel/Udp/UdpConnection.Fragmented.cs @@ -10,8 +10,7 @@ namespace Hazel.Udp /// /// The amount of data that can be put into a fragment. /// - public int FragmentSize { get { return fragmentSize; } } - int fragmentSize = 65507 - 1 - 2 - 2 - 2; + public const int FragmentSize = 65507 - 1 - 2 - 2 - 2; /// /// The last fragmented message ID that was written. diff --git a/Hazel/Udp/UdpConnection.Reliable.cs b/Hazel/Udp/UdpConnection.Reliable.cs index 0b3cdd5..fd40398 100644 --- a/Hazel/Udp/UdpConnection.Reliable.cs +++ b/Hazel/Udp/UdpConnection.Reliable.cs @@ -247,25 +247,39 @@ namespace Hazel.Udp /// /// Sends the bytes reliably and stores the send. /// - /// The byte array to write to. + /// + /// The byte array to write to. /// The callback to make once the packet has been acknowledged. void ReliableSend(byte sendOption, byte[] data, Action ackCallback = null) { - byte[] bytes = new byte[data.Length + 3]; + this.ReliableSend(sendOption, data, 0, data.Length, ackCallback); + } + + /// + /// Sends the bytes reliably and stores the send. + /// + /// + /// The byte array to write to. + /// + /// + /// The callback to make once the packet has been acknowledged. + void ReliableSend(byte sendOption, byte[] data, int offset, int length, Action ackCallback = null) + { + byte[] bytes = new byte[length + 3]; //Add message type bytes[0] = sendOption; //Add reliable ID AttachReliableID(bytes, 1, ackCallback); - + //Copy data into new array - Buffer.BlockCopy(data, 0, bytes, bytes.Length - data.Length, data.Length); + Buffer.BlockCopy(data, offset, bytes, bytes.Length - length, length); //Write to connection WriteBytesToConnection(bytes); - Statistics.LogReliableSend(data.Length, bytes.Length); + Statistics.LogReliableSend(length, bytes.Length); } /// diff --git a/Hazel/Udp/UdpConnection.cs b/Hazel/Udp/UdpConnection.cs index 6f97d2d..7f4c22d 100644 --- a/Hazel/Udp/UdpConnection.cs +++ b/Hazel/Udp/UdpConnection.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; @@ -47,6 +48,50 @@ namespace Hazel.Udp HandleSend(bytes, (byte)sendOption); } + /// + /// Sends a number of bytes to the end point of the connection using the specified . + /// + /// The bytes of the message to send. + /// + /// + /// The option specifying how the message should be sent. + /// + /// + /// + /// The sendOptions parameter is only a request to use those options and the actual method used to send the + /// data is up to the implementation. There are circumstances where this parameter may be ignored but in + /// general any implementer should aim to always follow the user's request. + /// + /// + public override void SendBytes(byte[] bytes, int offset, int length, SendOption sendOption = SendOption.None) + { + //Early check + if (State != ConnectionState.Connected) + throw new InvalidOperationException("Could not send data as this Connection is not connected. Did you disconnect?"); + + + //Inform keepalive not to send for a while + ResetKeepAliveTimer(); + + switch (sendOption) + { + //Handle reliable header and hellos + case SendOption.Reliable: + ReliableSend((byte)sendOption, bytes, offset, length); + break; + + case SendOption.FragmentedReliable: + throw new NotImplementedException(); + // FragmentedSend(data); + // break; + + //Treat all else as unreliable + default: + UnreliableSend((byte)sendOption, bytes, offset, length); + break; + } + } + /// /// Handles the reliable/fragmented sending from this connection. /// @@ -73,7 +118,7 @@ namespace Hazel.Udp //Treat all else as unreliable default: - UnreliableSend(data, sendOption); + UnreliableSend(sendOption, data); break; } } @@ -126,25 +171,37 @@ namespace Hazel.Udp } } + /// + /// Sends bytes using the unreliable UDP protocol. + /// + /// The SendOption to attach. + /// The data. + void UnreliableSend(byte sendOption, byte[] data) + { + this.UnreliableSend(sendOption, data, 0, data.Length); + } + /// /// Sends bytes using the unreliable UDP protocol. /// /// The data. /// The SendOption to attach. - void UnreliableSend(byte[] data, byte sendOption) + /// + /// + void UnreliableSend(byte sendOption, byte[] data, int offset, int length) { - byte[] bytes = new byte[data.Length + 1]; + byte[] bytes = new byte[length + 1]; //Add message type bytes[0] = sendOption; - + //Copy data into new array - Buffer.BlockCopy(data, 0, bytes, bytes.Length - data.Length, data.Length); + Buffer.BlockCopy(data, offset, bytes, bytes.Length - length, length); //Write to connection WriteBytesToConnection(bytes); - Statistics.LogUnreliableSend(data.Length, bytes.Length); + Statistics.LogUnreliableSend(length, bytes.Length); } /// -- 2.39.5