]> git.deb.at Git - rhonda/impostor.hazel.git/commitdiff
Lots of good stuff. Should have committed earlier
authorForest <chocozilla@gmail.com>
Fri, 20 Jul 2018 00:27:29 +0000 (17:27 -0700)
committerForest <chocozilla@gmail.com>
Fri, 20 Jul 2018 00:27:29 +0000 (17:27 -0700)
13 files changed:
Hazel.UnitTests/BroadcastTests.cs
Hazel.UnitTests/Hazel.UnitTests.csproj
Hazel.UnitTests/MessageWriterTests.cs [new file with mode: 0644]
Hazel.UnitTests/UdpConnectionTests.cs
Hazel/BinaryReaderExtensions.cs [new file with mode: 0644]
Hazel/BinaryWriterExtensions.cs [deleted file]
Hazel/Connection.cs
Hazel/Hazel.csproj
Hazel/MessageWriter.cs
Hazel/Udp/UdpClientConnection.cs
Hazel/Udp/UdpConnection.Reliable.cs
Hazel/Udp/UdpConnection.cs
Hazel/Udp/UdpServerConnection.cs

index 53b313917e41285713e656e95e41bfd04d438a5a..d9164463f7e1b2301ff45a79aa82002a178290c0 100644 (file)
@@ -15,8 +15,8 @@ namespace Hazel.UnitTests
         {
             const string TestData = "pwerowerower";
 
-            using (UdpBroadcaster caster = new UdpBroadcaster(47777))
-            using (UdpBroadcastListener listener = new UdpBroadcastListener(47777))
+            using (UdpBroadcaster caster = new UdpBroadcaster(4777))
+            using (UdpBroadcastListener listener = new UdpBroadcastListener(4777))
             {
                 listener.StartListen();
 
index 73dbb50833794732a3221e433600eceacdf5676a..b14bdd5e145a5a43cd779aba6352e7f27e60bdd0 100644 (file)
@@ -58,6 +58,7 @@
     <Compile Include="TestHelper.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="UdpConnectionTests.cs" />
+    <Compile Include="MessageWriterTests.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\Hazel\Hazel.csproj">
diff --git a/Hazel.UnitTests/MessageWriterTests.cs b/Hazel.UnitTests/MessageWriterTests.cs
new file mode 100644 (file)
index 0000000..571808a
--- /dev/null
@@ -0,0 +1,114 @@
+using System;
+using System.IO;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Hazel.UnitTests
+{
+    [TestClass]
+    public class MessageWriterTests
+    {
+        [TestMethod]
+        public void WriteProperInt()
+        {
+            const int Test1 = int.MaxValue;
+            const int Test2 = int.MinValue;
+
+            var msg = new MessageWriter(128);
+            msg.Write(Test1);
+            msg.Write(Test2);
+
+            Assert.AreEqual(8, msg.Length);
+            Assert.AreEqual(msg.Length, msg.Position);
+
+            using (MemoryStream m = new MemoryStream(msg.Buffer, 0, msg.Length))
+            using (BinaryReader reader = new BinaryReader(m))
+            {
+                Assert.AreEqual(Test1, reader.ReadInt32());
+                Assert.AreEqual(Test2, reader.ReadInt32());
+            }
+        }
+
+        [TestMethod]
+        public void WriteProperBool()
+        {
+            const bool Test1 = true;
+            const bool Test2 = false;
+
+            var msg = new MessageWriter(128);
+            msg.Write(Test1);
+            msg.Write(Test2);
+
+            Assert.AreEqual(2, msg.Length);
+            Assert.AreEqual(msg.Length, msg.Position);
+
+            using (MemoryStream m = new MemoryStream(msg.Buffer, 0, msg.Length))
+            using (BinaryReader reader = new BinaryReader(m))
+            {
+                Assert.AreEqual(Test1, reader.ReadBoolean());
+                Assert.AreEqual(Test2, reader.ReadBoolean());
+            }
+        }
+
+        [TestMethod]
+        public void WriteProperString()
+        {
+            const string Test1 = "Hello";
+            string Test2 = new string(' ', 1024);
+            var msg = new MessageWriter(2048);
+            msg.Write(Test1);
+            msg.Write(Test2);
+
+            Assert.AreEqual(msg.Length, msg.Position);
+
+            using (MemoryStream m = new MemoryStream(msg.Buffer, 0, msg.Length))
+            using (BinaryReader reader = new BinaryReader(m))
+            {
+                Assert.AreEqual(Test1, reader.ReadString());
+                Assert.AreEqual(Test2, reader.ReadString());
+            }
+        }
+
+        [TestMethod]
+        public void WriteProperFloat()
+        {
+            const float Test1 = 12.34f;
+
+            var msg = new MessageWriter(2048);
+            msg.Write(Test1);
+
+            Assert.AreEqual(msg.Length, msg.Position);
+
+            using (MemoryStream m = new MemoryStream(msg.Buffer, 0, msg.Length))
+            using (BinaryReader reader = new BinaryReader(m))
+            {
+                Assert.AreEqual(Test1, reader.ReadSingle());
+            }
+        }
+
+        [TestMethod]
+        public void WritesMessageLength()
+        {
+            var msg = new MessageWriter(2048);
+            msg.StartMessage(1);
+            msg.Write(65534);
+            msg.EndMessage();
+
+            Assert.AreEqual(2 + 1 + 4, msg.Position);
+            Assert.AreEqual(msg.Length, msg.Position);
+
+            using (MemoryStream m = new MemoryStream(msg.Buffer, 0, msg.Length))
+            using (BinaryReader reader = new BinaryReader(m))
+            {
+                Assert.AreEqual(4, reader.ReadUInt16()); // Length After Type and Target
+                Assert.AreEqual(1, reader.ReadByte()); // Type
+                Assert.AreEqual(65534, reader.ReadInt32()); // Content
+            }
+        }
+
+        [TestMethod]
+        public void GetLittleEndian()
+        {
+            Assert.IsTrue(MessageWriter.IsLittleEndian());
+        }
+    }
+}
index 2adcd83dc8ad8b006cdb1701d9d64921fe7e15ba..4ac8045c6a8fecd12f5f80e4af6ead41d8e43ecd 100644 (file)
@@ -53,6 +53,32 @@ namespace Hazel.UnitTests
             }
         }
 
+        [TestMethod]
+        public void UdpUnreliableMessageSendTest()
+        {
+            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.NewConnection += delegate (object sender, NewConnectionEventArgs e)
+                {
+                    e.Connection.DataReceived += delegate (object s, DataReceivedEventArgs evt)
+                    {
+                        Assert.IsTrue(Enumerable.SequenceEqual(evt.Bytes, new byte[] { 1, 2, 3, 4, 5, 6 }));
+                    };
+                };
+
+                listener.Start();
+                connection.Connect();
+
+                for (int i = 0; i < 4; ++i)
+                {
+                    var msg = MessageWriter.Get(SendOption.None);
+                    msg.Write(new byte[] { 1, 2, 3, 4, 5, 6 });
+                    connection.Send(msg);
+                    msg.Recycle();
+                }
+            }
+        }
 
         [TestMethod]
         public void UdpUnreliableDataSubsetSendTest()
diff --git a/Hazel/BinaryReaderExtensions.cs b/Hazel/BinaryReaderExtensions.cs
new file mode 100644 (file)
index 0000000..332f236
--- /dev/null
@@ -0,0 +1,48 @@
+using System.IO;
+
+namespace Hazel
+{
+    ///
+    public static class BinaryReaderExtensions
+    {
+        ///
+        public static uint ReadPackedUInt32(this BinaryReader reader)
+        {
+            bool readMore = true;
+            int shift = 0;
+            uint output = 0;
+
+            while (readMore)
+            {
+                byte b = reader.ReadByte();
+                if (b >= 0x80)
+                {
+                    readMore = true;
+                    b ^= 0x80;
+                }
+                else
+                {
+                    readMore = false;
+                }
+
+                output |= (uint)(b << shift);
+                shift += 7;
+            }
+
+            return output;
+        }
+
+        ///
+        public static int ReadPackedInt32(this BinaryReader reader)
+        {
+            return (int)reader.ReadPackedUInt32();
+        }
+
+        ///
+        public static byte[] ReadBytesAndSize(this BinaryReader reader)
+        {
+            int len = (int)reader.ReadPackedUInt32();
+            return reader.ReadBytes(len);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Hazel/BinaryWriterExtensions.cs b/Hazel/BinaryWriterExtensions.cs
deleted file mode 100644 (file)
index d5aeb22..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-using System.IO;
-
-namespace Hazel
-{
-    ///
-    public static class BinaryWriterExtensions
-    {
-        ///
-        public static void WritePacked(this BinaryWriter writer, uint value)
-        {
-            do
-            {
-                byte b = (byte)(value & 0xFF);
-                if (value >= 0x80)
-                {
-                    b |= 0x80;
-                }
-
-                writer.Write(b);
-                value >>= 7;
-            } while (value > 0);
-        }
-
-        ///
-        public static uint ReadPackedUInt32(this BinaryReader reader)
-        {
-            bool readMore = true;
-            int shift = 0;
-            uint output = 0;
-
-            while (readMore)
-            {
-                byte b = reader.ReadByte();
-                if (b >= 0x80)
-                {
-                    readMore = true;
-                    b ^= 0x80;
-                }
-                else
-                {
-                    readMore = false;
-                }
-
-                output |= (uint)(b << shift);
-                shift += 7;
-            }
-
-            return output;
-        }
-
-        ///
-        public static void WriteBytesFull(this BinaryWriter writer, byte[] bytes)
-        {
-            writer.WritePacked((uint)bytes.Length);
-            writer.Write(bytes);
-        }
-
-        ///
-        public static byte[] ReadBytesAndSize(this BinaryReader reader)
-        {
-            int len = (int)reader.ReadPackedUInt32();
-            return reader.ReadBytes(len);
-        }
-    }
-}
\ No newline at end of file
index 751795a7d3dcea96f7b70dff9d7721621af7b279..0f12223f7da97a3dd0264a7177616e1f151e9215 100644 (file)
@@ -50,6 +50,18 @@ namespace Hazel
         /// </example>
         public event EventHandler<DataReceivedEventArgs> DataReceived;
 
+        public event Action<byte[], int> DataSentRaw;
+        protected void InvokeDataSentRaw(byte[] data, int length)
+        {
+            this.DataSentRaw?.Invoke(data, length);
+        }
+
+        public event Action<byte[]> DataReceivedRaw;
+        protected void InvokeDataReceivedRaw(byte[] data)
+        {
+            this.DataReceivedRaw?.Invoke(data);
+        }
+
         /// <summary>
         ///     Called when the end point disconnects or an error occurs.
         /// </summary>
@@ -201,6 +213,19 @@ namespace Hazel
         /// </remarks>
         public abstract void Connect(byte[] bytes = null, int timeout = 5000);
 
+
+        /// <summary>
+        ///     Connects the connection to a server and begins listening.
+        /// </summary>
+        /// <param name="bytes">The bytes of data to send in the handshake.</param>
+        /// <param name="timeout">The number of milliseconds to wait before giving up on the connect attempt.</param>
+        /// <remarks>
+        ///     Calling Connect makes the connection attempt to connect to the end point that's specified in the 
+        ///     constructor. This method will block until the connection attempt completes and will throw a 
+        ///     <see cref="HazelException"/> if there is a problem connecting.
+        /// </remarks>
+        public abstract void ConnectAsync(byte[] bytes = null, int timeout = 5000);
+        
         /// <summary>
         ///     Invokes the DataReceived event.
         /// </summary>
index 24e67e93a595352a1e50e651e8b4ebd1bc466038..1172bb03a70d7bcc55ff6cc51d586bb8010e1c1b 100644 (file)
@@ -23,6 +23,7 @@
     <WarningLevel>4</WarningLevel>
     <DocumentationFile>
     </DocumentationFile>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
@@ -32,6 +33,7 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <DocumentationFile>bin\Release\Hazel.XML</DocumentationFile>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup>
     <SignAssembly>true</SignAssembly>
@@ -49,7 +51,7 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="BinaryWriterExtensions.cs" />
+    <Compile Include="BinaryReaderExtensions.cs" />
     <Compile Include="Connection.cs" />
     <Compile Include="ConnectionEndPoint.cs" />
     <Compile Include="ConnectionListener.cs" />
index 83902d9f1d24779dfeeae6d712a841359efcb748..3508688ee9c6b1620f698ee96b08245018167a53 100644 (file)
@@ -1,5 +1,7 @@
 using System;
+using System.Collections.Generic;
 using System.IO;
+using System.Text;
 
 namespace Hazel
 {
@@ -10,19 +12,17 @@ namespace Hazel
         private static readonly ObjectPool<MessageWriter> objectPool = new ObjectPool<MessageWriter>(() => new MessageWriter(BufferSize));
 
         internal byte[] Buffer;
-        internal MemoryStream Stream;
-        public readonly BinaryWriter Writer;
+        public int Length;
+        public int Position;
 
         public SendOption SendOption { get; private set; }
 
-        private long lastMessageStart;
-
+        private Stack<int> messageStarts = new Stack<int>();
+        
         ///
         public MessageWriter(int bufferSize)
         {
             this.Buffer = new byte[bufferSize];
-            this.Stream = new MemoryStream(this.Buffer, true);
-            this.Writer = new BinaryWriter(this.Stream);
         }
 
         ///
@@ -30,57 +30,169 @@ namespace Hazel
         public static MessageWriter Get(SendOption sendOption = SendOption.None)
         {
             var output = objectPool.GetObject();
-            output.SendOption = sendOption;
+            output.Clear(sendOption);
 
+            return output;
+        }
+
+        public bool HasBytes(int expected)
+        {
+            if (this.SendOption == SendOption.None)
+            {
+                return this.Length > 1 + expected;
+            }
+
+            return this.Length > 3 + expected;
+        }
+
+        ///
+        public void StartMessage(byte typeFlag)
+        {
+            messageStarts.Push(this.Position);
+            this.Position += 2; // Skip for size
+            this.Write(typeFlag);
+        }
+
+        ///
+        public void EndMessage()
+        {
+            var lastMessageStart = messageStarts.Pop();
+            ushort length = (ushort)(this.Position - lastMessageStart - 3); // Minus length and type byte
+            this.Buffer[lastMessageStart] = (byte)length;
+            this.Buffer[lastMessageStart + 1] = (byte)(length >> 8);
+        }
+
+        ///
+        public void CancelMessage()
+        {
+            this.Position = this.messageStarts.Pop();
+        }
+
+        public void Clear(SendOption sendOption)
+        {
+            this.Position = this.Length = 0;
+            this.SendOption = sendOption;
+
+            this.Buffer[0] = (byte)sendOption;
             switch (sendOption)
             {
                 case SendOption.None:
-                    output.Buffer[0] = (byte)sendOption;
-                    output.Stream.Position = 1; // Type
+                    this.Length = this.Position = 1;
                     break;
                 case SendOption.Reliable:
-                    output.Buffer[0] = (byte)sendOption;
-                    output.Stream.Position = 3; // Type + ID
+                    this.Length = this.Position = 3;
                     break;
                 case SendOption.FragmentedReliable:
                     throw new NotImplementedException("Sry bruh");
             }
-
-            return output;
         }
 
         ///
-        public void StartMessage(byte typeFlag, uint targetObjId)
+        public void Recycle()
         {
-            this.lastMessageStart = this.Stream.Position;
-            this.Stream.Position = this.lastMessageStart + 2;
+            this.Position = this.Length = 0;
+            objectPool.PutObject(this);
+        }
 
-            this.Writer.Write(typeFlag);
-            this.Writer.WritePacked(targetObjId);
+        #region WriteMethods
+        public void Write(bool value)
+        {
+            this.Buffer[this.Position++] = (byte)(value ? 1 : 0);
+            if (this.Position > this.Length) this.Length = this.Position;
         }
 
-        ///
-        public void EndMessage()
+        public void Write(byte value)
         {
-            this.Writer.Flush();
+            this.Buffer[this.Position++] = value;
+            if (this.Position > this.Length) this.Length = this.Position;
+        }
 
-            ushort length = (ushort)(this.Stream.Position - this.lastMessageStart);
-            this.Buffer[this.lastMessageStart] = (byte)(length >> 8);
-            this.Buffer[this.lastMessageStart + 1] = (byte)(length & 0xFF);
+        public void Write(short value)
+        {
+            this.Buffer[this.Position++] = (byte)value;
+            this.Buffer[this.Position++] = (byte)(value >> 8);
+            if (this.Position > this.Length) this.Length = this.Position;
+        }
+
+        public void Write(int value)
+        {
+            this.Buffer[this.Position++] = (byte)value;
+            this.Buffer[this.Position++] = (byte)(value >> 8);
+            this.Buffer[this.Position++] = (byte)(value >> 16);
+            this.Buffer[this.Position++] = (byte)(value >> 24);
+            if (this.Position > this.Length) this.Length = this.Position;
+        }
+
+        public unsafe void Write(float value)
+        {
+            fixed (byte* ptr = &this.Buffer[this.Position])
+            {
+                byte* valuePtr = (byte*)&value;
+
+                *ptr = *valuePtr;
+                *(ptr + 1) = *(valuePtr + 1);
+                *(ptr + 2) = *(valuePtr + 2);
+                *(ptr + 3) = *(valuePtr + 3);
+            }
+
+            this.Position += 4;
+            if (this.Position > this.Length) this.Length = this.Position;
+        }
+
+        public void Write(string value)
+        {
+            var bytes = UTF8Encoding.UTF8.GetBytes(value);
+            this.WritePacked(bytes.Length);
+            this.Write(bytes);
+        }
+
+        public void WriteBytesFull(byte[] bytes)
+        {
+            this.WritePacked((uint)bytes.Length);
+            this.Write(bytes);
+        }
+
+        public void Write(byte[] bytes)
+        {
+            Array.Copy(bytes, 0, this.Buffer, this.Position, bytes.Length);
+            this.Position += bytes.Length;
+            if (this.Position > this.Length) this.Length = this.Position;
         }
 
         ///
-        public void CancelMessage()
+        public void WritePacked(int value)
         {
-            this.Writer.Flush();
-            this.Stream.Position = this.lastMessageStart;
+            this.WritePacked((uint)value);
         }
 
         ///
-        public void Recycle()
+        public void WritePacked(uint value)
         {
-            this.Writer.Flush();
-            objectPool.PutObject(this);
+            do
+            {
+                byte b = (byte)(value & 0xFF);
+                if (value >= 0x80)
+                {
+                    b |= 0x80;
+                }
+
+                this.Write(b);
+                value >>= 7;
+            } while (value > 0);
+        }
+        #endregion
+
+        public unsafe static bool IsLittleEndian()
+        {
+            byte b;
+            unsafe
+            {
+                int i = 1;
+                byte* bp = (byte*)&i;
+                b = *bp;
+            }
+
+            return b == 1;
         }
     }
 }
index 4ea5c8826eb71ea7d873ed6eb826d3277a0f3882..1bd5a79d81de4e6dba8557840b524bf169209ede 100644 (file)
@@ -56,6 +56,8 @@ namespace Hazel.Udp
         /// <inheritdoc />
         protected override void WriteBytesToConnection(byte[] bytes, int length)
         {
+            InvokeDataSentRaw(bytes, length);
+
             lock (stateLock)
             {
                 if (State != ConnectionState.Connected && State != ConnectionState.Connecting)
@@ -104,6 +106,22 @@ namespace Hazel.Udp
 
         /// <inheritdoc />
         public override void Connect(byte[] bytes = null, int timeout = 5000)
+        {
+            this.ConnectAsync(bytes, timeout);
+
+            //Wait till hello packet is acknowledged and the state is set to Connected
+            bool timedOut = !WaitOnConnect(timeout);
+
+            //If we timed out raise an exception
+            if (timedOut)
+            {
+                Dispose();
+                throw new HazelException("Connection attempt timed out.");
+            }
+        }
+
+        /// <inheritdoc />
+        public override void ConnectAsync(byte[] bytes = null, int timeout = 5000)
         {
             lock (stateLock)
             {
@@ -112,7 +130,7 @@ namespace Hazel.Udp
 
                 State = ConnectionState.Connecting;
             }
-                
+
             //Begin listening
             try
             {
@@ -148,16 +166,6 @@ namespace Hazel.Udp
             //Write bytes to the server to tell it hi (and to punch a hole in our NAT, if present)
             //When acknowledged set the state to connected
             SendHello(bytes, () => { lock (stateLock) State = ConnectionState.Connected; });
-
-            //Wait till hello packet is acknowledged and the state is set to Connected
-            bool timedOut = !WaitOnConnect(timeout);
-
-            //If we timed out raise an exception
-            if (timedOut)
-            {
-                Dispose();
-                throw new HazelException("Connection attempt timed out.");
-            }
         }
 
         /// <summary>
index 1a1a3ffebe188149e61996b88a8aa9a58d54f730..e1c98e5345f19e88f2670f7f2f6f114c6e590461 100644 (file)
@@ -53,15 +53,7 @@ namespace Hazel.Udp
         /// </summary>
         volatile bool hasReceivedSomething = false;
 
-        /// <summary>
-        ///     The total time it has taken reliable packets to make a round trip.
-        /// </summary>
-        long totalRoundTime = 0;
-
-        /// <summary>
-        ///     The number of reliable messages that have been sent.
-        /// </summary>
-        long totalReliableMessages = 0;
+        object PingLock = new object();
 
         /// <summary>
         ///     Returns the average ping to this endpoint.
@@ -70,17 +62,7 @@ namespace Hazel.Udp
         ///     This returns the average ping for a one-way trip as calculated from the reliable packets that have been sent 
         ///     and acknowledged by the endpoint.
         /// </remarks>
-        public double AveragePing
-        {
-            get
-            {
-                long t = Interlocked.Read(ref totalReliableMessages);
-                if (t == 0)
-                    return 0;
-                else
-                    return Interlocked.Read(ref totalRoundTime) / t / 2;
-            }
-        }
+        public volatile float AveragePingMs = 500;
 
         /// <summary>
         ///     The maximum times a message should be resent before marking the endpoint as disconnected.
@@ -235,7 +217,7 @@ namespace Hazel.Udp
 
                         Trace.WriteLine("Resend.");
                     },
-                    resendTimeout > 0 ? resendTimeout : (AveragePing != 0 ? (int)AveragePing * 4 : 200),
+                    resendTimeout > 0 ? resendTimeout : (AveragePingMs != 0 ? (int)AveragePingMs * 4 : 200),
                     ackCallback
                 );
 
@@ -394,8 +376,10 @@ namespace Hazel.Udp
 
                     //Add to average ping
                     packet.Stopwatch.Stop();
-                    Interlocked.Add(ref totalRoundTime, packet.Stopwatch.Elapsed.Milliseconds);
-                    Interlocked.Increment(ref totalReliableMessages);
+                    lock (PingLock)
+                    {
+                        this.AveragePingMs = this.AveragePingMs * .7f + (float)packet.Stopwatch.Elapsed.TotalMilliseconds * .3f;
+                    }
 
                     packet.Recycle();
 
index 54d4c9912ec8184749a88b5fecaf1a15e773b8be..19434ea6f249394353d3ae41dcd342246d1e684f 100644 (file)
@@ -36,25 +36,26 @@ namespace Hazel.Udp
             if (State != ConnectionState.Connected)
                 throw new InvalidOperationException("Could not send data as this Connection is not connected. Did you disconnect?");
 
+            byte[] buffer = new byte[msg.Length];
+            Buffer.BlockCopy(msg.Buffer, 0, buffer, 0, msg.Length);
 
             //Inform keepalive not to send for a while
             ResetKeepAliveTimer();
 
-            int length = (int)msg.Stream.Length;
             switch (msg.SendOption)
             {
                 case SendOption.Reliable:
-                    AttachReliableID(msg.Buffer, 1, length);
-                    WriteBytesToConnection(msg.Buffer, length);
-                    Statistics.LogReliableSend(length - 3, length);
+                    AttachReliableID(buffer, 1, buffer.Length);
+                    WriteBytesToConnection(buffer, buffer.Length);
+                    Statistics.LogReliableSend(buffer.Length - 3, buffer.Length);
                     break;
 
                 case SendOption.FragmentedReliable:
                     throw new NotImplementedException("Not yet");
 
                 default:
-                    WriteBytesToConnection(msg.Buffer, length);
-                    Statistics.LogUnreliableSend(length - 1, length);;
+                    WriteBytesToConnection(buffer, buffer.Length);
+                    Statistics.LogUnreliableSend(buffer.Length - 1, buffer.Length);;
                     break;
             }
         }
@@ -159,6 +160,8 @@ namespace Hazel.Udp
         /// <param name="buffer">The buffer containing the bytes received.</param>
         protected internal void HandleReceive(byte[] buffer)
         {
+            InvokeDataReceivedRaw(buffer);
+
             //Inform keepalive not to send for a while
             ResetKeepAliveTimer();
             
index 1f47e6f8e81c720acc93d7c43ed320bb7cf0e695..3bfae30a4502c1ec93e3c8e043d4853ce4c63eed 100644 (file)
@@ -47,6 +47,8 @@ namespace Hazel.Udp
         /// <inheritdoc />
         protected override void WriteBytesToConnection(byte[] bytes, int length)
         {
+            InvokeDataSentRaw(bytes, length);
+
             lock (stateLock)
             {
                 if (State != ConnectionState.Connected)
@@ -65,6 +67,15 @@ namespace Hazel.Udp
             throw new HazelException("Cannot manually connect a UdpServerConnection, did you mean to use UdpClientConnection?");
         }
 
+        /// <inheritdoc />
+        /// <remarks>
+        ///     This will always throw a HazelException.
+        /// </remarks>
+        public override void ConnectAsync(byte[] bytes = null, int timeout = 5000)
+        {
+            throw new HazelException("Cannot manually connect a UdpServerConnection, did you mean to use UdpClientConnection?");
+        }
+
         /// <inheritdoc />
         protected override void HandleDisconnect(HazelException e = null)
         {