diff --git a/DarkRift.Client/BichannelClientConnection.cs b/DarkRift.Client/BichannelClientConnection.cs
index 21be3ff..e2ee1d6 100644
--- a/DarkRift.Client/BichannelClientConnection.cs
+++ b/DarkRift.Client/BichannelClientConnection.cs
@@ -9,6 +9,7 @@
using System.Linq;
using System.Net;
using System.Net.Sockets;
+using System.Runtime.CompilerServices;
using System.Text;
namespace DarkRift.Client
@@ -27,11 +28,12 @@ public sealed class BichannelClientConnection : NetworkClientConnection, IDispos
/// The IP address of the remote client.
///
public IPEndPoint RemoteUdpEndPoint { get; }
-
+
///
/// Whether Nagel's algorithm should be disabled or not.
///
- public bool NoDelay {
+ public bool NoDelay
+ {
get => tcpSocket.NoDelay;
set => tcpSocket.NoDelay = value;
}
@@ -64,7 +66,7 @@ public bool NoDelay {
/// The port (UDP and TCP) the server is listening on.
/// Whether to disable Nagle's algorithm or not.
public BichannelClientConnection(IPAddress ipAddress, int port, bool noDelay)
- : this (ipAddress, port, port, noDelay)
+ : this(ipAddress, port, port, noDelay)
{
}
@@ -76,7 +78,7 @@ public BichannelClientConnection(IPAddress ipAddress, int port, bool noDelay)
/// The port the server is listening on for TCP.
/// Whether to disable Nagle's algorithm or not.
public BichannelClientConnection(IPAddress ipAddress, int tcpPort, int udpPort, bool noDelay)
- : base ()
+ : base()
{
RemoteTcpEndPoint = new IPEndPoint(ipAddress, tcpPort);
RemoteUdpEndPoint = new IPEndPoint(ipAddress, udpPort);
@@ -105,7 +107,7 @@ public BichannelClientConnection(IPVersion ipVersion, IPAddress ipAddress, int p
tcpSocket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
udpSocket = new Socket(tcpSocket.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
-
+
NoDelay = noDelay;
}
@@ -139,13 +141,13 @@ public override void Connect()
//Receive auth token from TCP
byte[] buffer = new byte[9];
- tcpSocket.ReceiveTimeout = 5000;
+ tcpSocket.ReceiveTimeout = 5000; // 5s connection timeout
int receivedTcp = tcpSocket.Receive(buffer);
- tcpSocket.ReceiveTimeout = 0; //Reset to infinite
+ tcpSocket.ReceiveTimeout = 10000; // reset to 10s
if (receivedTcp != 9 || buffer[0] != 0)
{
- tcpSocket.Shutdown(SocketShutdown.Both);
+ Disconnect();
throw new DarkRiftConnectionException("Timeout waiting for auth token from server.", SocketError.ConnectionAborted);
}
@@ -154,26 +156,26 @@ public override void Connect()
//Receive response from server to initiate the connection
buffer = new byte[1];
- udpSocket.ReceiveTimeout = 5000;
+ udpSocket.ReceiveTimeout = 5000; // 5s connection timeout
int receivedUdp = udpSocket.Receive(buffer);
- udpSocket.ReceiveTimeout = 0; //Reset to infinite
+ udpSocket.ReceiveTimeout = 10000; // reset to 10s
if (receivedUdp != 1 || buffer[0] != 0)
{
- tcpSocket.Shutdown(SocketShutdown.Both);
+ Disconnect();
throw new DarkRiftConnectionException("Timeout waiting for UDP acknowledgement from server.", SocketError.ConnectionAborted);
}
}
catch (DarkRiftConnectionException)
{
// If any exceptions get thrown reset the connection state
- connectionState = ConnectionState.Disconnected;
+ Disconnect();
throw;
}
catch (SocketException)
{
// If any exceptions get thrown reset the connection state
- connectionState = ConnectionState.Disconnected;
+ Disconnect();
throw;
}
@@ -207,17 +209,9 @@ public override bool SendMessageReliable(MessageBuffer message)
if (connectionState == ConnectionState.Disconnected)
return false;
- byte[] header = new byte[4];
- BigEndianHelper.WriteBytes(header, 0, message.Count);
-
SocketAsyncEventArgs args = ObjectCache.GetSocketAsyncEventArgs();
- args.SetBuffer(null, 0, 0);
- args.BufferList = new List>()
- {
- new ArraySegment(header),
- new ArraySegment(message.Buffer, message.Offset, message.Count)
- };
+ args.SetBuffer(message.Buffer, message.Offset, message.Count);
args.UserToken = message;
args.Completed += TcpSendCompleted;
@@ -227,8 +221,14 @@ public override bool SendMessageReliable(MessageBuffer message)
{
completingAsync = tcpSocket.SendAsync(args);
}
+ catch (ObjectDisposedException)
+ {
+ TcpSendCompleted(this, args);
+ return false;
+ }
catch (Exception)
{
+ TcpSendCompleted(this, args);
return false;
}
@@ -258,6 +258,7 @@ public override bool SendMessageUnreliable(MessageBuffer message)
}
catch (Exception)
{
+ UdpSendCompleted(this, args);
return false;
}
@@ -274,8 +275,21 @@ public override bool Disconnect()
return false;
connectionState = ConnectionState.Disconnected;
- tcpSocket.Shutdown(SocketShutdown.Both);
-
+ try
+ {
+ tcpSocket.Shutdown(SocketShutdown.Both);
+ udpSocket.Shutdown(SocketShutdown.Both);
+ }
+ catch (SocketException)
+ {
+ //Ignore exception as socket is already shutdown
+ }
+ finally
+ {
+ tcpSocket.Close();
+ udpSocket.Close();
+ }
+
return true;
}
@@ -310,6 +324,7 @@ private void ReceiveHeaderAndBody(SocketAsyncEventArgs args)
try
{
+ // header not fully received yet, wait for it
bool headerContinueCompletingAsync = tcpSocket.ReceiveAsync(args);
if (headerContinueCompletingAsync)
return;
@@ -319,7 +334,13 @@ private void ReceiveHeaderAndBody(SocketAsyncEventArgs args)
HandleDisconnectionDuringHeaderReceive(args);
return;
}
+ catch (Exception)
+ {
+ HandleDisconnectionDuringHeaderReceive(args);
+ return;
+ }
+ // keep getting header in a loop until received
continue;
}
@@ -339,6 +360,11 @@ private void ReceiveHeaderAndBody(SocketAsyncEventArgs args)
HandleDisconnectionDuringBodyReceive(args);
return;
}
+ catch (Exception)
+ {
+ HandleDisconnectionDuringBodyReceive(args);
+ return;
+ }
if (!WasBodyReceiveSucessful(args))
{
@@ -352,6 +378,7 @@ private void ReceiveHeaderAndBody(SocketAsyncEventArgs args)
UpdateBufferPointers(args);
}
+ // body received, process it
MessageBuffer bodyBuffer = ProcessBody(args);
// Start next receive before invoking events
@@ -361,7 +388,12 @@ private void ReceiveHeaderAndBody(SocketAsyncEventArgs args)
{
headerCompletingAsync = tcpSocket.ReceiveAsync(args);
}
- catch (ObjectDisposedException)
+ catch (ObjectDisposedException)
+ {
+ HandleDisconnectionDuringHeaderReceive(args);
+ return;
+ }
+ catch (Exception)
{
HandleDisconnectionDuringHeaderReceive(args);
return;
@@ -413,7 +445,12 @@ private void AsyncReceiveBodyCompleted(object sender, SocketAsyncEventArgs args)
}
catch (ObjectDisposedException)
{
- HandleDisconnectionDuringBodyReceive(args);
+ HandleDisconnectionDuringHeaderReceive(args);
+ return;
+ }
+ catch (Exception)
+ {
+ HandleDisconnectionDuringHeaderReceive(args);
return;
}
}
@@ -427,7 +464,12 @@ private void AsyncReceiveBodyCompleted(object sender, SocketAsyncEventArgs args)
{
headerCompletingAsync = tcpSocket.ReceiveAsync(args);
}
- catch (ObjectDisposedException)
+ catch (ObjectDisposedException)
+ {
+ HandleDisconnectionDuringHeaderReceive(args);
+ return;
+ }
+ catch (Exception)
{
HandleDisconnectionDuringHeaderReceive(args);
return;
@@ -438,7 +480,7 @@ private void AsyncReceiveBodyCompleted(object sender, SocketAsyncEventArgs args)
if (headerCompletingAsync)
return;
- //Now move back into main loop until no more data is present
+ // header not recieved async, move back into main loop until no more data is present
ReceiveHeaderAndBody(args);
}
@@ -447,11 +489,12 @@ private void AsyncReceiveBodyCompleted(object sender, SocketAsyncEventArgs args)
///
/// The socket args used during the operation.
/// If the whole header has been received.
+ //[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(256)]
private bool IsHeaderReceiveComplete(SocketAsyncEventArgs args)
{
- MessageBuffer headerBuffer = (MessageBuffer)args.UserToken;
-
- return args.Offset + args.BytesTransferred - headerBuffer.Offset >= headerBuffer.Count;
+ // header size is 4 bytes, an int
+ return args.Offset + args.BytesTransferred >= Message.HEADER_RESERVED_BYTES_COUNT;
}
///
@@ -459,11 +502,15 @@ private bool IsHeaderReceiveComplete(SocketAsyncEventArgs args)
///
/// The socket args used during the operation.
/// If the whole body has been received.
+ //[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(256)]
private bool IsBodyReceiveComplete(SocketAsyncEventArgs args)
{
- MessageBuffer bodyBuffer = (MessageBuffer)args.UserToken;
+ MessageBuffer buffer = (MessageBuffer)args.UserToken;
+ return args.Offset + args.BytesTransferred >= buffer.Count;
- return args.Offset + args.BytesTransferred - bodyBuffer.Offset >= bodyBuffer.Count;
+ // DEBUG when using byte[] of exact size an not pooled MessageBuffer
+ //return args.Offset + args.BytesTransferred >= args.Buffer.Length;
}
///
@@ -473,14 +520,9 @@ private bool IsBodyReceiveComplete(SocketAsyncEventArgs args)
/// The number of bytes in the body.
private int ProcessHeader(SocketAsyncEventArgs args)
{
- MessageBuffer headerBuffer = (MessageBuffer)args.UserToken;
-
- int bodyLength = BigEndianHelper.ReadInt32(headerBuffer.Buffer, headerBuffer.Offset);
-
- headerBuffer.Dispose();
-
args.Completed -= AsyncReceiveHeaderCompleted;
+ int bodyLength = BigEndianHelper.ReadInt32(args.Buffer, args.Offset);
return bodyLength;
}
@@ -489,20 +531,29 @@ private int ProcessHeader(SocketAsyncEventArgs args)
///
/// The socket args used during the operation.
/// The buffer received.
+ //[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(256)]
private MessageBuffer ProcessBody(SocketAsyncEventArgs args)
{
args.Completed -= AsyncReceiveBodyCompleted;
return (MessageBuffer)args.UserToken;
+
+ // DEBUG MODE: create a buffer rather then getting it from the pool
+ //var buffer = MessageBuffer.Create(args.Buffer.Length);
+ //buffer.Count = args.Buffer.Length;
+ //Buffer.BlockCopy(args.Buffer, 0, buffer.Buffer, 0, args.Buffer.Length);
+ //return buffer;
}
///
/// Invokes message recevied events and cleans up.
///
/// The TCP body received.
+ //[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(256)]
private void ProcessMessage(MessageBuffer buffer)
{
HandleMessageReceived(buffer, SendMode.Reliable);
-
buffer.Dispose();
}
@@ -511,6 +562,8 @@ private void ProcessMessage(MessageBuffer buffer)
///
/// The socket args used during the operation.
/// If the receive completed correctly.
+ //[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(256)]
private bool WasHeaderReceiveSucessful(SocketAsyncEventArgs args)
{
return args.BytesTransferred != 0 && args.SocketError == SocketError.Success;
@@ -521,6 +574,7 @@ private bool WasHeaderReceiveSucessful(SocketAsyncEventArgs args)
///
/// The socket args used during the operation.
/// If the receive completed correctly.
+ //[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool WasBodyReceiveSucessful(SocketAsyncEventArgs args)
{
return args.BytesTransferred != 0 && args.SocketError == SocketError.Success;
@@ -532,12 +586,10 @@ private bool WasBodyReceiveSucessful(SocketAsyncEventArgs args)
/// The socket args used during the operation.
private void HandleDisconnectionDuringHeaderReceive(SocketAsyncEventArgs args)
{
- Disconnect(args.SocketError);
+ args.Completed -= AsyncReceiveHeaderCompleted;
- MessageBuffer buffer = (MessageBuffer)args.UserToken;
- buffer.Dispose();
+ Disconnect(args.SocketError);
- args.Completed -= AsyncReceiveHeaderCompleted;
ObjectCache.ReturnSocketAsyncEventArgs(args);
}
@@ -547,13 +599,13 @@ private void HandleDisconnectionDuringHeaderReceive(SocketAsyncEventArgs args)
/// The socket args used during the operation.
private void HandleDisconnectionDuringBodyReceive(SocketAsyncEventArgs args)
{
- Disconnect(args.SocketError);
+ args.Completed -= AsyncReceiveBodyCompleted;
MessageBuffer buffer = (MessageBuffer)args.UserToken;
- buffer.Dispose();
+ Disconnect(args.SocketError);
- args.Completed -= AsyncReceiveBodyCompleted;
ObjectCache.ReturnSocketAsyncEventArgs(args);
+ buffer.Dispose();
}
///
@@ -562,10 +614,8 @@ private void HandleDisconnectionDuringBodyReceive(SocketAsyncEventArgs args)
/// The socket args to use during the operation.
private void SetupReceiveHeader(SocketAsyncEventArgs args)
{
- MessageBuffer headerBuffer = MessageBuffer.Create(4);
-
- args.SetBuffer(headerBuffer.Buffer, headerBuffer.Offset, 4);
- args.UserToken = headerBuffer;
+ // TODO tiny alloc
+ args.SetBuffer(new byte[4], 0, 4);
args.Completed += AsyncReceiveHeaderCompleted;
}
@@ -576,11 +626,19 @@ private void SetupReceiveHeader(SocketAsyncEventArgs args)
/// The number of bytes in the body.
private void SetupReceiveBody(SocketAsyncEventArgs args, int length)
{
+ // here we're setting the buffer count as a marker on how much data received we need exactly for the body
MessageBuffer bodyBuffer = MessageBuffer.Create(length);
bodyBuffer.Count = length;
- args.SetBuffer(bodyBuffer.Buffer, bodyBuffer.Offset, length);
+ args.SetBuffer(bodyBuffer.Buffer, 0, length);
args.UserToken = bodyBuffer;
+ //Debug.Log($"Receive buffer created. Size: [{length}], Capacity: [{bodyBuffer.Buffer.Length}], Offset: [{bodyBuffer.Offset}]");
+
+ // DEBUG: use byte[] as buffer rather then pooled MessageBuffer
+ //byte[] bodyReceiveBuffer = new byte[length];
+ //args.SetBuffer(bodyReceiveBuffer, 0, length);
+ //Debug.Log($"Receive buffer created. Size: [{length}], Capacity: [{length}], Offset: [{args.Offset}]");
+
args.Completed += AsyncReceiveBodyCompleted;
}
@@ -588,8 +646,18 @@ private void SetupReceiveBody(SocketAsyncEventArgs args, int length)
/// Updates the pointers on the buffer to continue a receive operation.
///
/// The socket args to update.
- private void UpdateBufferPointers(SocketAsyncEventArgs args) {
- args.SetBuffer(args.Offset + args.BytesTransferred, args.Count - args.BytesTransferred);
+ private void UpdateBufferPointers(SocketAsyncEventArgs args)
+ {
+ MessageBuffer buffer = args.UserToken as MessageBuffer;
+ int newOffset = args.Offset + args.BytesTransferred;
+ args.SetBuffer(newOffset, buffer.Count - newOffset);
+ //Debug.Log($"Received bytes: [{args.BytesTransferred}], in buffer: [{newOffset}], remaining [{buffer.Count - newOffset}]");
+
+ // DEBUG: use byte[] as buffer rather then pooled MessageBuffer
+ // move the offset to bytes read
+ //int newOffset = args.Offset + args.BytesTransferred;
+ //args.SetBuffer(newOffset, args.Buffer.Length - newOffset);
+ //Debug.Log($"Received bytes: [{args.BytesTransferred}], in buffer: [{newOffset}], remaining [{args.Buffer.Length - newOffset}]");
}
///
@@ -605,17 +673,15 @@ private void UdpReceiveCompleted(object sender, SocketAsyncEventArgs e)
//If we received a Success then process it
if (e.SocketError == SocketError.Success)
{
- using (MessageBuffer buffer = MessageBuffer.Create(e.BytesTransferred))
- {
- Buffer.BlockCopy(e.Buffer, 0, buffer.Buffer, buffer.Offset, e.BytesTransferred);
- buffer.Count = e.BytesTransferred;
+ using MessageBuffer buffer = MessageBuffer.Create(e.BytesTransferred);
+ Buffer.BlockCopy(e.Buffer, 0, buffer.Buffer, buffer.Offset, e.BytesTransferred);
+ buffer.Count = e.BytesTransferred;
- completingAsync = udpSocket.ReceiveAsync(e);
+ completingAsync = udpSocket.ReceiveAsync(e);
- //Length of 0 must be a hole punching packet
- if (buffer.Count != 0)
- HandleMessageReceived(buffer, SendMode.Unreliable);
- }
+ //Length of 0 must be a hole punching packet
+ if (buffer.Count != 0)
+ HandleMessageReceived(buffer, SendMode.Unreliable);
}
//Ignore ConnectionReset (ICMP Port Unreachable) since NATs will return that when they get
@@ -644,18 +710,48 @@ private void UdpReceiveCompleted(object sender, SocketAsyncEventArgs e)
/// Called when a TCP send has completed.
///
///
- ///
- private void TcpSendCompleted(object sender, SocketAsyncEventArgs e)
+ ///
+ private void TcpSendCompleted(object sender, SocketAsyncEventArgs args)
{
- if (e.SocketError != SocketError.Success)
- Disconnect(e.SocketError);
+ MessageBuffer messageBuffer = (MessageBuffer)args.UserToken;
+ SocketError socketError = args.SocketError;
+
+ // Linux+Mono combination can complete without sending every byte on large packets
+ // this is not documented anythwere, call SendAsync again when that happens
+ // except in error case that is handled later on
+ int bytesTransferredTotal = args.Offset + args.BytesTransferred;
+ if (socketError == SocketError.Success && bytesTransferredTotal > 0 && bytesTransferredTotal < messageBuffer.Count)
+ {
+ args.SetBuffer(offset: bytesTransferredTotal, count: messageBuffer.Count - bytesTransferredTotal);
+ bool isCompletedAsync = tcpSocket.SendAsync(args);
+ if (isCompletedAsync)
+ return;
- e.Completed -= TcpSendCompleted;
+ // otherwise it completed sync, just continue with execution as we're already in the complete callback
+ }
- //Always dispose buffer when completed!
- ((MessageBuffer)e.UserToken).Dispose();
+ args.Completed -= TcpSendCompleted;
- ObjectCache.ReturnSocketAsyncEventArgs(e);
+ // must save some info before we release the args into the pool and it gets reset
+ int bytesTotal = messageBuffer.Count + Message.HEADER_RESERVED_BYTES_COUNT;
+ int bufferSize = messageBuffer.Buffer.Length;
+ int bytesTransferred = args.BytesTransferred;
+ int sendSize = args.SendPacketsSendSize;
+ SocketFlags flags = args.SocketFlags;
+
+ // socket disposed first to release ref to buffer as buffer might get reused immediatly
+ // if disposed with socket still holding the ref to it
+ ObjectCache.ReturnSocketAsyncEventArgs(args);
+
+ // Always dispose buffer when completed!
+ messageBuffer.Dispose();
+
+ // during receive BytesTransferred == 0 means disconnect, maybe it could mean here as well, it's not documented
+ if (socketError != SocketError.Success || bytesTransferredTotal == 0)
+ {
+ Disconnect(socketError);
+ return;
+ }
}
///
@@ -665,15 +761,19 @@ private void TcpSendCompleted(object sender, SocketAsyncEventArgs e)
///
private void UdpSendCompleted(object sender, SocketAsyncEventArgs e)
{
- if (e.SocketError != SocketError.Success)
- Disconnect(e.SocketError);
-
e.Completed -= UdpSendCompleted;
- //Always dispose buffer when completed!
- ((MessageBuffer)e.UserToken).Dispose();
+ MessageBuffer messageBuffer = (MessageBuffer)e.UserToken;
+ // socket disposed first to release ref to buffer as buffer might get reused immediatly
+ // if disposed with socket still holding the ref to it
ObjectCache.ReturnSocketAsyncEventArgs(e);
+
+ // Always dispose buffer when completed!
+ messageBuffer.Dispose();
+
+ if (e.SocketError != SocketError.Success)
+ Disconnect(e.SocketError);
}
///
@@ -684,8 +784,7 @@ private void Disconnect(SocketError error)
{
if (connectionState == ConnectionState.Connected)
{
- connectionState = ConnectionState.Disconnected;
-
+ Disconnect();
HandleDisconnection(error);
}
}
@@ -706,9 +805,6 @@ protected override void Dispose(bool disposing)
if (disposing)
{
Disconnect();
-
- tcpSocket.Close();
- udpSocket.Close();
}
disposedValue = true;
diff --git a/DarkRift.Client/DarkRift.Client.csproj b/DarkRift.Client/DarkRift.Client.csproj
index 2e9b9c4..929273f 100644
--- a/DarkRift.Client/DarkRift.Client.csproj
+++ b/DarkRift.Client/DarkRift.Client.csproj
@@ -8,6 +8,7 @@
bin\$(Configuration)\$(TargetFramework)\DarkRift.Client.xml
Debug;Free
true
+ 8.0
diff --git a/DarkRift.Client/DarkRiftClient.cs b/DarkRift.Client/DarkRiftClient.cs
index 69a186a..9c65060 100644
--- a/DarkRift.Client/DarkRiftClient.cs
+++ b/DarkRift.Client/DarkRiftClient.cs
@@ -232,8 +232,7 @@ public void Connect(NetworkClientConnection connection)
{
setupMutex.Reset();
- if (this.Connection != null)
- this.Connection.Dispose();
+ this.Connection?.Dispose();
this.Connection = connection;
connection.MessageReceived = MessageReceivedHandler;
@@ -371,26 +370,25 @@ public bool Disconnect()
/// The SendMode used to send the data.
private void MessageReceivedHandler(MessageBuffer buffer, SendMode sendMode)
{
- using (Message message = Message.Create(buffer, true))
+ using Message message = Message.Create(buffer, true);
+
+ //Record any ping acknowledgements
+ if (message.IsPingAcknowledgementMessage)
{
- //Record any ping acknowledgements
- if (message.IsPingAcknowledgementMessage)
+ try
{
- try
- {
- RoundTripTime.RecordInboundPing(message.PingCode);
- }
- catch (KeyNotFoundException)
- {
- //Nothing we can really do about this
- }
+ RoundTripTime.RecordInboundPing(message.PingCode);
+ }
+ catch (KeyNotFoundException)
+ {
+ //Nothing we can really do about this
}
-
- if (message.IsCommandMessage)
- HandleCommand(message);
- else
- HandleMessage(message, sendMode);
}
+
+ if (message.IsCommandMessage)
+ HandleCommand(message);
+ else
+ HandleMessage(message, sendMode);
}
///
@@ -399,16 +397,14 @@ private void MessageReceivedHandler(MessageBuffer buffer, SendMode sendMode)
/// The message that was received.
private void HandleCommand(Message message)
{
- using (DarkRiftReader reader = message.GetReader())
+ using DarkRiftReader reader = message.GetReader();
+ switch ((CommandCode)message.Tag)
{
- switch ((CommandCode)message.Tag)
- {
- case CommandCode.Configure:
- ID = reader.ReadUInt16();
+ case CommandCode.Configure:
+ ID = reader.ReadUInt16();
- setupMutex.Set();
- break;
- }
+ setupMutex.Set();
+ break;
}
}
@@ -420,8 +416,8 @@ private void HandleCommand(Message message)
private void HandleMessage(Message message, SendMode sendMode)
{
//Invoke for message received event
- using (MessageReceivedEventArgs args = MessageReceivedEventArgs.Create(message, sendMode))
- MessageReceived?.Invoke(this, args);
+ using MessageReceivedEventArgs args = MessageReceivedEventArgs.Create(message, sendMode);
+ MessageReceived?.Invoke(this, args);
}
///
@@ -455,8 +451,7 @@ protected virtual void Dispose(bool disposing)
{
disposed = true;
- if (Connection != null)
- Connection.Dispose();
+ Connection?.Dispose();
setupMutex.Close();
}
diff --git a/DarkRift.Server/DarkRift.Server.csproj b/DarkRift.Server/DarkRift.Server.csproj
index 644f32b..37cf741 100644
--- a/DarkRift.Server/DarkRift.Server.csproj
+++ b/DarkRift.Server/DarkRift.Server.csproj
@@ -8,6 +8,7 @@
bin\$(Configuration)\$(TargetFramework)\DarkRift.Server.xml
Debug;Release
true
+ 8.0
diff --git a/DarkRift/DarkRift.csproj b/DarkRift/DarkRift.csproj
index 4678203..cae4c0d 100644
--- a/DarkRift/DarkRift.csproj
+++ b/DarkRift/DarkRift.csproj
@@ -9,6 +9,7 @@
Debug;Release
true
true
+ 8.0
diff --git a/DarkRift/DarkRiftWriter.cs b/DarkRift/DarkRiftWriter.cs
index 3c27263..c6a7423 100644
--- a/DarkRift/DarkRiftWriter.cs
+++ b/DarkRift/DarkRiftWriter.cs
@@ -117,7 +117,18 @@ internal DarkRiftWriter()
{
serializeEventSingleton = new SerializeEvent(this);
}
-
+
+ ///
+ /// Clears out the buffer, making it empty and reusable.
+ ///
+ /// Added by kova@freerangegames.com 2022-05-20
+ public void Clear()
+ {
+ Position = 0;
+ buffer.Count = 0;
+ buffer.Offset = 0;
+ }
+
///
/// Writes a single byte to the writer.
///
@@ -565,7 +576,7 @@ public void Write(T[] value) where T : IDarkRiftSerializable
public void WriteRaw(byte[] bytes, int offset, int length)
{
buffer.EnsureLength(Position + length);
- System.Buffer.BlockCopy(bytes, offset, buffer.Buffer, Position, length);
+ Buffer.BlockCopy(bytes, offset, buffer.Buffer, Position, length);
Position += length;
buffer.Count = Math.Max(Length, Position);
diff --git a/DarkRift/Message.cs b/DarkRift/Message.cs
index 44cc453..ddf1870 100644
--- a/DarkRift/Message.cs
+++ b/DarkRift/Message.cs
@@ -19,6 +19,11 @@ namespace DarkRift
///
public sealed class Message : IDisposable
{
+ ///
+ /// How many bytes is reserved for message header with value of rest of the message
+ ///
+ public const int HEADER_RESERVED_BYTES_COUNT = 4;
+
///
/// Bitmask for the command message flag.
///
@@ -420,19 +425,23 @@ public void MakePingAcknowledgementMessage(Message acknowledging)
//TODO DR3 Make this return an IMessageBuffer
internal MessageBuffer ToBuffer()
{
- int headerLength = IsPingMessage || IsPingAcknowledgementMessage ? 5 : 3;
+ int headerLength = HEADER_RESERVED_BYTES_COUNT + (IsPingMessage || IsPingAcknowledgementMessage ? 5 : 3);
int totalLength = headerLength + DataLength;
MessageBuffer buffer = MessageBuffer.Create(totalLength);
buffer.Count = totalLength;
- buffer.Buffer[buffer.Offset] = flags;
- BigEndianHelper.WriteBytes(buffer.Buffer, buffer.Offset + 1, tag);
+ // write length of the rest of the message
+ BigEndianHelper.WriteBytes(buffer.Buffer, 0, totalLength - HEADER_RESERVED_BYTES_COUNT);
+
+ buffer.Buffer[HEADER_RESERVED_BYTES_COUNT] = flags;
+ BigEndianHelper.WriteBytes(buffer.Buffer, buffer.Offset + 1 + HEADER_RESERVED_BYTES_COUNT, tag);
if (IsPingMessage || IsPingAcknowledgementMessage)
- BigEndianHelper.WriteBytes(buffer.Buffer, buffer.Offset + 3, PingCode);
+ BigEndianHelper.WriteBytes(buffer.Buffer, buffer.Offset + 3 + HEADER_RESERVED_BYTES_COUNT, PingCode);
- //Due to poor design, here's un unavoidable memory copy! Hooray!
+ // Due to poor design, here's un unavoidable memory copy! Hooray!
+ // Copy the content of the message into rest of the new buffer
Buffer.BlockCopy(this.buffer.Buffer, this.buffer.Offset, buffer.Buffer, buffer.Offset + headerLength, this.buffer.Count);
return buffer;
diff --git a/DarkRift/MessageBuffer.cs b/DarkRift/MessageBuffer.cs
index ed513ed..c26da15 100644
--- a/DarkRift/MessageBuffer.cs
+++ b/DarkRift/MessageBuffer.cs
@@ -114,6 +114,9 @@ internal void EnsureLength(int newLength)
#region IDisposable Support
public void Dispose()
{
+ Count = 0;
+ Offset = 0;
+
//AutoRecyclingArray is reference counted, mark that we're no longer using it
backingBuffer.DecrementReference();
diff --git a/DarkRift/ObjectCache.cs b/DarkRift/ObjectCache.cs
index 96af8ec..1d42652 100644
--- a/DarkRift/ObjectCache.cs
+++ b/DarkRift/ObjectCache.cs
@@ -321,6 +321,16 @@ public static void ReturnSocketAsyncEventArgs(SocketAsyncEventArgs socketAsyncEv
ObjectCacheTestHelper.SocketAsyncEventArgsWasReturned();
#endif
+ // added safety restore to default state before going ito the pool
+ socketAsyncEventArgs.SocketFlags = SocketFlags.None;
+ socketAsyncEventArgs.SocketError = SocketError.Success;
+ socketAsyncEventArgs.SendPacketsSendSize = 0;
+ socketAsyncEventArgs.SendPacketsFlags = TransmitFileOptions.UseDefaultWorkerThread;
+ socketAsyncEventArgs.SendPacketsElements = null;
+ socketAsyncEventArgs.BufferList = null;
+ socketAsyncEventArgs.UserToken = null;
+ socketAsyncEventArgs.SetBuffer(null, 0, 0);
+
if (!socketAsyncEventArgsPool.ReturnInstance(socketAsyncEventArgs))
socketAsyncEventArgs.Dispose();
}