diff --git a/Projects/Server.Tests/Network/PipeTests.cs b/Projects/Server.Tests/Network/PipeTests.cs index fc2b31638..9ba78bc69 100644 --- a/Projects/Server.Tests/Network/PipeTests.cs +++ b/Projects/Server.Tests/Network/PipeTests.cs @@ -25,22 +25,21 @@ namespace Server.Tests.Network DelayedExecute(() => { - // Write some data into the pipe +; // Write some data into the pipe writer.GetAvailable(out var buffer); Assert.True(buffer.Length == 99); - - buffer.CopyFrom(new byte[] { 1 }); - buffer.CopyFrom(new byte[] { 2 }); - buffer.CopyFrom(new byte[] { 3 }); + buffer[0] = 0x1; + buffer[1] = 0x2; + buffer[2] = 0x3; writer.Advance(3); writer.Flush(); }); var segments = new ArraySegment[2]; - (await reader).TryRead(segments); + await reader.Read(segments); - Assert.True(segments[0].Count == 3); + Assert.Equal(3, segments[0].Count); } private bool _signal; @@ -139,32 +138,31 @@ namespace Server.Tests.Network writer.GetAvailable(out var buffer); - Assert.True(buffer.Length == 9); - Assert.True(reader.GetAvailable() == 0); + Assert.Equal(9, buffer.Length); + Assert.Equal(0u, reader.GetAvailable()); reader.TryRead(out buffer); - Assert.True(buffer.Length == 0); + Assert.Equal(0, buffer.Length); writer.Advance(7); writer.GetAvailable(out buffer); - Assert.True(buffer.Length == 2); - Assert.True(reader.GetAvailable() == 7); + Assert.Equal(2, buffer.Length); + Assert.Equal(7u, reader.GetAvailable()); reader.TryRead(out buffer); - Assert.True(buffer.Length == 7); + Assert.Equal(7, buffer.Length); reader.Advance(4); writer.GetAvailable(out buffer); - Assert.True(buffer.Length == 6); - Assert.True(reader.GetAvailable() == 3); + Assert.Equal(6, buffer.Length); + Assert.Equal(3u, reader.GetAvailable()); reader.TryRead(out buffer); - Assert.True(buffer.Length == 3); + Assert.Equal(3, buffer.Length); writer.Advance(3); writer.GetAvailable(out buffer); - Assert.True(buffer.Length == 3); - Assert.True(reader.GetAvailable() == 6); + Assert.Equal(3, buffer.Length); + Assert.Equal(6u, reader.GetAvailable()); reader.TryRead(out buffer); - Assert.True(buffer.Length == 6); - + Assert.Equal(6, buffer.Length); } [Fact] @@ -201,7 +199,7 @@ namespace Server.Tests.Network writer.Advance(9); writer.Flush(); - Assert.True(reader.GetAvailable() == 9); + Assert.Equal(9u, reader.GetAvailable()); reader.TryRead(out buffer); @@ -209,18 +207,18 @@ namespace Server.Tests.Network for (int i = 0; i < 9; i++) { - Assert.True(first[i] == i); + Assert.Equal(i, first[i]); } reader.Advance(4); reader.TryRead(out buffer); first = buffer.GetSpan(0); - Assert.True(buffer.Length == 5); - Assert.True(first[0] == 4); - Assert.True(first[1] == 5); - Assert.True(first[2] == 6); - Assert.True(first[3] == 7); - Assert.True(first[4] == 8); + Assert.Equal(5, buffer.Length); + Assert.Equal(4, first[0]); + Assert.Equal(5, first[1]); + Assert.Equal(6, first[2]); + Assert.Equal(7, first[3]); + Assert.Equal(8, first[4]); } } } diff --git a/Projects/Server/Network/NetState/NetState.cs b/Projects/Server/Network/NetState/NetState.cs index 2aeaab148..4b4406edf 100644 --- a/Projects/Server/Network/NetState/NetState.cs +++ b/Projects/Server/Network/NetState/NetState.cs @@ -23,7 +23,6 @@ using System.Net.Sockets; using System.Runtime.CompilerServices; using System.Threading; using Server.Accounting; -using Server.Exceptions; using Server.Gumps; using Server.HuePickers; using Server.Items; @@ -55,7 +54,6 @@ namespace Server.Network private byte[] _sendBuffer; private long m_NextCheckActivity; private volatile bool m_Running; - private readonly Thread _sendThread; private volatile EncodePacket _packetDecoder; private volatile EncodePacket _packetEncoder; @@ -77,7 +75,7 @@ namespace Server.Network Timer.DelayCall(checkAliveDuration, checkAliveDuration, CheckAllAlive); } - public NetState(Socket connection, Thread sendThread = null) + public NetState(Socket connection) { m_Running = false; Connection = connection; @@ -91,7 +89,6 @@ namespace Server.Network _sendBuffer = new byte[SendPipeSize]; SendPipe = new Pipe(_sendBuffer); m_NextCheckActivity = Core.TickCount + 30000; - _sendThread = sendThread ?? Core.Thread; try { @@ -372,8 +369,6 @@ namespace Server.Network NetworkState.Resume(ref m_NetworkState); } - public bool GetAvailableSendPipe(out CircularBuffer buffer) => SendPipe.Writer.GetAvailable(out buffer); - public virtual void Send(ref CircularBuffer buffer, int length) { if (Connection == null || BlockAllPackets || buffer.Length == 0) @@ -381,14 +376,6 @@ namespace Server.Network return; } -#if DEBUG - var currentThread = Thread.CurrentThread; - if (currentThread != _sendThread) - { - throw new InvalidThreadException("Attempted to send packet outside send thread!"); - } -#endif - try { _packetEncoder?.Invoke(ref buffer, ref length); @@ -412,15 +399,6 @@ namespace Server.Network return; } -#if DEBUG - var currentThread = Thread.CurrentThread; - - if (currentThread != _sendThread) - { - throw new InvalidThreadException("Attempted to send packet outside send thread!"); - } -#endif - var writer = SendPipe.Writer; try @@ -429,7 +407,7 @@ namespace Server.Network if (buffer.Length > 0 && length > 0) { - if (!GetAvailableSendPipe(out var pipeBuffer)) + if (!SendPipe.Writer.GetAvailable(out var pipeBuffer)) { p.OnSend(); return; @@ -489,7 +467,8 @@ namespace Server.Network { while (m_Running) { - if (!(await reader).TryRead(segments)) + var result = await reader.Read(segments); + if (result.Closed) { break; } diff --git a/Projects/Server/Network/Pipe.cs b/Projects/Server/Network/Pipe.cs index 4ab0db2f8..b7c94d999 100644 --- a/Projects/Server/Network/Pipe.cs +++ b/Projects/Server/Network/Pipe.cs @@ -33,12 +33,20 @@ namespace Server.Network public class Pipe { + public readonly struct Result + { + public bool Closed { get; } + + public Result(bool closed) => Closed = closed; + } + public class PipeWriter { private readonly Pipe _pipe; public PipeWriter(Pipe pipe) => _pipe = pipe; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool GetAvailable(ArraySegment[] segments) { var read = _pipe._readIdx; @@ -63,6 +71,7 @@ namespace Server.Network return !_pipe._closed; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool GetAvailable(out CircularBuffer buffer) { var read = _pipe._readIdx; @@ -183,7 +192,7 @@ namespace Server.Network } } - public class PipeReader : IPipeTask> + public class PipeReader : IPipeTask { private readonly Pipe _pipe; @@ -203,6 +212,20 @@ namespace Server.Network return write + _pipe.Size - read; } + private ArraySegment[] _segments; + + public IPipeTask Read(ArraySegment[] segments) + { + if (_pipe._awaitBeginning) + { + throw new Exception("Double await on reader"); + } + + _segments = segments; + return this; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryRead(out CircularBuffer buffer) { var read = _pipe._readIdx; @@ -226,7 +249,8 @@ namespace Server.Network return !_pipe._closed; } - public bool TryRead(ArraySegment[] segments) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void TryRead(ArraySegment[] segments) { var read = _pipe._readIdx; var write = _pipe._writeIdx; @@ -241,8 +265,6 @@ namespace Server.Network segments[0] = _pipe.Size - read == 0 ? ArraySegment.Empty : new ArraySegment(_pipe._buffer, (int)read, (int)(_pipe.Size - read)); segments[1] = write == 0 ? ArraySegment.Empty : new ArraySegment(_pipe._buffer, 0, (int)write); } - - return !_pipe._closed; } public void Advance(uint count) @@ -288,7 +310,7 @@ namespace Server.Network // The following makes it possible to await the reader. Do not use any of this directly. - public IPipeTask> GetAwaiter() => this; + public IPipeTask GetAwaiter() => this; public bool IsCompleted { @@ -304,7 +326,22 @@ namespace Server.Network } } - public PipeReader GetResult() => this; + public Result GetResult() + { + if (_pipe._closed) + { + _segments = null; + return new Result(true); + } + + if (_segments != null) + { + TryRead(_segments); + _segments = null; + } + + return new Result(false); + } public void OnCompleted(Action continuation) => _pipe._readerContinuation = continuation;