From d332b7935804d8aa92ef73050725ae9bb8362a78 Mon Sep 17 00:00:00 2001 From: mikelchai Date: Thu, 1 Nov 2018 13:35:05 -0700 Subject: [PATCH 01/33] Transfer timeouts to the right buckets (#439) --- build.cake | 3 ++- src/DotNetty.Common/Utilities/HashedWheelTimer.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build.cake b/build.cake index f8528a2fa..bdf1417aa 100644 --- a/build.cake +++ b/build.cake @@ -13,9 +13,10 @@ var version = Argument("targetversion", $"{releaseNote.Version}.{buildNu var skipClean = Argument("skipclean", false); var skipTests = Argument("skiptests", false); var nogit = Argument("nogit", false); +var config = Argument("configuration", "Release"); // Variables -var configuration = IsRunningOnWindows() ? "Release" : "MonoRelease"; +var configuration = IsRunningOnWindows() ? config : "MonoRelease"; var csProjectFiles = GetFiles("./src/**/*.csproj"); // Directories diff --git a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs index 2f3428cbb..cd37cb1ed 100644 --- a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs +++ b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs @@ -353,7 +353,7 @@ void TransferTimeoutsToBuckets() continue; } - long calculated = (timeout.Deadline.Ticks + this.owner.tickDuration - 1) / this.owner.tickDuration; // ceiling to timeout later rather than earlier + long calculated = timeout.Deadline.Ticks / this.owner.tickDuration; timeout.RemainingRounds = (calculated - this.tick) / this.owner.wheel.Length; long ticks = Math.Max(calculated, this.tick); // Ensure we don't schedule for past. From 4a76e624580e0005257513fce1c69555294763f5 Mon Sep 17 00:00:00 2001 From: mikelchai Date: Sat, 3 Nov 2018 20:32:51 -0700 Subject: [PATCH 02/33] Fix the exception message in ExpireTimeouts (#440) --- src/DotNetty.Common/Utilities/HashedWheelTimer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs index cd37cb1ed..af96b56c6 100644 --- a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs +++ b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs @@ -615,7 +615,7 @@ public void ExpireTimeouts(TimeSpan deadline) // The timeout was placed into a wrong slot. This should never happen. throw new InvalidOperationException( string.Format( - "timeout.deadline (%d) > deadline (%d)", + "timeout.deadline {0} > deadline {1}", timeout.Deadline, deadline)); } From 72deeb9a09627763ef82e543109a8a85a5334095 Mon Sep 17 00:00:00 2001 From: SilverFox Date: Wed, 26 Jun 2019 01:19:11 +0800 Subject: [PATCH 03/33] Less allocation for IdleStateHandler (#496) --- src/DotNetty.Handlers/Timeout/IdleStateHandler.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/DotNetty.Handlers/Timeout/IdleStateHandler.cs b/src/DotNetty.Handlers/Timeout/IdleStateHandler.cs index f20f52fab..c94f6c777 100644 --- a/src/DotNetty.Handlers/Timeout/IdleStateHandler.cs +++ b/src/DotNetty.Handlers/Timeout/IdleStateHandler.cs @@ -96,7 +96,12 @@ public class IdleStateHandler : ChannelDuplexHandler { static readonly TimeSpan MinTimeout = TimeSpan.FromMilliseconds(1); - readonly Action writeListener; + static readonly Action writeListener = (antecedent, state) => + { + var self = (IdleStateHandler)state; + self.lastWriteTime = self.Ticks(); + self.firstWriterIdleEvent = self.firstAllIdleEvent = true; + }; readonly bool observeOutput; readonly TimeSpan readerIdleTime; @@ -200,12 +205,6 @@ public IdleStateHandler(bool observeOutput, this.allIdleTime = allIdleTime > TimeSpan.Zero ? TimeUtil.Max(allIdleTime, IdleStateHandler.MinTimeout) : TimeSpan.Zero; - - this.writeListener = new Action(antecedent => - { - this.lastWriteTime = this.Ticks(); - this.firstWriterIdleEvent = this.firstAllIdleEvent = true; - }); } /// @@ -308,7 +307,7 @@ public override Task WriteAsync(IChannelHandlerContext context, object message) if (this.writerIdleTime.Ticks > 0 || this.allIdleTime.Ticks > 0) { Task task = context.WriteAsync(message); - task.ContinueWith(this.writeListener, TaskContinuationOptions.ExecuteSynchronously); + task.ContinueWith(writeListener, this, TaskContinuationOptions.ExecuteSynchronously); return task; } From 13f009426687afc7c8d60ea653f6bc59d520eb2b Mon Sep 17 00:00:00 2001 From: SilverFox Date: Tue, 9 Jul 2019 23:12:59 +0800 Subject: [PATCH 04/33] Fix an spell error (#494) --- src/DotNetty.Buffers/PoolSubpage.cs | 4 ++-- src/DotNetty.Buffers/PooledByteBufferAllocator.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DotNetty.Buffers/PoolSubpage.cs b/src/DotNetty.Buffers/PoolSubpage.cs index 678f75523..6186ddddc 100644 --- a/src/DotNetty.Buffers/PoolSubpage.cs +++ b/src/DotNetty.Buffers/PoolSubpage.cs @@ -250,8 +250,8 @@ public override string ToString() return "(" + this.memoryMapIdx + ": not in use)"; } - return '(' + this.memoryMapIdx + ": " + (maxNumElems - numAvail) + '/' + maxNumElems + - ", offset: " + this.runOffset + ", length: " + this.pageSize + ", elemSize: " + elemSize + ')'; + return "(" + this.memoryMapIdx + ": " + (maxNumElems - numAvail) + "/" + maxNumElems + + ", offset: " + this.runOffset + ", length: " + this.pageSize + ", elemSize: " + elemSize + ")"; } public int MaxNumElements diff --git a/src/DotNetty.Buffers/PooledByteBufferAllocator.cs b/src/DotNetty.Buffers/PooledByteBufferAllocator.cs index 7d52c0a48..a7e9ab082 100644 --- a/src/DotNetty.Buffers/PooledByteBufferAllocator.cs +++ b/src/DotNetty.Buffers/PooledByteBufferAllocator.cs @@ -274,7 +274,7 @@ protected unsafe override IByteBuffer NewDirectBuffer(int initialCapacity, int m public static bool DefaultPreferDirect => PlatformDependent.DirectBufferPreferred; - public override bool IsDirectBufferPooled => this.heapArenas != null; + public override bool IsDirectBufferPooled => this.directArenas != null; sealed class PoolThreadLocalCache : FastThreadLocal> { From d65154c3c41b62971803e91710562d1053014ba9 Mon Sep 17 00:00:00 2001 From: SilverFox Date: Wed, 16 Oct 2019 05:28:22 +0800 Subject: [PATCH 05/33] Avoid throw SocketException(10057) in TcpSocketChannel.DoClose when the Socket is not connected (#508) --- .../Channels/Sockets/TcpSocketChannel.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/DotNetty.Transport/Channels/Sockets/TcpSocketChannel.cs b/src/DotNetty.Transport/Channels/Sockets/TcpSocketChannel.cs index 2f2c9e95b..4e6b2fef1 100644 --- a/src/DotNetty.Transport/Channels/Sockets/TcpSocketChannel.cs +++ b/src/DotNetty.Transport/Channels/Sockets/TcpSocketChannel.cs @@ -170,9 +170,12 @@ protected override void DoClose() { try { - if (this.TryResetState(StateFlags.Open | StateFlags.Active)) + if (this.TryResetState(StateFlags.Open)) { - this.Socket.Shutdown(SocketShutdown.Both); + if (this.TryResetState(StateFlags.Active)) + { + this.Socket.Shutdown(SocketShutdown.Both); + } this.Socket.Dispose(); } } From 5bfd679ae517c1ec363b47c41f42e64f3336e802 Mon Sep 17 00:00:00 2001 From: Dimitris Deligiorgis Date: Wed, 16 Oct 2019 00:33:00 +0300 Subject: [PATCH 06/33] mark GetUnadjustedFrameLength as virtual (#506) --- src/DotNetty.Codecs/LengthFieldBasedFrameDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DotNetty.Codecs/LengthFieldBasedFrameDecoder.cs b/src/DotNetty.Codecs/LengthFieldBasedFrameDecoder.cs index 15e7078f4..3ae0aaf52 100644 --- a/src/DotNetty.Codecs/LengthFieldBasedFrameDecoder.cs +++ b/src/DotNetty.Codecs/LengthFieldBasedFrameDecoder.cs @@ -398,7 +398,7 @@ protected virtual object Decode(IChannelHandlerContext context, IByteBuffer inpu /// The length of the framelenght field. Expected: 1, 2, 3, 4, or 8. /// The preferred of buffer. /// A long integer that represents the unadjusted length of the next frame. - protected long GetUnadjustedFrameLength(IByteBuffer buffer, int offset, int length, ByteOrder order) + protected virtual long GetUnadjustedFrameLength(IByteBuffer buffer, int offset, int length, ByteOrder order) { long frameLength; switch (length) From a9d0723ba5994c1b98bb43ed452996d51beb1a7c Mon Sep 17 00:00:00 2001 From: Max Gortman Date: Wed, 16 Oct 2019 22:27:45 -0700 Subject: [PATCH 07/33] STE: Provide indicators of progress (#517) extra: give access to executors within executor group --- .../Concurrency/AbstractEventExecutor.cs | 6 +++ .../Concurrency/AbstractEventExecutorGroup.cs | 5 ++ .../Concurrency/IEventExecutorGroup.cs | 6 +++ .../Concurrency/SingleThreadEventExecutor.cs | 51 +++++++++++++------ .../DispatcherEventLoop.cs | 3 ++ .../DispatcherEventLoopGroup.cs | 5 ++ src/DotNetty.Transport.Libuv/EventLoop.cs | 3 ++ .../EventLoopGroup.cs | 5 ++ src/DotNetty.Transport.Libuv/LoopExecutor.cs | 10 ++-- .../WorkerEventLoop.cs | 3 ++ .../WorkerEventLoopGroup.cs | 5 ++ .../Channels/AffinitizedEventLoopGroup.cs | 5 ++ .../Channels/Embedded/EmbeddedEventLoop.cs | 8 ++- .../Channels/IEventLoopGroup.cs | 8 ++- .../Channels/MultithreadEventLoopGroup.cs | 7 +++ .../Channels/SingleThreadEventLoop.cs | 3 ++ 16 files changed, 110 insertions(+), 23 deletions(-) diff --git a/src/DotNetty.Common/Concurrency/AbstractEventExecutor.cs b/src/DotNetty.Common/Concurrency/AbstractEventExecutor.cs index 9a0efe00d..36a2ddd2e 100644 --- a/src/DotNetty.Common/Concurrency/AbstractEventExecutor.cs +++ b/src/DotNetty.Common/Concurrency/AbstractEventExecutor.cs @@ -4,6 +4,7 @@ namespace DotNetty.Common.Concurrency { using System; + using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using DotNetty.Common.Internal.Logging; @@ -46,6 +47,11 @@ protected AbstractEventExecutor(IEventExecutorGroup parent) /// public bool InEventLoop => this.IsInEventLoop(Thread.CurrentThread); + /// + public IEnumerable Items => this.GetItems(); + + protected abstract IEnumerable GetItems(); + /// public abstract bool IsInEventLoop(Thread thread); diff --git a/src/DotNetty.Common/Concurrency/AbstractEventExecutorGroup.cs b/src/DotNetty.Common/Concurrency/AbstractEventExecutorGroup.cs index c9e7653e5..5cbe1149d 100644 --- a/src/DotNetty.Common/Concurrency/AbstractEventExecutorGroup.cs +++ b/src/DotNetty.Common/Concurrency/AbstractEventExecutorGroup.cs @@ -4,6 +4,7 @@ namespace DotNetty.Common.Concurrency { using System; + using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -20,6 +21,8 @@ public abstract class AbstractEventExecutorGroup : IEventExecutorGroup public abstract Task TerminationCompletion { get; } + public IEnumerable Items => this.GetItems(); + public abstract IEventExecutor GetNext(); public void Execute(IRunnable task) => this.GetNext().Execute(task); @@ -65,5 +68,7 @@ public abstract class AbstractEventExecutorGroup : IEventExecutorGroup public Task ShutdownGracefullyAsync() => this.ShutdownGracefullyAsync(DefaultShutdownQuietPeriod, DefaultShutdownTimeout); public abstract Task ShutdownGracefullyAsync(TimeSpan quietPeriod, TimeSpan timeout); + + protected abstract IEnumerable GetItems(); } } \ No newline at end of file diff --git a/src/DotNetty.Common/Concurrency/IEventExecutorGroup.cs b/src/DotNetty.Common/Concurrency/IEventExecutorGroup.cs index 1d0af9c9c..091cbf966 100644 --- a/src/DotNetty.Common/Concurrency/IEventExecutorGroup.cs +++ b/src/DotNetty.Common/Concurrency/IEventExecutorGroup.cs @@ -4,6 +4,7 @@ namespace DotNetty.Common.Concurrency { using System; + using System.Collections.Generic; using System.Threading.Tasks; /// @@ -11,6 +12,11 @@ namespace DotNetty.Common.Concurrency /// public interface IEventExecutorGroup : IScheduledExecutorService { + /// + /// Returns list of owned event executors. + /// + IEnumerable Items { get; } + /// /// Returns true if and only if this executor is being shut down via . /// diff --git a/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs b/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs index 7cd814dc6..225871962 100644 --- a/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs +++ b/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs @@ -45,6 +45,7 @@ public class SingleThreadEventExecutor : AbstractScheduledEventExecutor PreciseTimeSpan gracefulShutdownQuietPeriod; PreciseTimeSpan gracefulShutdownTimeout; readonly ISet shutdownHooks = new HashSet(); + long progress; /// Creates a new instance of . public SingleThreadEventExecutor(string threadName, TimeSpan breakoutInterval) @@ -86,6 +87,21 @@ protected SingleThreadEventExecutor(IEventExecutorGroup parent, string threadNam /// public TaskScheduler Scheduler => this.scheduler; + /// + /// Allows to track whether executor is progressing through its backlog. Useful for diagnosing / mitigating stalls due to blocking calls in conjunction with IsBacklogEmpty property. + /// + public long Progress => Volatile.Read(ref this.progress); + + /// + /// Indicates whether executor's backlog is empty. Useful for diagnosing / mitigating stalls due to blocking calls in conjunction with Progress property. + /// + public bool IsBacklogEmpty => this.taskQueue.IsEmpty; + + /// + /// Gets length of backlog of tasks queued for immediate execution. + /// + public int BacklogLength => this.taskQueue.Count; + void Loop() { this.SetCurrentExecutor(this); @@ -140,6 +156,8 @@ public override void Execute(IRunnable task) } } + protected override IEnumerable GetItems() => new[] { this }; + protected void WakeUp(bool inEventLoop) { if (!inEventLoop || (this.executionState == ST_SHUTTING_DOWN)) @@ -152,12 +170,12 @@ protected void WakeUp(bool inEventLoop) /// Adds an which will be executed on shutdown of this instance. /// /// The to run on shutdown. - public void AddShutdownHook(Action action) + public void AddShutdownHook(Action action) { - if (this.InEventLoop) + if (this.InEventLoop) { this.shutdownHooks.Add(action); - } + } else { this.Execute(() => this.shutdownHooks.Add(action)); @@ -169,53 +187,53 @@ public void AddShutdownHook(Action action) /// executed on shutdown of this instance. /// /// The to remove. - public void RemoveShutdownHook(Action action) + public void RemoveShutdownHook(Action action) { - if (this.InEventLoop) + if (this.InEventLoop) { this.shutdownHooks.Remove(action); - } + } else { this.Execute(() => this.shutdownHooks.Remove(action)); } } - bool RunShutdownHooks() + bool RunShutdownHooks() { bool ran = false; - + // Note shutdown hooks can add / remove shutdown hooks. - while (this.shutdownHooks.Count > 0) + while (this.shutdownHooks.Count > 0) { var copy = this.shutdownHooks.ToArray(); this.shutdownHooks.Clear(); for (var i = 0; i < copy.Length; i++) { - try + try { copy[i](); - } - catch (Exception ex) + } + catch (Exception ex) { Logger.Warn("Shutdown hook raised an exception.", ex); - } - finally + } + finally { ran = true; } } } - if (ran) + if (ran) { this.lastExecutionTime = PreciseTimeSpan.FromStart; } return ran; } - + /// public override Task ShutdownGracefullyAsync(TimeSpan quietPeriod, TimeSpan timeout) @@ -398,6 +416,7 @@ protected bool RunAllTasks() while (true) { + Volatile.Write(ref this.progress, this.progress + 1); // volatile write is enough as this is the only thread ever writing SafeExecute(task); task = this.PollTask(); if (task == null) diff --git a/src/DotNetty.Transport.Libuv/DispatcherEventLoop.cs b/src/DotNetty.Transport.Libuv/DispatcherEventLoop.cs index d05550acf..788598694 100644 --- a/src/DotNetty.Transport.Libuv/DispatcherEventLoop.cs +++ b/src/DotNetty.Transport.Libuv/DispatcherEventLoop.cs @@ -4,6 +4,7 @@ namespace DotNetty.Transport.Libuv { using System; + using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; @@ -69,5 +70,7 @@ internal void Dispatch(NativeHandle handle) public Task RegisterAsync(IChannel channel) => channel.Unsafe.RegisterAsync(this); public new IEventLoopGroup Parent => (IEventLoopGroup)base.Parent; + + public new IEnumerable Items => new[] { this }; } } \ No newline at end of file diff --git a/src/DotNetty.Transport.Libuv/DispatcherEventLoopGroup.cs b/src/DotNetty.Transport.Libuv/DispatcherEventLoopGroup.cs index 646ad6b45..3b9010096 100644 --- a/src/DotNetty.Transport.Libuv/DispatcherEventLoopGroup.cs +++ b/src/DotNetty.Transport.Libuv/DispatcherEventLoopGroup.cs @@ -6,6 +6,7 @@ namespace DotNetty.Transport.Libuv { using System; + using System.Collections.Generic; using System.Threading.Tasks; using DotNetty.Common.Concurrency; using DotNetty.Transport.Channels; @@ -29,6 +30,10 @@ public DispatcherEventLoopGroup() internal DispatcherEventLoop Dispatcher => this.dispatcherEventLoop; + protected override IEnumerable GetItems() => new[] { this.dispatcherEventLoop }; + + public new IEnumerable Items => new[] { this.dispatcherEventLoop }; + IEventLoop IEventLoopGroup.GetNext() => (IEventLoop)this.GetNext(); public override IEventExecutor GetNext() => this.dispatcherEventLoop; diff --git a/src/DotNetty.Transport.Libuv/EventLoop.cs b/src/DotNetty.Transport.Libuv/EventLoop.cs index f3cade01d..fcced02e8 100644 --- a/src/DotNetty.Transport.Libuv/EventLoop.cs +++ b/src/DotNetty.Transport.Libuv/EventLoop.cs @@ -3,6 +3,7 @@ namespace DotNetty.Transport.Libuv { + using System.Collections.Generic; using System.Threading.Tasks; using DotNetty.Transport.Channels; @@ -19,5 +20,7 @@ public EventLoop(IEventLoopGroup parent, string threadName) public Task RegisterAsync(IChannel channel) => channel.Unsafe.RegisterAsync(this); public new IEventLoopGroup Parent => (IEventLoopGroup)base.Parent; + + public new IEnumerable Items => new[] { this }; } } \ No newline at end of file diff --git a/src/DotNetty.Transport.Libuv/EventLoopGroup.cs b/src/DotNetty.Transport.Libuv/EventLoopGroup.cs index 1df143da1..d58e8bded 100644 --- a/src/DotNetty.Transport.Libuv/EventLoopGroup.cs +++ b/src/DotNetty.Transport.Libuv/EventLoopGroup.cs @@ -6,6 +6,7 @@ namespace DotNetty.Transport.Libuv { using System; + using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -27,6 +28,8 @@ public sealed class EventLoopGroup : AbstractEventExecutorGroup, IEventLoopGroup public override Task TerminationCompletion { get; } + public new IEnumerable Items => this.eventLoops; + public EventLoopGroup() : this(DefaultEventLoopCount) { @@ -119,5 +122,7 @@ public override Task ShutdownGracefullyAsync(TimeSpan quietPeriod, TimeSpan time } return this.TerminationCompletion; } + + protected override IEnumerable GetItems() => this.eventLoops; } } \ No newline at end of file diff --git a/src/DotNetty.Transport.Libuv/LoopExecutor.cs b/src/DotNetty.Transport.Libuv/LoopExecutor.cs index 6f4c0f410..373624c37 100644 --- a/src/DotNetty.Transport.Libuv/LoopExecutor.cs +++ b/src/DotNetty.Transport.Libuv/LoopExecutor.cs @@ -7,6 +7,7 @@ namespace DotNetty.Transport.Libuv { using System; + using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Contracts; using System.Threading.Tasks; @@ -17,7 +18,6 @@ namespace DotNetty.Transport.Libuv using System.Threading; using DotNetty.Common; using DotNetty.Transport.Libuv.Native; - using Timer = Native.Timer; class LoopExecutor : AbstractScheduledEventExecutor @@ -297,7 +297,7 @@ void RunAllTasks(long timeout) long runTasks = 0; long executionTime; this.wakeUp = false; - for (;;) + for (; ; ) { SafeExecute(task); @@ -402,7 +402,7 @@ static bool RunAllTasksFrom(IQueue taskQueue) { return false; } - for (;;) + for (; ; ) { SafeExecute(task); task = PollTaskFrom(taskQueue); @@ -488,7 +488,7 @@ public override Task ShutdownGracefullyAsync(TimeSpan quietPeriod, TimeSpan time bool inEventLoop = this.InEventLoop; bool wakeUpLoop; int oldState; - for (;;) + for (; ; ) { if (this.IsShuttingDown) { @@ -540,5 +540,7 @@ public override Task ShutdownGracefullyAsync(TimeSpan quietPeriod, TimeSpan time return this.TerminationCompletion; } + + protected override IEnumerable GetItems() => new[] { this }; } } diff --git a/src/DotNetty.Transport.Libuv/WorkerEventLoop.cs b/src/DotNetty.Transport.Libuv/WorkerEventLoop.cs index df0f8b408..214818460 100644 --- a/src/DotNetty.Transport.Libuv/WorkerEventLoop.cs +++ b/src/DotNetty.Transport.Libuv/WorkerEventLoop.cs @@ -7,6 +7,7 @@ namespace DotNetty.Transport.Libuv { using System; + using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Contracts; using System.Threading.Tasks; @@ -112,6 +113,8 @@ void OnRead(Pipe handle, int status) public new IEventLoopGroup Parent => (IEventLoopGroup)base.Parent; + IEnumerable IEventLoopGroup.Items => new[] { this }; + sealed class PipeConnect : ConnectRequest { const int MaximumRetryCount = 10; diff --git a/src/DotNetty.Transport.Libuv/WorkerEventLoopGroup.cs b/src/DotNetty.Transport.Libuv/WorkerEventLoopGroup.cs index 87ac1c1df..a8986ca17 100644 --- a/src/DotNetty.Transport.Libuv/WorkerEventLoopGroup.cs +++ b/src/DotNetty.Transport.Libuv/WorkerEventLoopGroup.cs @@ -6,6 +6,7 @@ namespace DotNetty.Transport.Libuv { using System; + using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Contracts; using System.Linq; @@ -84,6 +85,8 @@ public WorkerEventLoopGroup(DispatcherEventLoopGroup eventLoopGroup, int eventLo internal string PipeName { get; } + IEnumerable IEventLoopGroup.Items => this.eventLoops; + internal void Accept(NativeHandle handle) { Debug.Assert(this.dispatcherLoop != null); @@ -126,5 +129,7 @@ public override Task ShutdownGracefullyAsync(TimeSpan quietPeriod, TimeSpan time } return this.TerminationCompletion; } + + protected override IEnumerable GetItems() => this.eventLoops; } } \ No newline at end of file diff --git a/src/DotNetty.Transport/Channels/AffinitizedEventLoopGroup.cs b/src/DotNetty.Transport/Channels/AffinitizedEventLoopGroup.cs index 25d487f3b..fa72871f2 100644 --- a/src/DotNetty.Transport/Channels/AffinitizedEventLoopGroup.cs +++ b/src/DotNetty.Transport/Channels/AffinitizedEventLoopGroup.cs @@ -4,6 +4,7 @@ namespace DotNetty.Transport.Channels { using System; + using System.Collections.Generic; using System.Threading.Tasks; using DotNetty.Common.Concurrency; @@ -23,6 +24,10 @@ public class AffinitizedEventLoopGroup : AbstractEventExecutorGroup, IEventLoopG /// public override Task TerminationCompletion => this.innerGroup.TerminationCompletion; + protected override IEnumerable GetItems() => this.innerGroup.Items; + + public new IEnumerable Items => ((IEventLoopGroup)this.innerGroup).Items; + /// /// Creates a new instance of . /// diff --git a/src/DotNetty.Transport/Channels/Embedded/EmbeddedEventLoop.cs b/src/DotNetty.Transport/Channels/Embedded/EmbeddedEventLoop.cs index 9419861e5..6e5b0f557 100644 --- a/src/DotNetty.Transport/Channels/Embedded/EmbeddedEventLoop.cs +++ b/src/DotNetty.Transport/Channels/Embedded/EmbeddedEventLoop.cs @@ -28,6 +28,10 @@ sealed class EmbeddedEventLoop : AbstractScheduledEventExecutor, IEventLoop public new IEventLoopGroup Parent => (IEventLoopGroup)base.Parent; + protected override IEnumerable GetItems() => new[] { this }; + + public new IEnumerable Items => new[] { this }; + public override bool IsInEventLoop(Thread thread) => true; public override void Execute(IRunnable command) @@ -48,7 +52,7 @@ public override Task ShutdownGracefullyAsync(TimeSpan quietPeriod, TimeSpan time internal void RunTasks() { - for (;;) + for (; ; ) { // have to perform an additional check since Queue throws upon empty dequeue in .NET if (this.tasks.Count == 0) @@ -67,7 +71,7 @@ internal void RunTasks() internal PreciseTimeSpan RunScheduledTasks() { PreciseTimeSpan time = GetNanos(); - for (;;) + for (; ; ) { IRunnable task = this.PollScheduledTask(time); if (task == null) diff --git a/src/DotNetty.Transport/Channels/IEventLoopGroup.cs b/src/DotNetty.Transport/Channels/IEventLoopGroup.cs index 43e8a2865..cdc5b99dd 100644 --- a/src/DotNetty.Transport/Channels/IEventLoopGroup.cs +++ b/src/DotNetty.Transport/Channels/IEventLoopGroup.cs @@ -3,6 +3,7 @@ namespace DotNetty.Transport.Channels { + using System.Collections.Generic; using System.Threading.Tasks; using DotNetty.Common.Concurrency; @@ -13,7 +14,12 @@ namespace DotNetty.Transport.Channels public interface IEventLoopGroup : IEventExecutorGroup { /// - /// Returns . + /// Returns list of owned event loops. + /// + new IEnumerable Items { get; } + + /// + /// Returns one of owned event loops. /// new IEventLoop GetNext(); diff --git a/src/DotNetty.Transport/Channels/MultithreadEventLoopGroup.cs b/src/DotNetty.Transport/Channels/MultithreadEventLoopGroup.cs index 4ef18c90d..24b9b6d5f 100644 --- a/src/DotNetty.Transport/Channels/MultithreadEventLoopGroup.cs +++ b/src/DotNetty.Transport/Channels/MultithreadEventLoopGroup.cs @@ -4,6 +4,7 @@ namespace DotNetty.Transport.Channels { using System; + using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -29,6 +30,12 @@ public sealed class MultithreadEventLoopGroup : AbstractEventExecutorGroup, IEve /// public override Task TerminationCompletion { get; } + /// + protected override IEnumerable GetItems() => this.eventLoops; + + /// + public new IEnumerable Items => this.eventLoops; + /// Creates a new instance of . public MultithreadEventLoopGroup() : this(DefaultEventLoopFactory, DefaultEventLoopThreadCount) diff --git a/src/DotNetty.Transport/Channels/SingleThreadEventLoop.cs b/src/DotNetty.Transport/Channels/SingleThreadEventLoop.cs index 360b1527b..ddf2c25df 100644 --- a/src/DotNetty.Transport/Channels/SingleThreadEventLoop.cs +++ b/src/DotNetty.Transport/Channels/SingleThreadEventLoop.cs @@ -4,6 +4,7 @@ namespace DotNetty.Transport.Channels { using System; + using System.Collections.Generic; using System.Threading.Tasks; using DotNetty.Common.Concurrency; using DotNetty.Common.Internal; @@ -70,5 +71,7 @@ protected SingleThreadEventLoop(IEventLoopGroup parent, string threadName, TimeS /// public new IEventLoopGroup Parent => (IEventLoopGroup)base.Parent; + + public new IEnumerable Items => new[] { this }; } } \ No newline at end of file From abda435273e979a2856964ab9ea6aafebcf1b8ef Mon Sep 17 00:00:00 2001 From: Max Gortman Date: Mon, 21 Oct 2019 12:24:25 -0700 Subject: [PATCH 08/33] Don't pool buffer objects (#518) * wip * fixing async stream->buffer --- src/DotNetty.Buffers/PooledByteBuffer.cs | 17 +--------- src/DotNetty.Buffers/PooledHeapByteBuffer.cs | 16 ++++----- .../PooledUnsafeDirectByteBuffer.cs | 22 ++++++------ .../UnpooledUnsafeDirectByteBuffer.cs | 6 ++-- src/DotNetty.Buffers/UnsafeByteBufferUtil.cs | 34 +++++++++++++++++++ 5 files changed, 58 insertions(+), 37 deletions(-) diff --git a/src/DotNetty.Buffers/PooledByteBuffer.cs b/src/DotNetty.Buffers/PooledByteBuffer.cs index 8192b0cde..1960c6819 100644 --- a/src/DotNetty.Buffers/PooledByteBuffer.cs +++ b/src/DotNetty.Buffers/PooledByteBuffer.cs @@ -6,13 +6,10 @@ namespace DotNetty.Buffers using System; using System.Diagnostics; using System.Runtime.CompilerServices; - using DotNetty.Common; using DotNetty.Common.Utilities; abstract class PooledByteBuffer : AbstractReferenceCountedByteBuffer { - readonly ThreadLocalPool.Handle recyclerHandle; - protected internal PoolChunk Chunk; protected internal long Handle; protected internal T Memory; @@ -22,10 +19,9 @@ abstract class PooledByteBuffer : AbstractReferenceCountedByteBuffer internal PoolThreadCache Cache; PooledByteBufferAllocator allocator; - protected PooledByteBuffer(ThreadLocalPool.Handle recyclerHandle, int maxCapacity) + protected PooledByteBuffer(int maxCapacity) : base(maxCapacity) { - this.recyclerHandle = recyclerHandle; } internal virtual void Init(PoolChunk chunk, long handle, int offset, int length, int maxLength, PoolThreadCache cache) => @@ -51,14 +47,6 @@ void Init0(PoolChunk chunk, long handle, int offset, int length, int maxLengt /** * Method must be called before reuse this {@link PooledByteBufAllocator} */ - internal void Reuse(int maxCapacity) - { - this.SetMaxCapacity(maxCapacity); - this.SetReferenceCount(1); - this.SetIndex0(0, 0); - this.DiscardMarks(); - } - public override int Capacity { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -143,12 +131,9 @@ protected internal sealed override void Deallocate() this.Memory = default(T); this.Chunk.Arena.Free(this.Chunk, handle, this.MaxLength, this.Cache); this.Chunk = null; - this.Recycle(); } } - void Recycle() => this.recyclerHandle.Release(this); - [MethodImpl(MethodImplOptions.AggressiveInlining)] protected int Idx(int index) => this.Offset + index; } diff --git a/src/DotNetty.Buffers/PooledHeapByteBuffer.cs b/src/DotNetty.Buffers/PooledHeapByteBuffer.cs index 35558a1ee..02e315cdd 100644 --- a/src/DotNetty.Buffers/PooledHeapByteBuffer.cs +++ b/src/DotNetty.Buffers/PooledHeapByteBuffer.cs @@ -7,22 +7,17 @@ namespace DotNetty.Buffers using System.IO; using System.Threading; using System.Threading.Tasks; - using DotNetty.Common; using DotNetty.Common.Internal; sealed class PooledHeapByteBuffer : PooledByteBuffer { - static readonly ThreadLocalPool Recycler = new ThreadLocalPool(handle => new PooledHeapByteBuffer(handle, 0)); - internal static PooledHeapByteBuffer NewInstance(int maxCapacity) { - PooledHeapByteBuffer buf = Recycler.Take(); - buf.Reuse(maxCapacity); - return buf; + return new PooledHeapByteBuffer(maxCapacity); } - internal PooledHeapByteBuffer(ThreadLocalPool.Handle recyclerHandle, int maxCapacity) - : base(recyclerHandle, maxCapacity) + internal PooledHeapByteBuffer(int maxCapacity) + : base(maxCapacity) { } @@ -108,6 +103,11 @@ public override IByteBuffer SetBytes(int index, IByteBuffer src, int srcIndex, i public override async Task SetBytesAsync(int index, Stream src, int length, CancellationToken cancellationToken) { + if (length == 0) + { + return 0; + } + int readTotal = 0; int read; int offset = this.ArrayOffset + index; diff --git a/src/DotNetty.Buffers/PooledUnsafeDirectByteBuffer.cs b/src/DotNetty.Buffers/PooledUnsafeDirectByteBuffer.cs index 8eb636a64..5ae1d3e0e 100644 --- a/src/DotNetty.Buffers/PooledUnsafeDirectByteBuffer.cs +++ b/src/DotNetty.Buffers/PooledUnsafeDirectByteBuffer.cs @@ -8,23 +8,18 @@ namespace DotNetty.Buffers using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; - using DotNetty.Common; sealed unsafe class PooledUnsafeDirectByteBuffer : PooledByteBuffer { - static readonly ThreadLocalPool Recycler = new ThreadLocalPool(handle => new PooledUnsafeDirectByteBuffer(handle, 0)); - byte* memoryAddress; internal static PooledUnsafeDirectByteBuffer NewInstance(int maxCapacity) { - PooledUnsafeDirectByteBuffer buf = Recycler.Take(); - buf.Reuse(maxCapacity); - return buf; + return new PooledUnsafeDirectByteBuffer(maxCapacity); } - PooledUnsafeDirectByteBuffer(ThreadLocalPool.Handle recyclerHandle, int maxCapacity) - : base(recyclerHandle, maxCapacity) + PooledUnsafeDirectByteBuffer(int maxCapacity) + : base(maxCapacity) { } @@ -48,6 +43,14 @@ void InitMemoryAddress() public override bool IsDirect => true; + internal void Reuse(int maxCapacity) + { + this.SetMaxCapacity(maxCapacity); + this.SetReferenceCount(1); + this.SetIndex0(0, 0); + this.DiscardMarks(); + } + protected internal override byte _GetByte(int index) => *(this.memoryAddress + index); protected internal override short _GetShort(int index) => UnsafeByteBufferUtil.GetShort(this.Addr(index)); @@ -121,8 +124,7 @@ public override IByteBuffer SetBytes(int index, byte[] src, int srcIndex, int le public override Task SetBytesAsync(int index, Stream src, int length, CancellationToken cancellationToken) { this.CheckIndex(index, length); - int read = UnsafeByteBufferUtil.SetBytes(this, this.Addr(index), index, src, length); - return Task.FromResult(read); + return UnsafeByteBufferUtil.SetBytesAsync(this, this.Addr(index), index, src, length, cancellationToken); } public override IByteBuffer Copy(int index, int length) diff --git a/src/DotNetty.Buffers/UnpooledUnsafeDirectByteBuffer.cs b/src/DotNetty.Buffers/UnpooledUnsafeDirectByteBuffer.cs index 9da1340c9..e0f7e8c8e 100644 --- a/src/DotNetty.Buffers/UnpooledUnsafeDirectByteBuffer.cs +++ b/src/DotNetty.Buffers/UnpooledUnsafeDirectByteBuffer.cs @@ -8,9 +8,11 @@ namespace DotNetty.Buffers using System.Diagnostics.Contracts; using System.IO; using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using DotNetty.Common.Internal; + using DotNetty.Common.Utilities; public unsafe class UnpooledUnsafeDirectByteBuffer : AbstractReferenceCountedByteBuffer { @@ -294,10 +296,8 @@ public override IByteBuffer GetBytes(int index, Stream output, int length) public override Task SetBytesAsync(int index, Stream src, int length, CancellationToken cancellationToken) { this.CheckIndex(index, length); - int read; fixed (byte* addr = &this.Addr(index)) - read = UnsafeByteBufferUtil.SetBytes(this, addr, index, src, length); - return Task.FromResult(read); + return UnsafeByteBufferUtil.SetBytesAsync(this, addr, index, src, length, cancellationToken); } public override int IoBufferCount => 1; diff --git a/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs b/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs index 28fa6779d..5bcbbfa8b 100644 --- a/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs +++ b/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs @@ -8,7 +8,10 @@ namespace DotNetty.Buffers using System.IO; using System.Runtime.CompilerServices; using System.Text; + using System.Threading; + using System.Threading.Tasks; using DotNetty.Common.Internal; + using DotNetty.Common.Utilities; static unsafe class UnsafeByteBufferUtil { @@ -214,6 +217,11 @@ internal static IByteBuffer Copy(AbstractByteBuffer buf, byte* addr, int index, internal static int SetBytes(AbstractByteBuffer buf, byte* addr, int index, Stream input, int length) { + if (length == 0) + { + return 0; + } + IByteBuffer tmpBuf = buf.Allocator.HeapBuffer(length); try { @@ -233,6 +241,32 @@ internal static int SetBytes(AbstractByteBuffer buf, byte* addr, int index, Stre } } + internal static Task SetBytesAsync(AbstractByteBuffer buf, byte* addr, int index, Stream input, int length, CancellationToken cancellationToken) + { + if (length == 0) + { + return TaskEx.Zero; + } + + IByteBuffer tmpBuf = buf.Allocator.HeapBuffer(length); + return tmpBuf.SetBytesAsync(0, input, length, cancellationToken) + .ContinueWith(t => { + try + { + var read = t.Result; + if (read > 0) + { + PlatformDependent.CopyMemory(tmpBuf.Array, tmpBuf.ArrayOffset, addr, read); + } + return read; + } + finally + { + tmpBuf.Release(); + } + }); + } + internal static void GetBytes(AbstractByteBuffer buf, byte* addr, int index, IByteBuffer dst, int dstIndex, int length) { Contract.Requires(dst != null); From 780acdb07aaa369cf05182f2eb4a21dce7c74b27 Mon Sep 17 00:00:00 2001 From: SilverFox Date: Tue, 22 Oct 2019 03:49:53 +0800 Subject: [PATCH 09/33] Port all properties io.netty.recycler.* and related logic (#497) --- src/DotNetty.Common/ThreadLocalPool.cs | 551 ++++++++++++++---- .../ThreadLocalPoolTest.cs | 230 ++++++-- 2 files changed, 629 insertions(+), 152 deletions(-) diff --git a/src/DotNetty.Common/ThreadLocalPool.cs b/src/DotNetty.Common/ThreadLocalPool.cs index 746555649..cbcc28290 100644 --- a/src/DotNetty.Common/ThreadLocalPool.cs +++ b/src/DotNetty.Common/ThreadLocalPool.cs @@ -3,7 +3,10 @@ namespace DotNetty.Common { + using DotNetty.Common.Internal; + using DotNetty.Common.Internal.Logging; using System; + using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.CompilerServices; using System.Threading; @@ -11,113 +14,230 @@ namespace DotNetty.Common public class ThreadLocalPool { - public sealed class Handle + public abstract class Handle + { + public abstract void Release(T value) + where T : class; + } + + protected sealed class NoopHandle : Handle + { + public static readonly NoopHandle Instance = new NoopHandle(); + + NoopHandle() + { + } + + public override void Release(T value) + { + } + } + + protected sealed class DefaultHandle : Handle { internal int lastRecycledId; internal int recycleId; - public object Value; + internal bool hasBeenRecycled; + + internal object Value; internal Stack Stack; - internal Handle(Stack stack) + internal DefaultHandle(Stack stack) { this.Stack = stack; } - public void Release(T value) - where T : class + public override void Release(T value) { Contract.Requires(value == this.Value, "value differs from one backed by this handle."); Stack stack = this.Stack; - Thread thread = Thread.CurrentThread; - if (stack.Thread == thread) - { - stack.Push(this); - return; - } - - ConditionalWeakTable queueDictionary = DelayedPool.Value; - WeakOrderQueue delayedRecycled; - if (!queueDictionary.TryGetValue(stack, out delayedRecycled)) + if (lastRecycledId != recycleId || stack == null) { - var newQueue = new WeakOrderQueue(stack, thread); - delayedRecycled = newQueue; - queueDictionary.Add(stack, delayedRecycled); + throw new InvalidOperationException("recycled already"); } - delayedRecycled.Add(this); + stack.Push(this); } } - internal sealed class WeakOrderQueue + // a queue that makes only moderate guarantees about visibility: items are seen in the correct order, + // but we aren't absolutely guaranteed to ever see anything at all, thereby keeping the queue cheap to maintain + protected sealed class WeakOrderQueue { - const int LinkCapacity = 16; + internal static readonly WeakOrderQueue Dummy = new WeakOrderQueue(); sealed class Link { - int writeIndex; + private int writeIndex; - internal readonly Handle[] elements; + internal readonly DefaultHandle[] elements = new DefaultHandle[LinkCapacity]; internal Link next; internal int ReadIndex { get; set; } internal int WriteIndex { - get { return Volatile.Read(ref this.writeIndex); } - set { Volatile.Write(ref this.writeIndex, value); } + get => Volatile.Read(ref writeIndex); + set => Volatile.Write(ref writeIndex, value); + } + + internal void LazySetWriteIndex(int value) => writeIndex = value; + } + + // This act as a place holder for the head Link but also will reclaim space once finalized. + // Its important this does not hold any reference to either Stack or WeakOrderQueue. + sealed class Head + { + readonly StrongBox availableSharedCapacity; + readonly StrongBox weakTableCounter; + + internal Link link; + + internal Head(StrongBox availableSharedCapacity, StrongBox weakTableCounter) + { + this.availableSharedCapacity = availableSharedCapacity; + this.weakTableCounter = weakTableCounter; + if (weakTableCounter != null) + Interlocked.Increment(ref weakTableCounter.Value); + } + + ~Head() + { + if (this.weakTableCounter != null) + { + Interlocked.Decrement(ref this.weakTableCounter.Value); + } + if (this.availableSharedCapacity == null) + { + return; + } + + Link head = this.link; + this.link = null; + while (head != null) + { + ReclaimSpace(LinkCapacity); + Link next = head.next; + // Unlink to help GC and guard against GC nepotism. + head.next = null; + head = next; + } + } + + internal void ReclaimSpace(int space) + { + Debug.Assert(space >= 0); + Interlocked.Add(ref availableSharedCapacity.Value, space); + } + + internal bool ReserveSpace(int space) + { + return ReserveSpace(availableSharedCapacity, space); } - internal Link() + internal static bool ReserveSpace(StrongBox availableSharedCapacity, int space) { - this.elements = new Handle[LinkCapacity]; + Debug.Assert(space >= 0); + for (; ; ) + { + int available = Volatile.Read(ref availableSharedCapacity.Value); + if (available < space) + { + return false; + } + if (Interlocked.CompareExchange(ref availableSharedCapacity.Value, available - space, available) == available) + { + return true; + } + } } } - Link head, tail; + // chain of data items + readonly Head head; + Link tail; + // pointer to another queue of delayed items for the same stack internal WeakOrderQueue next; - internal WeakReference ownerThread; + internal readonly WeakReference owner; readonly int id = Interlocked.Increment(ref idSource); - internal bool IsEmpty => this.tail.ReadIndex == this.tail.WriteIndex; + WeakOrderQueue() + { + owner = null; + head = new Head(null, null); + } + + WeakOrderQueue(Stack stack, Thread thread, DelayedThreadLocal.CountedWeakTable countedWeakTable) + { + this.tail = new Link(); + + // Its important that we not store the Stack itself in the WeakOrderQueue as the Stack also is used in + // the WeakHashMap as key. So just store the enclosed AtomicInteger which should allow to have the + // Stack itself GCed. + this.head = new Head(stack.availableSharedCapacity, countedWeakTable.Counter); + this.head.link = tail; + this.owner = new WeakReference(thread); + } - internal WeakOrderQueue(Stack stack, Thread thread) + static WeakOrderQueue NewQueue(Stack stack, Thread thread, DelayedThreadLocal.CountedWeakTable countedWeakTable) { - Contract.Requires(stack != null); + WeakOrderQueue queue = new WeakOrderQueue(stack, thread, countedWeakTable); + // Done outside of the constructor to ensure WeakOrderQueue.this does not escape the constructor and so + // may be accessed while its still constructed. + stack.Head = queue; - this.ownerThread = new WeakReference(thread); - this.head = this.tail = new Link(); - lock (stack) + return queue; + } + + internal WeakOrderQueue Next + { + set { - this.next = stack.HeadQueue; - stack.HeadQueue = this; + Debug.Assert(value != this); + this.next = value; } } - internal void Add(Handle handle) + /// + /// Allocate a new or return null if not possible. + /// + internal static WeakOrderQueue Allocate(Stack stack, Thread thread, DelayedThreadLocal.CountedWeakTable countedWeakTable) { - Contract.Requires(handle != null); + // We allocated a Link so reserve the space + return Head.ReserveSpace(stack.availableSharedCapacity, LinkCapacity) ? NewQueue(stack, thread, countedWeakTable) : null; + } + internal void Add(DefaultHandle handle) + { handle.lastRecycledId = this.id; Link tail = this.tail; int writeIndex = tail.WriteIndex; if (writeIndex == LinkCapacity) { + if (!head.ReserveSpace(LinkCapacity)) + { + // Drop it. + return; + } + // We allocate a Link so reserve the space this.tail = tail = tail.next = new Link(); writeIndex = tail.WriteIndex; } tail.elements[writeIndex] = handle; handle.Stack = null; - tail.WriteIndex = writeIndex + 1; + // we lazy set to ensure that setting stack to null appears before we unnull it in the owning thread; + // this also means we guarantee visibility of an element in the queue if we see the index updated + tail.LazySetWriteIndex(writeIndex + 1); } + internal bool HasFinalData => this.tail.ReadIndex != this.tail.WriteIndex; + + // transfer as many items as we can from this queue to the stack, returning true if any were transferred internal bool Transfer(Stack dst) { - // This method must be called by owner thread. - Contract.Requires(dst != null); - - Link head = this.head; + Link head = this.head.link; if (head == null) { return false; @@ -129,7 +249,7 @@ internal bool Transfer(Stack dst) { return false; } - this.head = head = head.next; + this.head.link = head = head.next; } int srcStart = head.ReadIndex; @@ -151,12 +271,12 @@ internal bool Transfer(Stack dst) if (srcStart != srcEnd) { - Handle[] srcElems = head.elements; - Handle[] dstElems = dst.elements; + DefaultHandle[] srcElems = head.elements; + DefaultHandle[] dstElems = dst.elements; int newDstSize = dstSize; for (int i = srcStart; i < srcEnd; i++) { - Handle element = srcElems[i]; + DefaultHandle element = srcElems[i]; if (element.recycleId == 0) { element.recycleId = element.lastRecycledId; @@ -165,18 +285,30 @@ internal bool Transfer(Stack dst) { throw new InvalidOperationException("recycled already"); } + srcElems[i] = null; + + if (dst.DropHandle(element)) + { + // Drop the object. + continue; + } element.Stack = dst; dstElems[newDstSize++] = element; - srcElems[i] = null; } - dst.size = newDstSize; if (srcEnd == LinkCapacity && head.next != null) { - this.head = head.next; + // Add capacity back as the Link is GCed. + this.head.ReclaimSpace(LinkCapacity); + this.head.link = head.next; } head.ReadIndex = srcEnd; + if (dst.size == newDstSize) + { + return false; + } + dst.size = newDstSize; return true; } else @@ -187,35 +319,54 @@ internal bool Transfer(Stack dst) } } - internal sealed class Stack + protected sealed class Stack { - internal readonly ThreadLocalPool Parent; - internal readonly Thread Thread; - - internal Handle[] elements; + // we keep a queue of per-thread queues, which is appended to once only, each time a new thread other + // than the stack owner recycles: when we run out of items in our stack we iterate this collection + // to scavenge those that can be reused. this permits us to incur minimal thread synchronisation whilst + // still recycling all items. + internal readonly ThreadLocalPool parent; + + // We store the Thread in a WeakReference as otherwise we may be the only ones that still hold a strong + // Reference to the Thread itself after it died because DefaultHandle will hold a reference to the Stack. + // + // The biggest issue is if we do not use a WeakReference the Thread may not be able to be collected at all if + // the user will store a reference to the DefaultHandle somewhere and never clear this reference (or not clear + // it in a timely manner). + internal readonly WeakReference threadRef; + internal readonly StrongBox availableSharedCapacity; + internal readonly int maxDelayedQueues; readonly int maxCapacity; + readonly int ratioMask; + internal DefaultHandle[] elements; internal int size; + int handleRecycleCount = -1; // Start with -1 so the first one will be recycled. + WeakOrderQueue cursorQueue, prevQueue; + volatile WeakOrderQueue headQueue; - WeakOrderQueue headQueue; - WeakOrderQueue cursorQueue; - WeakOrderQueue prevQueue; - - internal WeakOrderQueue HeadQueue + internal Stack(ThreadLocalPool parent, Thread thread, int maxCapacity, int maxSharedCapacityFactor, + int ratioMask, int maxDelayedQueues) { - get { return Volatile.Read(ref this.headQueue); } - set { Volatile.Write(ref this.headQueue, value); } + this.parent = parent; + this.threadRef = new WeakReference(thread); + this.maxCapacity = maxCapacity; + this.availableSharedCapacity = new StrongBox(Math.Max(maxCapacity / maxSharedCapacityFactor, LinkCapacity)); + this.elements = new DefaultHandle[Math.Min(DefaultInitialCapacity, maxCapacity)]; + this.ratioMask = ratioMask; + this.maxDelayedQueues = maxDelayedQueues; } - internal int Size => this.size; - - internal Stack(int maxCapacity, ThreadLocalPool parent, Thread thread) + internal WeakOrderQueue Head { - this.maxCapacity = maxCapacity; - this.Parent = parent; - this.Thread = thread; - - this.elements = new Handle[Math.Min(InitialCapacity, maxCapacity)]; + set + { + lock (this) + { + value.next = headQueue; + headQueue = value; + } + } } internal int IncreaseCapacity(int expectedCapacity) @@ -237,9 +388,25 @@ internal int IncreaseCapacity(int expectedCapacity) return newCapacity; } - internal void Push(Handle item) + internal void Push(DefaultHandle item) + { + Thread currentThread = Thread.CurrentThread; + if (threadRef.TryGetTarget(out Thread thread) && thread == currentThread) + { + // The current Thread is the thread that belongs to the Stack, we can try to push the object now. + PushNow(item); + } + else + { + // The current Thread is not the one that belongs to the Stack + // (or the Thread that belonged to the Stack was collected already), we need to signal that the push + // happens later. + PushLater(item, currentThread); + } + } + + void PushNow(DefaultHandle item) { - Contract.Requires(item != null); if ((item.recycleId | item.lastRecycledId) != 0) { throw new InvalidOperationException("released already"); @@ -247,7 +414,7 @@ internal void Push(Handle item) item.recycleId = item.lastRecycledId = ownThreadId; int size = this.size; - if (size >= this.maxCapacity) + if (size >= this.maxCapacity || DropHandle(item)) { // Hit the maximum capacity - drop the possibly youngest object. return; @@ -261,7 +428,56 @@ internal void Push(Handle item) this.size = size + 1; } - internal bool TryPop(out Handle item) + void PushLater(DefaultHandle item, Thread thread) + { + // we don't want to have a ref to the queue as the value in our weak map + // so we null it out; to ensure there are no races with restoring it later + // we impose a memory ordering here (no-op on x86) + DelayedThreadLocal.CountedWeakTable countedWeakTable = DelayedPool.Value; + ConditionalWeakTable delayedRecycled = countedWeakTable.WeakTable; + delayedRecycled.TryGetValue(this, out WeakOrderQueue queue); + if (queue == null) + { + if (Volatile.Read(ref countedWeakTable.Counter.Value) >= maxDelayedQueues) + { + // Add a dummy queue so we know we should drop the object + delayedRecycled.Add(this, WeakOrderQueue.Dummy); + return; + } + // Check if we already reached the maximum number of delayed queues and if we can allocate at all. + if ((queue = WeakOrderQueue.Allocate(this, thread, countedWeakTable)) == null) + { + // drop object + return; + } + delayedRecycled.Add(this, queue); + } + else if (queue == WeakOrderQueue.Dummy) + { + // drop object + return; + } + + queue.Add(item); + } + + internal bool DropHandle(DefaultHandle handle) + { + if (!handle.hasBeenRecycled) + { + if ((++handleRecycleCount & ratioMask) != 0) + { + // Drop the object. + return true; + } + handle.hasBeenRecycled = true; + } + return false; + } + + internal DefaultHandle NewHandle() => new DefaultHandle(this); + + internal bool TryPop(out DefaultHandle item) { int size = this.size; if (size == 0) @@ -274,16 +490,17 @@ internal bool TryPop(out Handle item) size = this.size; } size--; - Handle ret = this.elements[size]; + DefaultHandle ret = this.elements[size]; + elements[size] = null; if (ret.lastRecycledId != ret.recycleId) { throw new InvalidOperationException("recycled multiple times"); } ret.recycleId = 0; ret.lastRecycledId = 0; - item = ret; this.size = size; + item = ret; return true; } @@ -297,24 +514,29 @@ bool Scavenge() // reset our scavenge cursor this.prevQueue = null; - this.cursorQueue = this.HeadQueue; + this.cursorQueue = this.headQueue; return false; } bool ScavengeSome() { + WeakOrderQueue prev; WeakOrderQueue cursor = this.cursorQueue; if (cursor == null) { - cursor = this.HeadQueue; + prev = null; + cursor = this.headQueue; if (cursor == null) { return false; } } + else + { + prev = this.prevQueue; + } bool success = false; - WeakOrderQueue prev = this.prevQueue; do { if (cursor.Transfer(this)) @@ -324,13 +546,12 @@ bool ScavengeSome() } WeakOrderQueue next = cursor.next; - Thread ownerThread; - if (!cursor.ownerThread.TryGetTarget(out ownerThread)) + if (!cursor.owner.TryGetTarget(out _)) { // If the thread associated with the queue is gone, unlink it, after // performing a volatile read to confirm there is no data left to collect. // We never unlink the first queue, as we don't want to synchronize on updating the head. - if (!cursor.IsEmpty) + if (cursor.HasFinalData) { for (;;) { @@ -346,7 +567,7 @@ bool ScavengeSome() } if (prev != null) { - prev.next = next; + prev.Next = next; } } else @@ -364,46 +585,143 @@ bool ScavengeSome() } } - internal static readonly int DefaultMaxCapacity = 262144; - internal static readonly int InitialCapacity = Math.Min(256, DefaultMaxCapacity); + const int DefaultInitialMaxCapacityPerThread = 4 * 1024; // Use 4k instances as default. + protected static readonly int DefaultMaxCapacityPerThread; + protected static readonly int DefaultInitialCapacity; + protected static readonly int DefaultMaxSharedCapacityFactor; + protected static readonly int DefaultMaxDelayedQueuesPerThread; + protected static readonly int LinkCapacity; + protected static readonly int DefaultRatio; static int idSource = int.MinValue; static readonly int ownThreadId = Interlocked.Increment(ref idSource); - internal static readonly DelayedThreadLocal DelayedPool = new DelayedThreadLocal(); + protected static readonly DelayedThreadLocal DelayedPool = new DelayedThreadLocal(); - internal sealed class DelayedThreadLocal : FastThreadLocal> + protected sealed class DelayedThreadLocal : FastThreadLocal { - protected override ConditionalWeakTable GetInitialValue() => new ConditionalWeakTable(); + public class CountedWeakTable + { + internal readonly ConditionalWeakTable WeakTable = new ConditionalWeakTable(); + + internal readonly StrongBox Counter = new StrongBox(); + } + protected override CountedWeakTable GetInitialValue() => new CountedWeakTable(); } - public ThreadLocalPool(int maxCapacity) + static ThreadLocalPool() { - Contract.Requires(maxCapacity > 0); - this.MaxCapacity = maxCapacity; + // In the future, we might have different maxCapacity for different object types. + // e.g. io.netty.recycler.maxCapacity.writeTask + // io.netty.recycler.maxCapacity.outboundBuffer + int maxCapacityPerThread = SystemPropertyUtil.GetInt("io.netty.recycler.maxCapacityPerThread", + SystemPropertyUtil.GetInt("io.netty.recycler.maxCapacity", DefaultInitialMaxCapacityPerThread)); + if (maxCapacityPerThread < 0) + { + maxCapacityPerThread = DefaultInitialMaxCapacityPerThread; + } + + DefaultMaxCapacityPerThread = maxCapacityPerThread; + + DefaultMaxSharedCapacityFactor = Math.Max(2, + SystemPropertyUtil.GetInt("io.netty.recycler.maxSharedCapacityFactor", + 2)); + + DefaultMaxDelayedQueuesPerThread = Math.Max(0, + SystemPropertyUtil.GetInt("io.netty.recycler.maxDelayedQueuesPerThread", + // We use the same value as default EventLoop number + Environment.ProcessorCount * 2)); + + LinkCapacity = MathUtil.SafeFindNextPositivePowerOfTwo( + Math.Max(SystemPropertyUtil.GetInt("io.netty.recycler.linkCapacity", 16), 16)); + + // By default we allow one push to a Recycler for each 8th try on handles that were never recycled before. + // This should help to slowly increase the capacity of the recycler while not be too sensitive to allocation + // bursts. + DefaultRatio = MathUtil.SafeFindNextPositivePowerOfTwo(SystemPropertyUtil.GetInt("io.netty.recycler.ratio", 8)); + + IInternalLogger logger = InternalLoggerFactory.GetInstance(typeof(ThreadLocalPool)); + if (logger.DebugEnabled) + { + if (DefaultMaxCapacityPerThread == 0) + { + logger.Debug("-Dio.netty.recycler.maxCapacityPerThread: disabled"); + logger.Debug("-Dio.netty.recycler.maxSharedCapacityFactor: disabled"); + logger.Debug("-Dio.netty.recycler.maxDelayedQueuesPerThread: disabled"); + logger.Debug("-Dio.netty.recycler.linkCapacity: disabled"); + logger.Debug("-Dio.netty.recycler.ratio: disabled"); + } + else + { + logger.Debug("-Dio.netty.recycler.maxCapacityPerThread: {}", DefaultMaxCapacityPerThread); + logger.Debug("-Dio.netty.recycler.maxSharedCapacityFactor: {}", DefaultMaxSharedCapacityFactor); + logger.Debug("-Dio.netty.recycler.maxDelayedQueuesPerThread: {}", DefaultMaxDelayedQueuesPerThread); + logger.Debug("-Dio.netty.recycler.linkCapacity: {}", LinkCapacity); + logger.Debug("-Dio.netty.recycler.ratio: {}", DefaultRatio); + } + } + + DefaultInitialCapacity = Math.Min(DefaultMaxCapacityPerThread, 256); + } + + public ThreadLocalPool(int maxCapacityPerThread) + : this (maxCapacityPerThread, DefaultMaxSharedCapacityFactor, DefaultRatio, DefaultMaxDelayedQueuesPerThread) + { + } + + public ThreadLocalPool(int maxCapacityPerThread, int maxSharedCapacityFactor, + int ratio, int maxDelayedQueuesPerThread) + { + this.ratioMask = MathUtil.SafeFindNextPositivePowerOfTwo(ratio) - 1; + if (maxCapacityPerThread <= 0) + { + this.maxCapacityPerThread = 0; + this.maxSharedCapacityFactor = 1; + this.maxDelayedQueuesPerThread = 0; + } + else + { + this.maxCapacityPerThread = maxCapacityPerThread; + this.maxSharedCapacityFactor = Math.Max(1, maxSharedCapacityFactor); + this.maxDelayedQueuesPerThread = Math.Max(0, maxDelayedQueuesPerThread); + } } - public int MaxCapacity { get; } + protected readonly int maxCapacityPerThread; + protected readonly int ratioMask; + protected readonly int maxSharedCapacityFactor; + protected readonly int maxDelayedQueuesPerThread; } public sealed class ThreadLocalPool : ThreadLocalPool where T : class { readonly ThreadLocalStack threadLocal; - readonly Func valueFactory; readonly bool preCreate; + readonly Func valueFactory; public ThreadLocalPool(Func valueFactory) - : this(valueFactory, DefaultMaxCapacity) + : this(valueFactory, DefaultMaxCapacityPerThread) + { + } + + public ThreadLocalPool(Func valueFactory, int maxCapacityPerThread) + : this(valueFactory, maxCapacityPerThread, DefaultMaxCapacityPerThread, DefaultRatio, DefaultMaxCapacityPerThread, false) + { + } + + public ThreadLocalPool(Func valueFactory, int maxCapacityPerThread, bool preCreate) + : this(valueFactory, maxCapacityPerThread, DefaultMaxCapacityPerThread, DefaultRatio, DefaultMaxCapacityPerThread, false) { } - public ThreadLocalPool(Func valueFactory, int maxCapacity) - : this(valueFactory, maxCapacity, false) + public ThreadLocalPool(Func valueFactory, int maxCapacityPerThread, int maxSharedCapacityFactor) + : this(valueFactory, maxCapacityPerThread, maxSharedCapacityFactor, DefaultRatio, DefaultMaxCapacityPerThread, false) { } - public ThreadLocalPool(Func valueFactory, int maxCapacity, bool preCreate) - : base(maxCapacity) + public ThreadLocalPool(Func valueFactory, int maxCapacityPerThread, int maxSharedCapacityFactor, + int ratio, int maxDelayedQueuesPerThread, bool preCreate = false) + : base(maxCapacityPerThread, maxSharedCapacityFactor, ratio, maxDelayedQueuesPerThread) { Contract.Requires(valueFactory != null); @@ -415,26 +733,30 @@ public ThreadLocalPool(Func valueFactory, int maxCapacity, bool preCr public T Take() { + if (maxCapacityPerThread == 0) + { + return this.valueFactory(NoopHandle.Instance); + } + Stack stack = this.threadLocal.Value; - Handle handle; + DefaultHandle handle; if (!stack.TryPop(out handle)) { - handle = this.CreateValue(stack); + handle = CreateValue(stack); } return (T)handle.Value; } - Handle CreateValue(Stack stack) + DefaultHandle CreateValue(Stack stack) { - var handle = new Handle(stack); - T value = this.valueFactory(handle); - handle.Value = value; + var handle = stack.NewHandle(); + handle.Value = this.valueFactory(handle); return handle; } internal int ThreadLocalCapacity => this.threadLocal.Value.elements.Length; - internal int ThreadLocalSize => this.threadLocal.Value.Size; + internal int ThreadLocalSize => this.threadLocal.Value.size; sealed class ThreadLocalStack : FastThreadLocal { @@ -447,16 +769,29 @@ public ThreadLocalStack(ThreadLocalPool owner) protected override Stack GetInitialValue() { - var stack = new Stack(this.owner.MaxCapacity, this.owner, Thread.CurrentThread); + var stack = new Stack(this.owner, Thread.CurrentThread, this.owner.maxCapacityPerThread, + this.owner.maxSharedCapacityFactor, this.owner.ratioMask, this.owner.maxDelayedQueuesPerThread); if (this.owner.preCreate) { - for (int i = 0; i < this.owner.MaxCapacity; i++) + for (int i = 0; i < this.owner.maxCapacityPerThread; i++) { stack.Push(this.owner.CreateValue(stack)); } } return stack; } + + protected override void OnRemoval(Stack value) + { + // Let us remove the WeakOrderQueue from the WeakHashMap directly if its safe to remove some overhead + if (value.threadRef.TryGetTarget(out Thread valueThread) && valueThread == Thread.CurrentThread) + { + if (DelayedPool.IsSet()) + { + DelayedPool.Value.WeakTable.Remove(value); + } + } + } } } } \ No newline at end of file diff --git a/test/DotNetty.Common.Tests/ThreadLocalPoolTest.cs b/test/DotNetty.Common.Tests/ThreadLocalPoolTest.cs index 1ce989dd1..ace0d40bb 100644 --- a/test/DotNetty.Common.Tests/ThreadLocalPoolTest.cs +++ b/test/DotNetty.Common.Tests/ThreadLocalPoolTest.cs @@ -3,60 +3,128 @@ namespace DotNetty.Common.Tests { + using DotNetty.Common.Concurrency; using System; + using System.Runtime.ExceptionServices; + using System.Threading; using System.Threading.Tasks; using Xunit; public class ThreadLocalPoolTest { + private static ThreadLocalPool NewPool(int max) + => new ThreadLocalPool(handle => new HandledObject(handle), max); + + //Not use Task to do all `AtDifferentThreadTest`, because can't promise Task won't be run inline. + + [Fact] + public void ThreadCanBeCollectedEvenIfHandledObjectIsReferencedTest() + { + ThreadLocalPool pool = NewPool(1024); + HandledObject reference = null; + WeakReference threadRef = null; + WeakReference xThreadRef = null; + + var thread1 = new Thread(() => + { + //Don't know the reason, but thread2 will not be collected without wrapped with thread1 + var thread2 = new Thread(() => + { + Volatile.Write(ref xThreadRef, new WeakReference(XThread.CurrentThread)); + HandledObject data = pool.Take(); + // Store a reference to the HandledObject to ensure it is not collected when the run method finish. + Volatile.Write(ref reference, data); + }); + Volatile.Write(ref threadRef, new WeakReference(thread2)); + thread2.Start(); + thread2.Join(); + Assert.True(Volatile.Read(ref threadRef)?.TryGetTarget(out _)); + Assert.True(Volatile.Read(ref xThreadRef)?.TryGetTarget(out _)); + + GC.KeepAlive(thread2); + // Null out so it can be collected. + thread2 = null; + }); + thread1.Start(); + thread1.Join(); + + for (int i = 0; i < 5; ++i) + { + GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true); + GC.WaitForPendingFinalizers(); + + if (Volatile.Read(ref threadRef)?.TryGetTarget(out _) == true || Volatile.Read(ref xThreadRef)?.TryGetTarget(out _) == true) + Thread.Sleep(100); + } + + Assert.False(Volatile.Read(ref threadRef)?.TryGetTarget(out _)); + Assert.False(Volatile.Read(ref xThreadRef)?.TryGetTarget(out _)); + + // Now call recycle after the Thread was collected to ensure this still works... + reference.Release(); + reference = null; + } + [Fact] public void MultipleReleaseTest() { - RecyclableObject obj = RecyclableObject.NewInstance(); + ThreadLocalPool pool = NewPool(1024); + HandledObject obj = pool.Take(); obj.Release(); var exception = Assert.ThrowsAny(() => obj.Release()); Assert.True(exception != null); } + [Fact] + public void MultipleReleaseAtDifferentThreadTest() + { + ThreadLocalPool pool = NewPool(1024); + HandledObject obj = pool.Take(); + + Thread thread = new Thread(() => + { + obj.Release(); + }); + thread.Start(); + thread.Join(); + + ExceptionDispatchInfo exceptionDispatchInfo = null; + Thread thread2 = new Thread(() => + { + try + { + obj.Release(); + } + catch (Exception ex) + { + Volatile.Write(ref exceptionDispatchInfo, ExceptionDispatchInfo.Capture(ex)); + } + }); + thread2.Start(); + thread2.Join(); + var exception = Assert.ThrowsAny(() => Volatile.Read(ref exceptionDispatchInfo)?.Throw()); + Assert.True(exception != null); + } [Fact] public void ReleaseTest() { - RecyclableObject obj = RecyclableObject.NewInstance(); + ThreadLocalPool pool = NewPool(1024); + HandledObject obj = pool.Take(); obj.Release(); - RecyclableObject obj2 = RecyclableObject.NewInstance(); + HandledObject obj2 = pool.Take(); Assert.Same(obj, obj2); obj2.Release(); } [Fact] - public void RecycleAtDifferentThreadTest() + public void ReleaseDisableTest() { - RecyclableObject obj = RecyclableObject.NewInstance(); - - RecyclableObject prevObject = obj; - Task.Run(() => { obj.Release(); }).Wait(); - obj = RecyclableObject.NewInstance(); - - Assert.True(obj == prevObject); + ThreadLocalPool pool = NewPool(-1); + HandledObject obj = pool.Take(); obj.Release(); - } - - class RecyclableObject - { - internal static readonly ThreadLocalPool pool = - new ThreadLocalPool(handle => - new RecyclableObject(handle), 1, true); - - readonly ThreadLocalPool.Handle handle; - - public RecyclableObject(ThreadLocalPool.Handle handle) - { - this.handle = handle; - } - - public static RecyclableObject NewInstance() => pool.Take(); - - public void Release() => handle.Release(this); + HandledObject obj2 = pool.Take(); + Assert.NotSame(obj, obj2); + obj2.Release(); } class HandledObject @@ -74,17 +142,17 @@ internal HandledObject(ThreadLocalPool.Handle handle) [Fact] public void MaxCapacityTest() { - this.MaxCapacityTest0(300); + MaxCapacityTest0(300); var rand = new Random(); for (int i = 0; i < 50; i++) { - this.MaxCapacityTest0(rand.Next(1000) + 256); // 256 - 1256 + MaxCapacityTest0(rand.Next(1000) + 256); // 256 - 1256 } } - void MaxCapacityTest0(int maxCapacity) + static void MaxCapacityTest0(int maxCapacity) { - var recycler = new ThreadLocalPool(handle => new HandledObject(handle), maxCapacity); + var recycler = NewPool(maxCapacity); var objects = new HandledObject[maxCapacity * 3]; for (int i = 0; i < objects.Length; i++) @@ -97,14 +165,36 @@ void MaxCapacityTest0(int maxCapacity) objects[i].Release(); objects[i] = null; } - Assert.Equal(maxCapacity, recycler.ThreadLocalCapacity); + Assert.True(maxCapacity >= recycler.ThreadLocalCapacity, + "The threadLocalCapacity (" + recycler.ThreadLocalCapacity + ") must be <= maxCapacity (" + + maxCapacity + ") as we not pool all new handles internally"); + } + + [Fact] + public void ReleaseAtDifferentThreadTest() + { + ThreadLocalPool pool = new ThreadLocalPool(handle => new HandledObject(handle), + 256, 10, 2, 10); + + HandledObject obj = pool.Take(); + HandledObject obj2 = pool.Take(); + Thread thread = new Thread(() => + { + obj.Release(); + obj2.Release(); + }); + thread.Start(); + thread.Join(); + + Assert.Same(pool.Take(), obj); + Assert.NotSame(pool.Take(), obj2); } [Fact] - public void MaxCapacityWithRecycleAtDifferentThreadTest() + public void MaxCapacityWithReleaseAtDifferentThreadTest() { const int maxCapacity = 4; // Choose the number smaller than WeakOrderQueue.LINK_CAPACITY - var recycler = new ThreadLocalPool(handle => new HandledObject(handle), maxCapacity); + var pool = NewPool(maxCapacity); // Borrow 2 * maxCapacity objects. // Return the half from the same thread. @@ -113,7 +203,7 @@ public void MaxCapacityWithRecycleAtDifferentThreadTest() var array = new HandledObject[maxCapacity * 3]; for (int i = 0; i < array.Length; i++) { - array[i] = recycler.Take(); + array[i] = pool.Take(); } for (int i = 0; i < maxCapacity; i++) @@ -121,24 +211,76 @@ public void MaxCapacityWithRecycleAtDifferentThreadTest() array[i].Release(); } - Task.Run(() => + Thread thread = new Thread(() => { for (int i = maxCapacity; i < array.Length; i++) { array[i].Release(); } - }).Wait(); + }); + thread.Start(); + thread.Join(); + + Assert.Equal(maxCapacity, pool.ThreadLocalCapacity); + Assert.Equal(1, pool.ThreadLocalSize); + + for (int i = 0; i < array.Length; i++) + { + pool.Take(); + } + + Assert.Equal(maxCapacity, pool.ThreadLocalCapacity); + Assert.Equal(0, pool.ThreadLocalSize); + } + + [Fact] + public void DiscardingExceedingElementsWithReleaseAtDifferentThreadTest() + { + int maxCapacity = 32; + int instancesCount = 0; + + ThreadLocalPool pool = new ThreadLocalPool(handle => + { + Interlocked.Increment(ref instancesCount); + return new HandledObject(handle); + }, maxCapacity, 2); + + // Borrow 2 * maxCapacity objects. + HandledObject[] array = new HandledObject[maxCapacity * 2]; + for (int i = 0; i < array.Length; i++) + { + array[i] = pool.Take(); + } + + Assert.Equal(array.Length, Volatile.Read(ref instancesCount)); + // Reset counter. + Volatile.Write(ref instancesCount, 0); + + // Release from other thread. + Thread thread = new Thread(() => + { + for (int i = 0; i < array.Length; i++) + { + array[i].Release(); + } + }); + thread.Start(); + thread.Join(); - Assert.Equal(recycler.ThreadLocalCapacity, maxCapacity); - Assert.Equal(recycler.ThreadLocalSize, maxCapacity); + Assert.Equal(0, Volatile.Read(ref instancesCount)); + // Borrow 2 * maxCapacity objects. Half of them should come from + // the recycler queue, the other half should be freshly allocated. for (int i = 0; i < array.Length; i++) { - recycler.Take(); + array[i] = pool.Take(); } - Assert.Equal(maxCapacity, recycler.ThreadLocalCapacity); - Assert.Equal(0, recycler.ThreadLocalSize); + // The implementation uses maxCapacity / 2 as limit per WeakOrderQueue + Assert.True(array.Length - maxCapacity / 2 <= Volatile.Read(ref instancesCount), + "The instances count (" + Volatile.Read(ref instancesCount) + ") must be <= array.length (" + array.Length + + ") - maxCapacity (" + maxCapacity + ") / 2 as we not pool all new handles" + + " internally"); } } } \ No newline at end of file From c011350ddeb5814c72c524827601add52a842d77 Mon Sep 17 00:00:00 2001 From: SilverFox Date: Tue, 22 Oct 2019 04:06:54 +0800 Subject: [PATCH 10/33] Fix #498 (#507) --- src/DotNetty.Common/Utilities/AttributeKey.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/DotNetty.Common/Utilities/AttributeKey.cs b/src/DotNetty.Common/Utilities/AttributeKey.cs index 202f07935..4e06cf7a2 100644 --- a/src/DotNetty.Common/Utilities/AttributeKey.cs +++ b/src/DotNetty.Common/Utilities/AttributeKey.cs @@ -5,6 +5,18 @@ namespace DotNetty.Common.Utilities { using System; + internal static class AttributeKey + { + // Keep the instance of AttributeConstantPool out of generic classes, to make it an really singleton for different generic types. + // see https://github.com/Azure/DotNetty/issues/498 + public static readonly ConstantPool Pool = new AttributeConstantPool(); + + sealed class AttributeConstantPool : ConstantPool + { + protected override IConstant NewConstant(int id, string name) => new AttributeKey(id, name); + }; + } + /// /// Key which can be used to access out of the . Be aware that /// it is not be possible to have multiple keys with the same name. @@ -14,12 +26,7 @@ namespace DotNetty.Common.Utilities /// public sealed class AttributeKey : AbstractConstant> { - public static readonly ConstantPool Pool = new AttributeConstantPool(); - - sealed class AttributeConstantPool : ConstantPool - { - protected override IConstant NewConstant(int id, string name) => new AttributeKey(id, name); - }; + public static readonly ConstantPool Pool = AttributeKey.Pool; /// Returns the singleton instance of the {@link AttributeKey} which has the specified name. public static AttributeKey ValueOf(string name) => (AttributeKey)Pool.ValueOf(name); From d4bb7ae10e885311c78bf575e0dbdece2913c3ea Mon Sep 17 00:00:00 2001 From: SilverFox Date: Tue, 22 Oct 2019 04:36:05 +0800 Subject: [PATCH 11/33] Fix issue #472 (#473) * Align and add some missing overloads for ByteBuffer * Add the workaround for case 1 in #436 * Remove Deque.cs from DotNetty.Common * Fix false positive resource leak report. * Change some behavior of ResourceLeakDetector --- src/DotNetty.Buffers/AbstractByteBuffer.cs | 16 +- .../AdvancedLeakAwareByteBuffer.cs | 24 + .../AdvancedLeakAwareCompositeByteBuffer.cs | 175 ++++ .../SimpleLeakAwareCompositeByteBuffer.cs | 8 + .../UnpooledUnsafeDirectByteBuffer.cs | 2 + .../WrappedCompositeByteBuffer.cs | 28 +- src/DotNetty.Common/Deque.cs | 893 ------------------ src/DotNetty.Common/ResourceLeakDetector.cs | 142 ++- 8 files changed, 349 insertions(+), 939 deletions(-) delete mode 100644 src/DotNetty.Common/Deque.cs diff --git a/src/DotNetty.Buffers/AbstractByteBuffer.cs b/src/DotNetty.Buffers/AbstractByteBuffer.cs index 96e85bde0..8c9e42f1d 100644 --- a/src/DotNetty.Buffers/AbstractByteBuffer.cs +++ b/src/DotNetty.Buffers/AbstractByteBuffer.cs @@ -560,16 +560,20 @@ public virtual IByteBuffer SetShortLE(int index, int value) protected internal abstract void _SetShortLE(int index, int value); - public virtual IByteBuffer SetUnsignedShort(int index, ushort value) + public IByteBuffer SetUnsignedShort(int index, ushort value) { - this.SetShort(index, value); - return this; + unchecked + { + return this.SetShort(index, (short)value); + } } - public virtual IByteBuffer SetUnsignedShortLE(int index, ushort value) + public IByteBuffer SetUnsignedShortLE(int index, ushort value) { - this.SetShortLE(index, value); - return this; + unchecked + { + return this.SetShortLE(index, (short)value); + } } public virtual IByteBuffer SetChar(int index, char value) diff --git a/src/DotNetty.Buffers/AdvancedLeakAwareByteBuffer.cs b/src/DotNetty.Buffers/AdvancedLeakAwareByteBuffer.cs index 4bae93d78..cbf9d5c56 100644 --- a/src/DotNetty.Buffers/AdvancedLeakAwareByteBuffer.cs +++ b/src/DotNetty.Buffers/AdvancedLeakAwareByteBuffer.cs @@ -771,6 +771,30 @@ public override IReferenceCounted Retain(int increment) return base.Retain(increment); } + public override IByteBuffer RetainedSlice() + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.RetainedSlice(); + } + + public override IByteBuffer RetainedSlice(int index, int length) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.RetainedSlice(index, length); + } + + public override IByteBuffer RetainedDuplicate() + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.RetainedDuplicate(); + } + + public override IByteBuffer ReadRetainedSlice(int length) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.ReadRetainedSlice(length); + } + public override IReferenceCounted Touch() { this.Leak.Record(); diff --git a/src/DotNetty.Buffers/AdvancedLeakAwareCompositeByteBuffer.cs b/src/DotNetty.Buffers/AdvancedLeakAwareCompositeByteBuffer.cs index ec8354877..cbd582ce1 100644 --- a/src/DotNetty.Buffers/AdvancedLeakAwareCompositeByteBuffer.cs +++ b/src/DotNetty.Buffers/AdvancedLeakAwareCompositeByteBuffer.cs @@ -4,6 +4,7 @@ namespace DotNetty.Buffers { using System; + using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; @@ -593,6 +594,156 @@ public override IByteBuffer GetBytes(int index, Stream destination, int length) return base.GetBytes(index, destination, length); } + public override CompositeByteBuffer AddComponent(bool increaseWriterIndex, IByteBuffer buffer) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.AddComponent(increaseWriterIndex, buffer); + } + + public override CompositeByteBuffer AddComponent(bool increaseWriterIndex, int cIndex, IByteBuffer buffer) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.AddComponent(increaseWriterIndex, cIndex, buffer); + } + + public override CompositeByteBuffer AddComponent(IByteBuffer buffer) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.AddComponent(buffer); + } + + public override CompositeByteBuffer AddComponent(int cIndex, IByteBuffer buffer) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.AddComponent(cIndex, buffer); + } + + public override CompositeByteBuffer AddComponents(bool increaseWriterIndex, params IByteBuffer[] buffers) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.AddComponents(increaseWriterIndex, buffers); + } + + public override CompositeByteBuffer AddComponents(bool increaseWriterIndex, IEnumerable buffers) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.AddComponents(increaseWriterIndex, buffers); + } + + public override CompositeByteBuffer AddComponents(IEnumerable buffers) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.AddComponents(buffers); + } + + public override CompositeByteBuffer AddComponents(int cIndex, IEnumerable buffers) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.AddComponents(cIndex, buffers); + } + + public override CompositeByteBuffer AddComponents(int cIndex, params IByteBuffer[] buffers) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.AddComponents(cIndex, buffers); + } + + public override CompositeByteBuffer AddComponents(params IByteBuffer[] buffers) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.AddComponents(buffers); + } + + public override CompositeByteBuffer RemoveComponent(int cIndex) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.RemoveComponent(cIndex); + } + + public override CompositeByteBuffer RemoveComponents(int cIndex, int numComponents) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.RemoveComponents(cIndex, numComponents); + } + + public override CompositeByteBuffer Consolidate() + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.Consolidate(); + } + + public override CompositeByteBuffer Consolidate(int cIndex, int numComponents) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.Consolidate(cIndex, numComponents); + } + + public override CompositeByteBuffer DiscardReadComponents() + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.DiscardReadComponents(); + } + + public override IList Decompose(int offset, int length) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.Decompose(offset, length); + } + + public override ICharSequence GetCharSequence(int index, int length, Encoding encoding) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.GetCharSequence(index, length, encoding); + } + + public override ICharSequence ReadCharSequence(int length, Encoding encoding) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.ReadCharSequence(length, encoding); + } + + public override int SetCharSequence(int index, ICharSequence sequence, Encoding encoding) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.SetCharSequence(index, sequence, encoding); + } + + public override int WriteCharSequence(ICharSequence sequence, Encoding encoding) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.WriteCharSequence(sequence, encoding); + } + + public override string GetString(int index, int length, Encoding encoding) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.GetString(index, length, encoding); + } + + public override string ReadString(int length, Encoding encoding) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.ReadString(length, encoding); + } + + public override int SetString(int index, string value, Encoding encoding) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.SetString(index, value, encoding); + } + + public override int WriteString(string value, Encoding encoding) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.WriteString(value, encoding); + } + + public override IEnumerator GetEnumerator() + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.GetEnumerator(); + } + public override IReferenceCounted Retain() { this.Leak.Record(); @@ -605,6 +756,30 @@ public override IReferenceCounted Retain(int increment) return base.Retain(increment); } + public override IByteBuffer RetainedSlice() + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.RetainedSlice(); + } + + public override IByteBuffer RetainedSlice(int index, int length) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.RetainedSlice(index, length); + } + + public override IByteBuffer RetainedDuplicate() + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.RetainedDuplicate(); + } + + public override IByteBuffer ReadRetainedSlice(int length) + { + RecordLeakNonRefCountingOperation(this.Leak); + return base.ReadRetainedSlice(length); + } + public override bool Release() { this.Leak.Record(); diff --git a/src/DotNetty.Buffers/SimpleLeakAwareCompositeByteBuffer.cs b/src/DotNetty.Buffers/SimpleLeakAwareCompositeByteBuffer.cs index 97f3c95f2..21f3c3a9e 100644 --- a/src/DotNetty.Buffers/SimpleLeakAwareCompositeByteBuffer.cs +++ b/src/DotNetty.Buffers/SimpleLeakAwareCompositeByteBuffer.cs @@ -61,6 +61,14 @@ void CloseLeak(IByteBuffer trackedByteBuf) public override IByteBuffer ReadSlice(int length) => this.NewLeakAwareByteBuffer(base.ReadSlice(length)); + public override IByteBuffer RetainedSlice() => this.NewLeakAwareByteBuffer(base.RetainedSlice()); + + public override IByteBuffer RetainedSlice(int index, int length) => this.NewLeakAwareByteBuffer(base.RetainedSlice(index, length)); + + public override IByteBuffer RetainedDuplicate() => this.NewLeakAwareByteBuffer(base.RetainedDuplicate()); + + public override IByteBuffer ReadRetainedSlice(int length) => this.NewLeakAwareByteBuffer(base.ReadRetainedSlice(length)); + SimpleLeakAwareByteBuffer NewLeakAwareByteBuffer(IByteBuffer wrapped) => this.NewLeakAwareByteBuffer(wrapped, this.Unwrap(), this.Leak); protected virtual SimpleLeakAwareByteBuffer NewLeakAwareByteBuffer(IByteBuffer wrapped, IByteBuffer trackedByteBuf, IResourceLeakTracker leakTracker) => diff --git a/src/DotNetty.Buffers/UnpooledUnsafeDirectByteBuffer.cs b/src/DotNetty.Buffers/UnpooledUnsafeDirectByteBuffer.cs index e0f7e8c8e..ff3d52781 100644 --- a/src/DotNetty.Buffers/UnpooledUnsafeDirectByteBuffer.cs +++ b/src/DotNetty.Buffers/UnpooledUnsafeDirectByteBuffer.cs @@ -297,7 +297,9 @@ public override Task SetBytesAsync(int index, Stream src, int length, Cance { this.CheckIndex(index, length); fixed (byte* addr = &this.Addr(index)) + { return UnsafeByteBufferUtil.SetBytesAsync(this, addr, index, src, length, cancellationToken); + } } public override int IoBufferCount => 1; diff --git a/src/DotNetty.Buffers/WrappedCompositeByteBuffer.cs b/src/DotNetty.Buffers/WrappedCompositeByteBuffer.cs index 07dff4b7c..3fb8453ee 100644 --- a/src/DotNetty.Buffers/WrappedCompositeByteBuffer.cs +++ b/src/DotNetty.Buffers/WrappedCompositeByteBuffer.cs @@ -110,13 +110,13 @@ internal WrappedCompositeByteBuffer(CompositeByteBuffer wrapped) : base(wrapped. public override int ForEachByteDesc(int index, int length, IByteProcessor processor) => this.wrapped.ForEachByteDesc(index, length, processor); - public override int GetHashCode() => this.wrapped.GetHashCode(); + public sealed override int GetHashCode() => this.wrapped.GetHashCode(); - public override bool Equals(IByteBuffer buf) => this.wrapped.Equals(buf); + public sealed override bool Equals(IByteBuffer buf) => this.wrapped.Equals(buf); - public override int CompareTo(IByteBuffer that) => this.wrapped.CompareTo(that); + public sealed override int CompareTo(IByteBuffer that) => this.wrapped.CompareTo(that); - public override int ReferenceCount => this.wrapped.ReferenceCount; + public sealed override int ReferenceCount => this.wrapped.ReferenceCount; public override IByteBuffer Duplicate() => this.wrapped.Duplicate(); @@ -669,5 +669,25 @@ public override IByteBuffer DiscardSomeReadBytes() protected internal sealed override void Deallocate() => this.wrapped.Deallocate(); public sealed override IByteBuffer Unwrap() => this.wrapped; + + public sealed override IntPtr AddressOfPinnedMemory() => this.wrapped.AddressOfPinnedMemory(); + + public sealed override ref byte GetPinnableMemoryAddress() => ref this.wrapped.GetPinnableMemoryAddress(); + + public sealed override bool HasMemoryAddress => this.wrapped.HasMemoryAddress; + + public sealed override bool IsWritable(int size) => this.wrapped.IsWritable(size); + + public sealed override int MaxCapacity => this.wrapped.MaxCapacity; + + public sealed override bool IsDirect => this.wrapped.IsDirect; + + public override IByteBuffer ReadRetainedSlice(int length) => this.wrapped.ReadRetainedSlice(length); + + public override IByteBuffer RetainedDuplicate() => this.wrapped.RetainedDuplicate(); + + public override IByteBuffer RetainedSlice() => this.wrapped.RetainedSlice(); + + public override IByteBuffer RetainedSlice(int index, int length) => this.wrapped.RetainedSlice(index, length); } } \ No newline at end of file diff --git a/src/DotNetty.Common/Deque.cs b/src/DotNetty.Common/Deque.cs deleted file mode 100644 index e99461c04..000000000 --- a/src/DotNetty.Common/Deque.cs +++ /dev/null @@ -1,893 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Nito -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using System.Reflection; - - /// - /// A double-ended queue (deque), which provides O(1) indexed access, O(1) removals from the front and back, amortized - /// O(1) insertions to the front and back, and O(N) insertions and removals anywhere else (with the operations getting - /// slower as the index approaches the middle). - /// - /// The type of elements contained in the deque. - [DebuggerDisplay("Count = {Count}, Capacity = {Capacity}")] - [DebuggerTypeProxy(typeof(Deque<>.DebugView))] - sealed class Deque : IList, IList - { - /// - /// The default capacity. - /// - const int DefaultCapacity = 8; - - /// - /// The circular buffer that holds the view. - /// - T[] buffer; - - /// - /// The offset into where the view begins. - /// - int offset; - - /// - /// Initializes a new instance of the class with the specified capacity. - /// - /// The initial capacity. Must be greater than 0. - public Deque(int capacity) - { - if (capacity < 1) - throw new ArgumentOutOfRangeException(nameof(capacity), "Capacity must be greater than 0."); - this.buffer = new T[capacity]; - } - - /// - /// Initializes a new instance of the class with the elements from the specified - /// collection. - /// - /// The collection. - public Deque(IEnumerable collection) - { - int count = collection.Count(); - if (count > 0) - { - this.buffer = new T[count]; - this.DoInsertRange(0, collection, count); - } - else - { - this.buffer = new T[DefaultCapacity]; - } - } - - /// - /// Initializes a new instance of the class. - /// - public Deque() - : this(DefaultCapacity) - { - } - - #region GenericListImplementations - - /// - /// Gets a value indicating whether this list is read-only. This implementation always returns false. - /// - /// true if this list is read-only; otherwise, false. - bool ICollection.IsReadOnly => false; - - /// - /// Gets or sets the item at the specified index. - /// - /// The index of the item to get or set. - /// is not a valid index in this list. - /// This property is set and the list is read-only. - public T this[int index] - { - get - { - CheckExistingIndexArgument(this.Count, index); - return this.DoGetItem(index); - } - - set - { - CheckExistingIndexArgument(this.Count, index); - this.DoSetItem(index, value); - } - } - - /// - /// Inserts an item to this list at the specified index. - /// - /// The zero-based index at which should be inserted. - /// The object to insert into this list. - /// - /// is not a valid index in this list. - /// - /// - /// This list is read-only. - /// - public void Insert(int index, T item) - { - CheckNewIndexArgument(this.Count, index); - this.DoInsert(index, item); - } - - /// - /// Removes the item at the specified index. - /// - /// The zero-based index of the item to remove. - /// - /// is not a valid index in this list. - /// - /// - /// This list is read-only. - /// - public void RemoveAt(int index) - { - CheckExistingIndexArgument(this.Count, index); - this.DoRemoveAt(index); - } - - /// - /// Determines the index of a specific item in this list. - /// - /// The object to locate in this list. - /// The index of if found in this list; otherwise, -1. - public int IndexOf(T item) - { - EqualityComparer comparer = EqualityComparer.Default; - int ret = 0; - foreach (T sourceItem in this) - { - if (comparer.Equals(item, sourceItem)) - return ret; - ++ret; - } - - return -1; - } - - /// - /// Adds an item to the end of this list. - /// - /// The object to add to this list. - /// - /// This list is read-only. - /// - void ICollection.Add(T item) - { - this.DoInsert(this.Count, item); - } - - /// - /// Determines whether this list contains a specific value. - /// - /// The object to locate in this list. - /// - /// true if is found in this list; otherwise, false. - /// - bool ICollection.Contains(T item) - { - return this.Contains(item, null); - } - - /// - /// Copies the elements of this list to an , starting at a particular - /// index. - /// - /// - /// The one-dimensional that is the destination of the elements copied - /// from this slice. The must have zero-based indexing. - /// - /// The zero-based index in at which copying begins. - /// - /// is null. - /// - /// - /// is less than 0. - /// - /// - /// is equal to or greater than the length of . - /// -or- - /// The number of elements in the source is greater than the - /// available space from to the end of the destination . - /// - void ICollection.CopyTo(T[] array, int arrayIndex) - { - if (array == null) - throw new ArgumentNullException(nameof(array), "Array is null"); - - int count = this.Count; - CheckRangeArguments(array.Length, arrayIndex, count); - for (int i = 0; i != count; ++i) - { - array[arrayIndex + i] = this[i]; - } - } - - /// - /// Removes the first occurrence of a specific object from this list. - /// - /// The object to remove from this list. - /// - /// true if was successfully removed from this list; otherwise, false. This method also - /// returns false if is not found in this list. - /// - /// - /// This list is read-only. - /// - public bool Remove(T item) - { - int index = this.IndexOf(item); - if (index == -1) - return false; - - this.DoRemoveAt(index); - return true; - } - - /// - /// Returns an enumerator that iterates through the collection. - /// - /// - /// A that can be used to iterate through the collection. - /// - public IEnumerator GetEnumerator() - { - int count = this.Count; - for (int i = 0; i != count; ++i) - { - yield return this.DoGetItem(i); - } - } - - /// - /// Returns an enumerator that iterates through a collection. - /// - /// - /// An object that can be used to iterate through the collection. - /// - IEnumerator IEnumerable.GetEnumerator() - { - return this.GetEnumerator(); - } - - #endregion - - #region ObjectListImplementations - - /// - /// Returns whether or not the type of a given item indicates it is appropriate for storing in this container. - /// - /// The item to test. - /// true if the item is appropriate to store in this container; otherwise, false. - bool ObjectIsT(object item) - { - if (item is T) - { - return true; - } - - if (item == null) - { - TypeInfo typeInfo = typeof(T).GetTypeInfo(); - if (typeInfo.IsClass && !typeInfo.IsPointer) - return true; // classes, arrays, and delegates - if (typeInfo.IsInterface) - return true; // interfaces - if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>)) - return true; // nullable value types - } - - return false; - } - - int IList.Add(object value) - { - if (!this.ObjectIsT(value)) - throw new ArgumentException("Item is not of the correct type.", nameof(value)); - this.AddToBack((T)value); - return this.Count - 1; - } - - bool IList.Contains(object value) - { - if (!this.ObjectIsT(value)) - throw new ArgumentException("Item is not of the correct type.", nameof(value)); - return this.Contains((T)value); - } - - int IList.IndexOf(object value) - { - if (!this.ObjectIsT(value)) - throw new ArgumentException("Item is not of the correct type.", nameof(value)); - return this.IndexOf((T)value); - } - - void IList.Insert(int index, object value) - { - if (!this.ObjectIsT(value)) - throw new ArgumentException("Item is not of the correct type.", nameof(value)); - this.Insert(index, (T)value); - } - - bool IList.IsFixedSize => false; - - bool IList.IsReadOnly => false; - - void IList.Remove(object value) - { - if (!this.ObjectIsT(value)) - throw new ArgumentException("Item is not of the correct type.", nameof(value)); - this.Remove((T)value); - } - - object IList.this[int index] - { - get { return this[index]; } - - set - { - if (!this.ObjectIsT(value)) - throw new ArgumentException("Item is not of the correct type.", nameof(value)); - this[index] = (T)value; - } - } - - void ICollection.CopyTo(Array array, int index) - { - if (array == null) - throw new ArgumentNullException(nameof(array), "Destination array cannot be null."); - CheckRangeArguments(array.Length, index, this.Count); - - for (int i = 0; i != this.Count; ++i) - { - try - { - array.SetValue(this[i], index + i); - } - catch (InvalidCastException ex) - { - throw new ArgumentException("Destination array is of incorrect type.", ex); - } - } - } - - bool ICollection.IsSynchronized => false; - - object ICollection.SyncRoot => this; - - #endregion - - #region GenericListHelpers - - /// - /// Checks the argument to see if it refers to a valid insertion point in a source of a given - /// length. - /// - /// The length of the source. This parameter is not checked for validity. - /// The index into the source. - /// - /// is not a valid index to an insertion point for - /// the source. - /// - static void CheckNewIndexArgument(int sourceLength, int index) - { - if (index < 0 || index > sourceLength) - { - throw new ArgumentOutOfRangeException(nameof(index), "Invalid new index " + index + " for source length " + sourceLength); - } - } - - /// - /// Checks the argument to see if it refers to an existing element in a source of a given - /// length. - /// - /// The length of the source. This parameter is not checked for validity. - /// The index into the source. - /// - /// is not a valid index to an existing element for - /// the source. - /// - static void CheckExistingIndexArgument(int sourceLength, int index) - { - if (index < 0 || index >= sourceLength) - { - throw new ArgumentOutOfRangeException(nameof(index), "Invalid existing index " + index + " for source length " + sourceLength); - } - } - - /// - /// Checks the and arguments for validity when applied to a source - /// of a given length. Allows 0-element ranges, including a 0-element range at the end of the source. - /// - /// The length of the source. This parameter is not checked for validity. - /// The index into source at which the range begins. - /// The number of elements in the range. - /// - /// Either or is less - /// than 0. - /// - /// The range [offset, offset + count) is not within the range [0, sourceLength). - static void CheckRangeArguments(int sourceLength, int offset, int count) - { - if (offset < 0) - { - throw new ArgumentOutOfRangeException(nameof(offset), "Invalid offset " + offset); - } - - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), "Invalid count " + count); - } - - if (sourceLength - offset < count) - { - throw new ArgumentException("Invalid offset (" + offset + ") or count + (" + count + ") for source length " + sourceLength); - } - } - - #endregion - - /// - /// Gets a value indicating whether this instance is empty. - /// - bool IsEmpty => this.Count == 0; - - /// - /// Gets a value indicating whether this instance is at full capacity. - /// - bool IsFull => this.Count == this.Capacity; - - /// - /// Gets a value indicating whether the buffer is "split" (meaning the beginning of the view is at a later index in - /// than the end). - /// - bool IsSplit => this.offset > (this.Capacity - this.Count); - - /// - /// Gets or sets the capacity for this deque. This value must always be greater than zero, and this property cannot be - /// set to a value less than . - /// - /// Capacity cannot be set to a value less than . - public int Capacity - { - get { return this.buffer.Length; } - - set - { - if (value < 1) - throw new ArgumentOutOfRangeException(nameof(value), "Capacity must be greater than 0."); - - if (value < this.Count) - throw new InvalidOperationException("Capacity cannot be set to a value less than Count"); - - if (value == this.buffer.Length) - return; - - // Create the new buffer and copy our existing range. - var newBuffer = new T[value]; - if (this.IsSplit) - { - // The existing buffer is split, so we have to copy it in parts - int length = this.Capacity - this.offset; - Array.Copy(this.buffer, this.offset, newBuffer, 0, length); - Array.Copy(this.buffer, 0, newBuffer, length, this.Count - length); - } - else - { - // The existing buffer is whole - Array.Copy(this.buffer, this.offset, newBuffer, 0, this.Count); - } - - // Set up to use the new buffer. - this.buffer = newBuffer; - this.offset = 0; - } - } - - /// - /// Gets the number of elements contained in this deque. - /// - /// The number of elements contained in this deque. - public int Count { get; private set; } - - /// - /// Applies the offset to , resulting in a buffer index. - /// - /// The deque index. - /// The buffer index. - int DequeIndexToBufferIndex(int index) - { - return (index + this.offset) % this.Capacity; - } - - /// - /// Gets an element at the specified view index. - /// - /// The zero-based view index of the element to get. This index is guaranteed to be valid. - /// The element at the specified index. - T DoGetItem(int index) - { - return this.buffer[this.DequeIndexToBufferIndex(index)]; - } - - /// - /// Sets an element at the specified view index. - /// - /// The zero-based view index of the element to get. This index is guaranteed to be valid. - /// The element to store in the list. - void DoSetItem(int index, T item) - { - this.buffer[this.DequeIndexToBufferIndex(index)] = item; - } - - /// - /// Inserts an element at the specified view index. - /// - /// - /// The zero-based view index at which the element should be inserted. This index is guaranteed to be - /// valid. - /// - /// The element to store in the list. - void DoInsert(int index, T item) - { - this.EnsureCapacityForOneElement(); - - if (index == 0) - { - this.DoAddToFront(item); - return; - } - else if (index == this.Count) - { - this.DoAddToBack(item); - return; - } - - this.DoInsertRange(index, new[] { item }, 1); - } - - /// - /// Removes an element at the specified view index. - /// - /// The zero-based view index of the element to remove. This index is guaranteed to be valid. - void DoRemoveAt(int index) - { - if (index == 0) - { - this.DoRemoveFromFront(); - return; - } - else if (index == this.Count - 1) - { - this.DoRemoveFromBack(); - return; - } - - this.DoRemoveRange(index, 1); - } - - /// - /// Increments by using modulo- arithmetic. - /// - /// The value by which to increase . May not be negative. - /// The value of after it was incremented. - int PostIncrement(int value) - { - int ret = this.offset; - this.offset += value; - this.offset %= this.Capacity; - return ret; - } - - /// - /// Decrements by using modulo- arithmetic. - /// - /// - /// The value by which to reduce . May not be negative or greater than - /// . - /// - /// The value of before it was decremented. - int PreDecrement(int value) - { - this.offset -= value; - if (this.offset < 0) - this.offset += this.Capacity; - return this.offset; - } - - /// - /// Inserts a single element to the back of the view. must be false when this method is called. - /// - /// The element to insert. - void DoAddToBack(T value) - { - this.buffer[this.DequeIndexToBufferIndex(this.Count)] = value; - ++this.Count; - } - - /// - /// Inserts a single element to the front of the view. must be false when this method is called. - /// - /// The element to insert. - void DoAddToFront(T value) - { - this.buffer[this.PreDecrement(1)] = value; - ++this.Count; - } - - /// - /// Removes and returns the last element in the view. must be false when this method is called. - /// - /// The former last element. - T DoRemoveFromBack() - { - T ret = this.buffer[this.DequeIndexToBufferIndex(this.Count - 1)]; - --this.Count; - return ret; - } - - /// - /// Removes and returns the first element in the view. must be false when this method is called. - /// - /// The former first element. - T DoRemoveFromFront() - { - --this.Count; - return this.buffer[this.PostIncrement(1)]; - } - - /// - /// Inserts a range of elements into the view. - /// - /// The index into the view at which the elements are to be inserted. - /// The elements to insert. - /// - /// The number of elements in . Must be greater than zero, and - /// the sum of and must be less than or equal to - /// . - /// - void DoInsertRange(int index, IEnumerable collection, int collectionCount) - { - // Make room in the existing list - if (index < this.Count / 2) - { - // Inserting into the first half of the list - - // Move lower items down: [0, index) -> [Capacity - collectionCount, Capacity - collectionCount + index) - // This clears out the low "index" number of items, moving them "collectionCount" places down; - // after rotation, there will be a "collectionCount"-sized hole at "index". - int copyCount = index; - int writeIndex = this.Capacity - collectionCount; - for (int j = 0; j != copyCount; ++j) - this.buffer[this.DequeIndexToBufferIndex(writeIndex + j)] = this.buffer[this.DequeIndexToBufferIndex(j)]; - - // Rotate to the new view - this.PreDecrement(collectionCount); - } - else - { - // Inserting into the second half of the list - - // Move higher items up: [index, count) -> [index + collectionCount, collectionCount + count) - int copyCount = this.Count - index; - int writeIndex = index + collectionCount; - for (int j = copyCount - 1; j != -1; --j) - this.buffer[this.DequeIndexToBufferIndex(writeIndex + j)] = this.buffer[this.DequeIndexToBufferIndex(index + j)]; - } - - // Copy new items into place - int i = index; - foreach (T item in collection) - { - this.buffer[this.DequeIndexToBufferIndex(i)] = item; - ++i; - } - - // Adjust valid count - this.Count += collectionCount; - } - - /// - /// Removes a range of elements from the view. - /// - /// The index into the view at which the range begins. - /// - /// The number of elements in the range. This must be greater than 0 and less than or equal - /// to . - /// - void DoRemoveRange(int index, int collectionCount) - { - if (index == 0) - { - // Removing from the beginning: rotate to the new view - this.PostIncrement(collectionCount); - this.Count -= collectionCount; - return; - } - else if (index == this.Count - collectionCount) - { - // Removing from the ending: trim the existing view - this.Count -= collectionCount; - return; - } - - if ((index + (collectionCount / 2)) < this.Count / 2) - { - // Removing from first half of list - - // Move lower items up: [0, index) -> [collectionCount, collectionCount + index) - int copyCount = index; - int writeIndex = collectionCount; - for (int j = copyCount - 1; j != -1; --j) - this.buffer[this.DequeIndexToBufferIndex(writeIndex + j)] = this.buffer[this.DequeIndexToBufferIndex(j)]; - - // Rotate to new view - this.PostIncrement(collectionCount); - } - else - { - // Removing from second half of list - - // Move higher items down: [index + collectionCount, count) -> [index, count - collectionCount) - int copyCount = this.Count - collectionCount - index; - int readIndex = index + collectionCount; - for (int j = 0; j != copyCount; ++j) - this.buffer[this.DequeIndexToBufferIndex(index + j)] = this.buffer[this.DequeIndexToBufferIndex(readIndex + j)]; - } - - // Adjust valid count - this.Count -= collectionCount; - } - - /// - /// Doubles the capacity if necessary to make room for one more element. When this method returns, - /// is false. - /// - void EnsureCapacityForOneElement() - { - if (this.IsFull) - { - this.Capacity = this.Capacity * 2; - } - } - - /// - /// Inserts a single element at the back of this deque. - /// - /// The element to insert. - public void AddToBack(T value) - { - this.EnsureCapacityForOneElement(); - this.DoAddToBack(value); - } - - /// - /// Inserts a single element at the front of this deque. - /// - /// The element to insert. - public void AddToFront(T value) - { - this.EnsureCapacityForOneElement(); - this.DoAddToFront(value); - } - - /// - /// Inserts a collection of elements into this deque. - /// - /// The index at which the collection is inserted. - /// The collection of elements to insert. - /// - /// is not a valid index to an insertion point for - /// the source. - /// - public void InsertRange(int index, IEnumerable collection) - { - int collectionCount = collection.Count(); - CheckNewIndexArgument(this.Count, index); - - // Overflow-safe check for "this.Count + collectionCount > this.Capacity" - if (collectionCount > this.Capacity - this.Count) - { - this.Capacity = checked(this.Count + collectionCount); - } - - if (collectionCount == 0) - { - return; - } - - this.DoInsertRange(index, collection, collectionCount); - } - - /// - /// Removes a range of elements from this deque. - /// - /// The index into the deque at which the range begins. - /// The number of elements to remove. - /// - /// Either or is less - /// than 0. - /// - /// - /// The range [, + - /// ) is not within the range [0, ). - /// - public void RemoveRange(int offset, int count) - { - CheckRangeArguments(this.Count, offset, count); - - if (count == 0) - { - return; - } - - this.DoRemoveRange(offset, count); - } - - /// - /// Removes and returns the last element of this deque. - /// - /// The former last element. - /// The deque is empty. - public T RemoveFromBack() - { - if (this.IsEmpty) - throw new InvalidOperationException("The deque is empty."); - - return this.DoRemoveFromBack(); - } - - /// - /// Removes and returns the first element of this deque. - /// - /// The former first element. - /// The deque is empty. - public T RemoveFromFront() - { - if (this.IsEmpty) - throw new InvalidOperationException("The deque is empty."); - - return this.DoRemoveFromFront(); - } - - /// - /// Removes all items from this deque. - /// - public void Clear() - { - this.offset = 0; - this.Count = 0; - } - - [DebuggerNonUserCode] - sealed class DebugView - { - readonly Deque deque; - - public DebugView(Deque deque) - { - this.deque = deque; - } - - [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] - public T[] Items - { - get - { - var array = new T[this.deque.Count]; - ((ICollection)this.deque).CopyTo(array, 0); - return array; - } - } - } - } -} diff --git a/src/DotNetty.Common/ResourceLeakDetector.cs b/src/DotNetty.Common/ResourceLeakDetector.cs index bebc25958..34145e8c1 100644 --- a/src/DotNetty.Common/ResourceLeakDetector.cs +++ b/src/DotNetty.Common/ResourceLeakDetector.cs @@ -141,7 +141,13 @@ public IResourceLeakTracker Track(object obj) void ReportLeak(DefaultResourceLeak resourceLeak) { - string records = resourceLeak.ToString(); + if (!Logger.ErrorEnabled) + { + resourceLeak.Dispose(); + return; + } + + string records = resourceLeak.Dump(); if (this.reportedLeaks.TryAdd(records, true)) { if (records.Length == 0) @@ -179,21 +185,31 @@ sealed class DefaultResourceLeak : IResourceLeakTracker RecordEntry head; long droppedRecords; + readonly WeakReference gcNotice; public DefaultResourceLeak(ResourceLeakDetector owner, object referent) { Debug.Assert(referent != null); this.owner = owner; - if (owner.gcNotificationMap.TryGetValue(referent, out GCNotice existingNotice)) - { - existingNotice.Rearm(this); - } - else + GCNotice gcNotice; + do { - owner.gcNotificationMap.Add(referent, new GCNotice(this, referent)); + GCNotice gcNotice0 = null; + gcNotice = owner.gcNotificationMap.GetValue(referent, referent0 => + { + gcNotice0 = new GCNotice(referent0, owner); + return gcNotice0; + }); + if (gcNotice0 != null && gcNotice0 != gcNotice) + { + GC.SuppressFinalize(gcNotice0); + } } + while (!gcNotice.Arm(this, owner, referent)); + this.gcNotice = new WeakReference(gcNotice); this.head = RecordEntry.Bottom; + Record(); } public void Record() => this.Record0(null); @@ -213,7 +229,7 @@ void Record0(object hint) bool dropped; do { - if ((prevHead = oldHead = this.head) == null) + if ((prevHead = oldHead = Volatile.Read(ref this.head)) == null) { // already closed. return; @@ -244,40 +260,34 @@ void Record0(object hint) public bool Close(object trackedObject) { - if (this.owner.gcNotificationMap.TryGetValue(trackedObject, out GCNotice notice)) + if (gcNotice.TryGetTarget(out var notice)) { - // The close is called by byte buffer release, in this case - // we suppress the GCNotice finalize to prevent false positive - // report where the byte buffer instance gets reused by thread - // local cache and the existing GCNotice finalizer still holds - // the same byte buffer instance. - GC.SuppressFinalize(notice); - - Debug.Assert(this.owner.gcNotificationMap.Remove(trackedObject)); - Interlocked.Exchange(ref this.head, null); - return true; + if (notice.UnArm(this, owner, trackedObject)) + { + this.Dispose(); + return true; + } } return false; } - // This is called from GCNotice finalizer - internal void CloseFinal(object trackedObject) + // This is called from GCNotice finalizer + internal void CloseFinal() { - if (this.owner.gcNotificationMap.Remove(trackedObject) - && Volatile.Read(ref this.head) != null) + if (Volatile.Read(ref this.head) != null) { this.owner.ReportLeak(this); } } - public override string ToString() + public string Dump() { RecordEntry oldHead = Interlocked.Exchange(ref this.head, null); if (oldHead == null) { // Already closed - return string.Empty; + return string.Empty; } long dropped = Interlocked.Read(ref this.droppedRecords); @@ -314,7 +324,7 @@ public override string ToString() if (duped > 0) { buf.Append(": ") - .Append(dropped) + .Append(duped) .Append(" leak records were discarded because they were duplicates") .Append(StringUtil.Newline); } @@ -334,6 +344,11 @@ public override string ToString() buf.Length = buf.Length - StringUtil.Newline.Length; return buf.ToString(); } + + internal void Dispose() + { + Interlocked.Exchange(ref this.head, null); + } } // Record @@ -403,26 +418,81 @@ class GCNotice // Once the key dies, the dictionary automatically removes // the key/value entry. // - DefaultResourceLeak leak; + private readonly LinkedList leakList = new LinkedList(); object referent; - - public GCNotice(DefaultResourceLeak leak, object referent) + ResourceLeakDetector owner; + public GCNotice(object referent, ResourceLeakDetector owner) { - this.leak = leak; this.referent = referent; + this.owner = owner; } ~GCNotice() { - object trackedObject = this.referent; - this.referent = null; - this.leak.CloseFinal(trackedObject); + lock (this.leakList) + { + foreach (var leak in this.leakList) + { + leak.CloseFinal(); + } + this.leakList.Clear(); + + //Since we get here with finalizer, it's no needed to remove key from gcNotificationMap + + //this.referent = null; + this.owner = null; + } + } + + public bool Arm(DefaultResourceLeak leak, ResourceLeakDetector owner, object referent) + { + lock (this.leakList) + { + if (this.owner == null) + { + //Already disposed + return false; + } + Debug.Assert(owner == this.owner); + Debug.Assert(referent == this.referent); + + this.leakList.AddLast(leak); + return true; + } } - public void Rearm(DefaultResourceLeak newLeak) + public bool UnArm(DefaultResourceLeak leak, ResourceLeakDetector owner, object referent) { - DefaultResourceLeak oldLeak = Interlocked.Exchange(ref this.leak, newLeak); - oldLeak.CloseFinal(this.referent); + lock (this.leakList) + { + if (this.owner == null) + { + //Already disposed + return false; + } + Debug.Assert(owner == this.owner); + Debug.Assert(referent == this.referent); + + bool res = this.leakList.Remove(leak); + if (this.leakList.Count == 0) + { + // The close is called by byte buffer release, in this case + // we suppress the GCNotice finalize to prevent false positive + // report where the byte buffer instance gets reused by thread + // local cache and the existing GCNotice finalizer still holds + // the same byte buffer instance. + GC.SuppressFinalize(this); + + // Don't inline the variable, anything inside Debug.Assert() + // will be stripped out in Release builds + bool removed = this.owner.gcNotificationMap.Remove(this.referent); + Debug.Assert(removed); + + //this.referent = null; + this.owner = null; + } + return res; + } } } } From 47f5ec7303037f1360615d182939e04d8619a2b3 Mon Sep 17 00:00:00 2001 From: Erik O'Leary <969938+onionhammer@users.noreply.github.com> Date: Mon, 7 Jan 2019 10:31:35 -0600 Subject: [PATCH 12/33] Fix ParseMachineId (#459) Fix issue parsing manual machine id; fixes #458 - second parameter of `Substring` is 'length' not 'index' --- src/DotNetty.Transport/Channels/DefaultChannelId.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DotNetty.Transport/Channels/DefaultChannelId.cs b/src/DotNetty.Transport/Channels/DefaultChannelId.cs index 1ea5edab5..05a7e3d92 100644 --- a/src/DotNetty.Transport/Channels/DefaultChannelId.cs +++ b/src/DotNetty.Transport/Channels/DefaultChannelId.cs @@ -123,7 +123,7 @@ static byte[] ParseMachineId(string value) var machineId = new byte[MachineIdLen]; for (int i = 0; i < value.Length; i += 2) { - machineId[i] = (byte)int.Parse(value.Substring(i, i + 2), NumberStyles.AllowHexSpecifier); + machineId[i] = (byte)int.Parse(value.Substring(i, 2), NumberStyles.AllowHexSpecifier); } return machineId; } @@ -251,4 +251,4 @@ public override bool Equals(object obj) public override string ToString() => this.AsShortText(); } -} \ No newline at end of file +} From 1cdaadbfaad12046442426bb2d9655c3b2a1390b Mon Sep 17 00:00:00 2001 From: Andrey Ilnitsky Date: Fri, 11 Jun 2021 16:25:37 -0700 Subject: [PATCH 13/33] - target net472 and netstandard2.0 - microsoft.extensions.logging 5.0.0 - microsoft.extensions.configuration 5.0.0 --- DotNetty.sln.DotSettings | 1 + RELEASE_NOTES.md | 5 +++++ build.cake | 4 ++-- examples/Discard.Client/Discard.Client.csproj | 6 +++--- examples/Discard.Server/Discard.Server.csproj | 6 +++--- examples/Echo.Client/Echo.Client.csproj | 6 +++--- examples/Echo.Server/Echo.Server.csproj | 6 +++--- examples/Examples.Common/ExampleHelper.cs | 6 +++--- .../Examples.Common/Examples.Common.csproj | 12 +++++------ .../Factorial.Client/Factorial.Client.csproj | 6 +++--- .../Factorial.Server/Factorial.Server.csproj | 6 +++--- examples/Factorial/Factorial.csproj | 4 ++-- examples/HttpServer/HttpServer.csproj | 6 +++--- .../QuoteOfTheMoment.Client.csproj | 6 +++--- .../QuoteOfTheMoment.Server.csproj | 6 +++--- .../SecureChat.Client.csproj | 6 +++--- .../SecureChat.Server.csproj | 6 +++--- examples/Telnet.Client/Telnet.Client.csproj | 6 +++--- examples/Telnet.Server/Telnet.Server.csproj | 6 +++--- .../WebSockets.Client.csproj | 6 +++--- .../WebSockets.Server.csproj | 6 +++--- src/DotNetty.Buffers/DotNetty.Buffers.csproj | 15 ++++--------- src/DotNetty.Buffers/UnsafeByteBufferUtil.cs | 2 +- .../DotNetty.Codecs.Http.csproj | 15 ++++--------- .../DotNetty.Codecs.Mqtt.csproj | 13 +++--------- .../DotNetty.Codecs.Protobuf.csproj | 13 +++--------- .../DotNetty.Codecs.ProtocolBuffers.csproj | 15 +++---------- .../DotNetty.Codecs.Redis.csproj | 13 +++--------- src/DotNetty.Codecs/DotNetty.Codecs.csproj | 13 +++--------- src/DotNetty.Common/DotNetty.Common.csproj | 19 +++++------------ .../DotNetty.Handlers.csproj | 15 +++---------- src/DotNetty.Handlers/Tls/SniHandler.cs | 2 +- src/DotNetty.Handlers/Tls/TlsHandler.cs | 8 +++---- .../DotNetty.Transport.Libuv.csproj | 12 +++-------- .../Native/NativeMethods.cs | 6 +++--- .../Native/WindowsApi.cs | 2 +- .../Native/WriteRequest.cs | 2 +- .../Sockets/AbstractSocketByteChannel.cs | 4 ++-- .../Channels/Sockets/SocketDatagramChannel.cs | 2 +- .../DotNetty.Transport.csproj | 21 +++---------------- src/shared/SharedAssemblyInfo.cs | 4 ++-- .../DotNetty.Buffers.Tests.csproj | 4 ++-- .../DotNetty.Codecs.Http.Tests.csproj | 4 ++-- .../DotNetty.Codecs.Mqtt.Tests.csproj | 4 ++-- .../DotNetty.Codecs.Protobuf.Tests.csproj | 4 ++-- ...tNetty.Codecs.ProtocolBuffers.Tests.csproj | 4 ++-- .../DotNetty.Codecs.Redis.Tests.csproj | 4 ++-- .../DotNetty.Codecs.Tests.csproj | 4 ++-- .../DotNetty.Common.Tests.csproj | 4 ++-- .../DotNetty.Handlers.Tests.csproj | 4 ++-- .../AbstractByteBufferAllocatorBenchmark.cs | 6 ++++-- .../Buffers/ByteBufUtilBenchmark.cs | 1 - .../Buffers/ByteBufferBenchmark.cs | 11 +++++----- .../Buffers/PooledByteBufferBenchmark.cs | 13 ++++++------ .../Buffers/UnpooledByteBufferBenchmark.cs | 12 +++++------ .../Codecs/DateFormatterBenchmark.cs | 4 ++-- .../Common/AsciiStringBenchmark.cs | 12 +++++------ .../Concurrency/FastThreadLocalBenchmark.cs | 4 ++-- .../SingleThreadEventExecutorBenchmark.cs | 1 - .../DotNetty.Microbench.csproj | 12 +++++------ .../Headers/HeadersBenchmark.cs | 1 - .../Http/ClientCookieDecoderBenchmark.cs | 4 ++-- .../Http/HttpRequestDecoderBenchmark.cs | 1 - .../Http/HttpRequestEncoderInsertBenchmark.cs | 4 ++-- .../WriteBytesVsShortOrMediumBenchmark.cs | 4 ++-- .../Internal/PlatformDependentBenchmark.cs | 5 +++-- .../DotNetty.Tests.Common.csproj | 4 ++-- .../DotNetty.Tests.End2End.csproj | 4 ++-- .../DotNetty.Transport.Libuv.Tests.csproj | 6 +++--- ...otNetty.Transport.Tests.Performance.csproj | 4 ++-- .../DotNetty.Transport.Tests.csproj | 4 ++-- 71 files changed, 193 insertions(+), 278 deletions(-) diff --git a/DotNetty.sln.DotSettings b/DotNetty.sln.DotSettings index 5d7c8db35..b04f8d982 100644 --- a/DotNetty.sln.DotSettings +++ b/DotNetty.sln.DotSettings @@ -98,6 +98,7 @@ Licensed under the MIT license. See LICENSE file in the project root for full li True True True + True True True True diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6bb552172..fee9a0bf2 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,8 @@ +#### 0.7.0 June 11, 2021 +- target net472 and netstandard2.0 +- microsoft.extensions.logging 5.0.0 +- microsoft.extensions.configuration 5.0.0 + #### 0.6.0 October 9, 2018 - Clearly marks Unsafe Buffer management routines as `unsafe` - Changes defaults for Unpooled and Pooled buffer allocators to safe versions diff --git a/build.cake b/build.cake index bdf1417aa..acc9db369 100644 --- a/build.cake +++ b/build.cake @@ -173,7 +173,7 @@ Task("Benchmark") { StartProcess(nuget.ToString() + "/nuget.exe", "install NBench.Runner -OutputDirectory tools -ExcludeVersion -Version 1.0.0"); - var libraries = GetFiles("./test/**/bin/" + configuration + "/net452/*.Performance.dll"); + var libraries = GetFiles("./test/**/bin/" + configuration + "/net472/*.Performance.dll"); CreateDirectory(outputPerfResults); foreach (var lib in libraries) @@ -181,7 +181,7 @@ Task("Benchmark") Information("Using NBench.Runner: {0}", lib); // Make sure libuv.dll exists in performance test folder - CopyFiles("./test/DotNetty.Transport.Libuv.Tests/bin/" + configuration + "/net452/win-x64/libuv.dll", lib.GetDirectory(), false); + CopyFiles("./test/DotNetty.Transport.Libuv.Tests/bin/" + configuration + "/net472/win-x64/libuv.dll", lib.GetDirectory(), false); CopyFiles("./tools/NBench.Runner*/**/NBench.Runner.exe", lib.GetDirectory(), false); var nbenchArgs = new StringBuilder() diff --git a/examples/Discard.Client/Discard.Client.csproj b/examples/Discard.Client/Discard.Client.csproj index bcfafd5db..96c39faba 100644 --- a/examples/Discard.Client/Discard.Client.csproj +++ b/examples/Discard.Client/Discard.Client.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/Discard.Server/Discard.Server.csproj b/examples/Discard.Server/Discard.Server.csproj index bcfafd5db..96c39faba 100644 --- a/examples/Discard.Server/Discard.Server.csproj +++ b/examples/Discard.Server/Discard.Server.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/Echo.Client/Echo.Client.csproj b/examples/Echo.Client/Echo.Client.csproj index bcfafd5db..96c39faba 100644 --- a/examples/Echo.Client/Echo.Client.csproj +++ b/examples/Echo.Client/Echo.Client.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/Echo.Server/Echo.Server.csproj b/examples/Echo.Server/Echo.Server.csproj index d5133dab1..defec1f72 100644 --- a/examples/Echo.Server/Echo.Server.csproj +++ b/examples/Echo.Server/Echo.Server.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/Examples.Common/ExampleHelper.cs b/examples/Examples.Common/ExampleHelper.cs index 0ae7b20c6..535170274 100644 --- a/examples/Examples.Common/ExampleHelper.cs +++ b/examples/Examples.Common/ExampleHelper.cs @@ -6,7 +6,7 @@ namespace Examples.Common using System; using DotNetty.Common.Internal.Logging; using Microsoft.Extensions.Configuration; - using Microsoft.Extensions.Logging.Console; + using Microsoft.Extensions.Logging; public static class ExampleHelper { @@ -22,7 +22,7 @@ public static string ProcessDirectory { get { -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 return AppContext.BaseDirectory; #else return AppDomain.CurrentDomain.BaseDirectory; @@ -32,6 +32,6 @@ public static string ProcessDirectory public static IConfigurationRoot Configuration { get; } - public static void SetConsoleLogger() => InternalLoggerFactory.DefaultFactory.AddProvider(new ConsoleLoggerProvider((s, level) => true, false)); + public static void SetConsoleLogger() => InternalLoggerFactory.DefaultFactory = LoggerFactory.Create(builder => builder.AddConsole()); } } \ No newline at end of file diff --git a/examples/Examples.Common/Examples.Common.csproj b/examples/Examples.Common/Examples.Common.csproj index 6c6288b95..8e186c734 100644 --- a/examples/Examples.Common/Examples.Common.csproj +++ b/examples/Examples.Common/Examples.Common.csproj @@ -1,14 +1,14 @@  - netstandard1.3;net451 - 1.6.1 + netstandard2.0;net472 + 2.0.3 false - - - - + + + + diff --git a/examples/Factorial.Client/Factorial.Client.csproj b/examples/Factorial.Client/Factorial.Client.csproj index c2c8a70ba..f5a342a29 100644 --- a/examples/Factorial.Client/Factorial.Client.csproj +++ b/examples/Factorial.Client/Factorial.Client.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/Factorial.Server/Factorial.Server.csproj b/examples/Factorial.Server/Factorial.Server.csproj index c2c8a70ba..f5a342a29 100644 --- a/examples/Factorial.Server/Factorial.Server.csproj +++ b/examples/Factorial.Server/Factorial.Server.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/Factorial/Factorial.csproj b/examples/Factorial/Factorial.csproj index 06ad6a0d6..d2ccbbd2f 100644 --- a/examples/Factorial/Factorial.csproj +++ b/examples/Factorial/Factorial.csproj @@ -1,7 +1,7 @@  - netstandard1.3;net451 - 1.6.1 + netstandard2.0;net472 + 2.0.3 false diff --git a/examples/HttpServer/HttpServer.csproj b/examples/HttpServer/HttpServer.csproj index d36ebb1f7..9e580ec6f 100644 --- a/examples/HttpServer/HttpServer.csproj +++ b/examples/HttpServer/HttpServer.csproj @@ -1,12 +1,12 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false true - + win-x64 diff --git a/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj b/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj index bcfafd5db..96c39faba 100644 --- a/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj +++ b/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj b/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj index bcfafd5db..96c39faba 100644 --- a/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj +++ b/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/SecureChat.Client/SecureChat.Client.csproj b/examples/SecureChat.Client/SecureChat.Client.csproj index bcfafd5db..96c39faba 100644 --- a/examples/SecureChat.Client/SecureChat.Client.csproj +++ b/examples/SecureChat.Client/SecureChat.Client.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/SecureChat.Server/SecureChat.Server.csproj b/examples/SecureChat.Server/SecureChat.Server.csproj index bcfafd5db..96c39faba 100644 --- a/examples/SecureChat.Server/SecureChat.Server.csproj +++ b/examples/SecureChat.Server/SecureChat.Server.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/Telnet.Client/Telnet.Client.csproj b/examples/Telnet.Client/Telnet.Client.csproj index bcfafd5db..96c39faba 100644 --- a/examples/Telnet.Client/Telnet.Client.csproj +++ b/examples/Telnet.Client/Telnet.Client.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/Telnet.Server/Telnet.Server.csproj b/examples/Telnet.Server/Telnet.Server.csproj index bcfafd5db..96c39faba 100644 --- a/examples/Telnet.Server/Telnet.Server.csproj +++ b/examples/Telnet.Server/Telnet.Server.csproj @@ -1,11 +1,11 @@  Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/WebSockets.Client/WebSockets.Client.csproj b/examples/WebSockets.Client/WebSockets.Client.csproj index 361196c21..1beb17f74 100644 --- a/examples/WebSockets.Client/WebSockets.Client.csproj +++ b/examples/WebSockets.Client/WebSockets.Client.csproj @@ -2,11 +2,11 @@ Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false - + win-x64 diff --git a/examples/WebSockets.Server/WebSockets.Server.csproj b/examples/WebSockets.Server/WebSockets.Server.csproj index 2c0d50ea0..86c509dbf 100644 --- a/examples/WebSockets.Server/WebSockets.Server.csproj +++ b/examples/WebSockets.Server/WebSockets.Server.csproj @@ -2,12 +2,12 @@ Exe - netcoreapp2.0;net451 - 1.6.1 + netcoreapp3.1;net472 + 2.0.3 false true - + win-x64 diff --git a/src/DotNetty.Buffers/DotNetty.Buffers.csproj b/src/DotNetty.Buffers/DotNetty.Buffers.csproj index 1d68f3c2a..a48ae7618 100644 --- a/src/DotNetty.Buffers/DotNetty.Buffers.csproj +++ b/src/DotNetty.Buffers/DotNetty.Buffers.csproj @@ -1,12 +1,12 @@  - netstandard1.3;net45 + netstandard2.0;net472 true Buffer management in DotNetty © Microsoft Corporation. All rights reserved. DotNetty: buffer management en-US - 0.6.0 + 0.7.0 Microsoft $(NoWarn);CS1591 True @@ -22,22 +22,15 @@ https://github.com/Azure/DotNetty/blob/master/LICENSE.txt true https://github.com/Azure/DotNetty/ - 1.6.1 + 2.0.3 - + - - - - - - - \ No newline at end of file diff --git a/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs b/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs index 5bcbbfa8b..61680802b 100644 --- a/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs +++ b/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs @@ -386,7 +386,7 @@ internal static void SetZero(byte* addr, int length) internal static string GetString(byte* src, int length, Encoding encoding) { -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 return encoding.GetString(src, length); #else int charCount = encoding.GetCharCount(src, length); diff --git a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj index 50d94aa4c..c1833227d 100644 --- a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj +++ b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj @@ -1,14 +1,14 @@  - netstandard1.3;net45 + netstandard2.0;net472 true DotNetty.Codecs.Http Http codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: Http codec en-US - 0.6.0 + 0.7.0 Microsoft $(NoWarn);CS1591 true @@ -24,13 +24,13 @@ true git https://github.com/Azure/DotNetty/ - 1.6.1 + 2.0.3 - + @@ -39,11 +39,4 @@ - - - - - - - \ No newline at end of file diff --git a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj index e8fb2a9b1..e851eefec 100644 --- a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj +++ b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj @@ -1,13 +1,13 @@  - netstandard1.3;net45 + netstandard2.0;net472 true DotNetty.Codecs.Mqtt MQTT codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: MQTT codec en-US - 0.6.0 + 0.7.0 Microsoft $(NoWarn);CS1591 false @@ -22,7 +22,7 @@ true git https://github.com/Azure/DotNetty/ - 1.6.1 + 2.0.3 @@ -33,11 +33,4 @@ - - - - - - - \ No newline at end of file diff --git a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj index 370b050d8..8e02867e9 100644 --- a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj +++ b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj @@ -1,13 +1,13 @@  - netstandard1.3;net45 + netstandard2.0;net472 true DotNetty.Codecs.Protobuf Protobuf Proto3 codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: Protobuf Proto3 codec en-US - 0.6.0 + 0.7.0 Microsoft $(NoWarn);CS1591 false @@ -22,7 +22,7 @@ true git https://github.com/Azure/DotNetty/ - 1.6.1 + 2.0.3 @@ -36,11 +36,4 @@ - - - - - - - \ No newline at end of file diff --git a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj index 3ed09b9c8..3ff1a6e8d 100644 --- a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj +++ b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj @@ -1,14 +1,14 @@  - netstandard1.3;net45 + netstandard2.0;net472 true DotNetty.Codecs.ProtocolBuffers ProtocolBuffers Proto2 codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: ProtocolBuffers Proto2 codec en-US - 0.6.0 + 0.7.0 Microsoft $(NoWarn);CS1591 false @@ -23,8 +23,7 @@ true git https://github.com/Azure/DotNetty/ - $(PackageTargetFallback);portable-net45+win8 - 1.6.1 + 2.0.3 @@ -38,12 +37,4 @@ - - - - - - - - \ No newline at end of file diff --git a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj index 2edf79522..203ca7100 100644 --- a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj +++ b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj @@ -1,13 +1,13 @@  - netstandard1.3;net45 + netstandard2.0;net472 true DotNetty.Codecs.Redis Redis codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: Redis codec en-US - 0.6.0 + 0.7.0 Microsoft $(NoWarn);CS1591 false @@ -22,7 +22,7 @@ true git https://github.com/Azure/DotNetty/ - 1.6.1 + 2.0.3 @@ -33,11 +33,4 @@ - - - - - - - \ No newline at end of file diff --git a/src/DotNetty.Codecs/DotNetty.Codecs.csproj b/src/DotNetty.Codecs/DotNetty.Codecs.csproj index 12a113965..4a8a5b2d4 100644 --- a/src/DotNetty.Codecs/DotNetty.Codecs.csproj +++ b/src/DotNetty.Codecs/DotNetty.Codecs.csproj @@ -1,13 +1,13 @@  - netstandard1.3;net45 + netstandard2.0;net472 true DotNetty.Codecs General purpose codecs for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: codecs en-US - 0.6.0 + 0.7.0 Microsoft $(NoWarn);CS1591 true @@ -24,7 +24,7 @@ true git https://github.com/Azure/DotNetty/ - 1.6.1 + 2.0.3 @@ -37,11 +37,4 @@ - - - - - - - \ No newline at end of file diff --git a/src/DotNetty.Common/DotNetty.Common.csproj b/src/DotNetty.Common/DotNetty.Common.csproj index c187ae363..0627ff11d 100644 --- a/src/DotNetty.Common/DotNetty.Common.csproj +++ b/src/DotNetty.Common/DotNetty.Common.csproj @@ -1,14 +1,14 @@  - netstandard1.3;net45 + netstandard2.0;net472 true DotNetty.Common DotNetty common routines © Microsoft Corporation. All rights reserved. DotNetty: common routines en-US - 0.6.0 + 0.7.0 Microsoft $(NoWarn);CS1591 True @@ -24,22 +24,13 @@ true git https://github.com/Azure/DotNetty/ - 1.6.1 + 2.0.3 - - - - - - - - - - - + + \ No newline at end of file diff --git a/src/DotNetty.Handlers/DotNetty.Handlers.csproj b/src/DotNetty.Handlers/DotNetty.Handlers.csproj index d9afdf486..d755ec7c4 100644 --- a/src/DotNetty.Handlers/DotNetty.Handlers.csproj +++ b/src/DotNetty.Handlers/DotNetty.Handlers.csproj @@ -1,14 +1,14 @@  - netstandard1.3;net45 + netstandard2.0;net472 true DotNetty.Handlers Application handlers for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: handlers en-US - 0.6.0 + 0.7.0 Microsoft $(NoWarn);CS1591 false @@ -23,7 +23,7 @@ true git https://github.com/Azure/DotNetty/ - 1.6.1 + 2.0.3 @@ -34,13 +34,4 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/DotNetty.Handlers/Tls/SniHandler.cs b/src/DotNetty.Handlers/Tls/SniHandler.cs index 0e2bb8276..4f7b48827 100644 --- a/src/DotNetty.Handlers/Tls/SniHandler.cs +++ b/src/DotNetty.Handlers/Tls/SniHandler.cs @@ -214,7 +214,7 @@ protected override void Decode(IChannelHandlerContext context, IByteBuffer input }; hostname = idn.GetAscii(hostname); -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 // TODO: netcore does not have culture sensitive tolower() hostname = hostname.ToLowerInvariant(); #else diff --git a/src/DotNetty.Handlers/Tls/TlsHandler.cs b/src/DotNetty.Handlers/Tls/TlsHandler.cs index 063aa2db9..e46d8c32f 100644 --- a/src/DotNetty.Handlers/Tls/TlsHandler.cs +++ b/src/DotNetty.Handlers/Tls/TlsHandler.cs @@ -674,7 +674,7 @@ sealed class MediationStream : Stream int inputLength; TaskCompletionSource readCompletionSource; ArraySegment sslOwnedBuffer; -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 int readByteCount; #else SynchronousAsyncResult syncReadResult; @@ -718,7 +718,7 @@ public void ExpandSource(int count) } this.sslOwnedBuffer = default(ArraySegment); -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 this.readByteCount = this.ReadFromInput(sslBuffer.Array, sslBuffer.Offset, sslBuffer.Count); // hack: this tricks SslStream's continuation to run synchronously instead of dispatching to TP. Remove once Begin/EndRead are available. new Task( @@ -744,7 +744,7 @@ public void ExpandSource(int count) #endif } -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { if (this.SourceReadableBytes > 0) @@ -817,7 +817,7 @@ IAsyncResult PrepareSyncReadResult(int readBytes, object state) public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) => this.owner.FinishWrapNonAppDataAsync(buffer, offset, count); -#if !NETSTANDARD1_3 +#if !NETSTANDARD2_0 static readonly Action WriteCompleteCallback = HandleChannelWriteComplete; public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) diff --git a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj index 600591ca9..41fbf1426 100644 --- a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj +++ b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj @@ -1,14 +1,14 @@  - netstandard1.3;net45 + netstandard2.0;net472 true DotNetty.Transport.Libuv Libuv transport model in DotNetty © Microsoft Corporation. All rights reserved. DotNetty: libuv transport model Experimental en-US - 0.6.0 + 0.7.0 Microsoft $(NoWarn);CS1591 True @@ -24,7 +24,7 @@ true git https://github.com/Azure/DotNetty/ - 1.6.1 + 2.0.3 @@ -39,11 +39,5 @@ - - - - - - \ No newline at end of file diff --git a/src/DotNetty.Transport.Libuv/Native/NativeMethods.cs b/src/DotNetty.Transport.Libuv/Native/NativeMethods.cs index 29311dc75..73d437b30 100644 --- a/src/DotNetty.Transport.Libuv/Native/NativeMethods.cs +++ b/src/DotNetty.Transport.Libuv/Native/NativeMethods.cs @@ -331,7 +331,7 @@ internal static IPEndPoint TcpGetSocketName(IntPtr handle) { Debug.Assert(handle != IntPtr.Zero); -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 int namelen = Marshal.SizeOf(); #else int namelen = Marshal.SizeOf(typeof(sockaddr)); @@ -344,7 +344,7 @@ internal static IPEndPoint TcpGetPeerName(IntPtr handle) { Debug.Assert(handle != IntPtr.Zero); -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 int namelen = Marshal.SizeOf(); #else int namelen = Marshal.SizeOf(typeof(sockaddr)); @@ -354,7 +354,7 @@ internal static IPEndPoint TcpGetPeerName(IntPtr handle) return sockaddr.GetIPEndPoint(); } -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 internal static IntPtr Allocate(int size) => Marshal.AllocCoTaskMem(size); internal static void FreeMemory(IntPtr ptr) => Marshal.FreeCoTaskMem(ptr); diff --git a/src/DotNetty.Transport.Libuv/Native/WindowsApi.cs b/src/DotNetty.Transport.Libuv/Native/WindowsApi.cs index 1526ab494..12b4307b9 100644 --- a/src/DotNetty.Transport.Libuv/Native/WindowsApi.cs +++ b/src/DotNetty.Transport.Libuv/Native/WindowsApi.cs @@ -41,7 +41,7 @@ public void DetachFromIOCP(NativeHandle handle) IntPtr socket = IntPtr.Zero; NativeMethods.uv_fileno(handle.Handle, ref socket); -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 uint len = (uint)Marshal.SizeOf(); #else uint len = (uint)Marshal.SizeOf(typeof(FILE_COMPLETION_INFORMATION)); diff --git a/src/DotNetty.Transport.Libuv/Native/WriteRequest.cs b/src/DotNetty.Transport.Libuv/Native/WriteRequest.cs index f0da3c1fc..169e68d65 100644 --- a/src/DotNetty.Transport.Libuv/Native/WriteRequest.cs +++ b/src/DotNetty.Transport.Libuv/Native/WriteRequest.cs @@ -26,7 +26,7 @@ sealed class WriteRequest : NativeRequest, ChannelOutboundBuffer.IMessageProcess static WriteRequest() { -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 BufferSize = Marshal.SizeOf(); #else BufferSize = Marshal.SizeOf(typeof(uv_buf_t)); diff --git a/src/DotNetty.Transport/Channels/Sockets/AbstractSocketByteChannel.cs b/src/DotNetty.Transport/Channels/Sockets/AbstractSocketByteChannel.cs index a6b7654ba..e297a8b08 100644 --- a/src/DotNetty.Transport/Channels/Sockets/AbstractSocketByteChannel.cs +++ b/src/DotNetty.Transport/Channels/Sockets/AbstractSocketByteChannel.cs @@ -154,7 +154,7 @@ protected override void ScheduleSocketRead() { SocketChannelAsyncOperation operation = this.ReadOperation; bool pending; -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 pending = this.Socket.ReceiveAsync(operation); #else if (ExecutionContext.IsFlowSuppressed()) @@ -308,7 +308,7 @@ protected bool IncompleteWrite(bool scheduleAsync, SocketChannelAsyncOperation o this.SetState(StateFlags.WriteScheduled); bool pending; -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 pending = this.Socket.SendAsync(operation); #else if (ExecutionContext.IsFlowSuppressed()) diff --git a/src/DotNetty.Transport/Channels/Sockets/SocketDatagramChannel.cs b/src/DotNetty.Transport/Channels/Sockets/SocketDatagramChannel.cs index 6431db8fe..4696a4ab2 100644 --- a/src/DotNetty.Transport/Channels/Sockets/SocketDatagramChannel.cs +++ b/src/DotNetty.Transport/Channels/Sockets/SocketDatagramChannel.cs @@ -115,7 +115,7 @@ protected override void ScheduleSocketRead() operation.SetBuffer(bytes.Array, bytes.Offset, bytes.Count); bool pending; -#if NETSTANDARD1_3 +#if NETSTANDARD2_0 pending = this.Socket.ReceiveFromAsync(operation); #else if (ExecutionContext.IsFlowSuppressed()) diff --git a/src/DotNetty.Transport/DotNetty.Transport.csproj b/src/DotNetty.Transport/DotNetty.Transport.csproj index 3cb33d768..e9b1687be 100644 --- a/src/DotNetty.Transport/DotNetty.Transport.csproj +++ b/src/DotNetty.Transport/DotNetty.Transport.csproj @@ -1,14 +1,14 @@  - netstandard1.3;net45 + netstandard2.0;net472 true DotNetty.Transport Transport model in DotNetty © Microsoft Corporation. All rights reserved. DotNetty: transport model en-US - 0.6.0 + 0.7.0 Microsoft $(NoWarn);CS1591 false @@ -23,7 +23,7 @@ true git https://github.com/Azure/DotNetty/ - 1.6.1 + 2.0.3 @@ -32,19 +32,4 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/shared/SharedAssemblyInfo.cs b/src/shared/SharedAssemblyInfo.cs index d26bd3b76..37003f66d 100644 --- a/src/shared/SharedAssemblyInfo.cs +++ b/src/shared/SharedAssemblyInfo.cs @@ -7,7 +7,7 @@ [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("DotNetty")] -[assembly: AssemblyVersion("0.6.0")] -[assembly: AssemblyFileVersion("0.6.0")] +[assembly: AssemblyVersion("0.7.0")] +[assembly: AssemblyFileVersion("0.7.0")] [assembly: AssemblyCopyright("(c) Microsoft 2015 - 2018")] diff --git a/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj b/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj index d5cf91256..94e38d7a6 100644 --- a/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj +++ b/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj @@ -1,13 +1,13 @@  true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + diff --git a/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj b/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj index faf18d82c..82dcbc4d9 100644 --- a/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj +++ b/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj @@ -1,13 +1,13 @@  true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + diff --git a/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj b/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj index 9cdc23b6e..f14e1e5e7 100644 --- a/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj +++ b/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj @@ -1,13 +1,13 @@  true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + diff --git a/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj b/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj index 5c50839cf..4a32e857b 100644 --- a/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj +++ b/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj @@ -1,13 +1,13 @@  true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + diff --git a/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj b/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj index e83990edb..58d563787 100644 --- a/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj +++ b/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj @@ -1,11 +1,11 @@  true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false - + diff --git a/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj b/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj index 61258cda7..f42b68f15 100644 --- a/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj +++ b/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj @@ -1,13 +1,13 @@  true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + diff --git a/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj b/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj index f69fb7b7d..ac979f577 100644 --- a/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj +++ b/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj @@ -1,13 +1,13 @@  true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + diff --git a/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj b/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj index 3570fb1f7..b6cef6261 100644 --- a/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj +++ b/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj @@ -1,13 +1,13 @@  true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + diff --git a/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj b/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj index b8b4e9a40..0a67729c2 100644 --- a/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj +++ b/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj @@ -1,13 +1,13 @@  true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + diff --git a/test/DotNetty.Microbench/Allocators/AbstractByteBufferAllocatorBenchmark.cs b/test/DotNetty.Microbench/Allocators/AbstractByteBufferAllocatorBenchmark.cs index b7acc058d..88dacb88d 100644 --- a/test/DotNetty.Microbench/Allocators/AbstractByteBufferAllocatorBenchmark.cs +++ b/test/DotNetty.Microbench/Allocators/AbstractByteBufferAllocatorBenchmark.cs @@ -5,11 +5,13 @@ namespace DotNetty.Microbench.Allocators { using System; using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; + using BenchmarkDotNet.Jobs; + // using BenchmarkDotNet.Attributes.Jobs; using DotNetty.Buffers; using DotNetty.Common; - [CoreJob] + // [CoreJob] + [SimpleJob(RuntimeMoniker.NetCoreApp31)] [BenchmarkCategory("ByteBufferAllocator")] [MemoryDiagnoser] public abstract class AbstractByteBufferAllocatorBenchmark diff --git a/test/DotNetty.Microbench/Buffers/ByteBufUtilBenchmark.cs b/test/DotNetty.Microbench/Buffers/ByteBufUtilBenchmark.cs index ae612e74f..6bceb78fd 100644 --- a/test/DotNetty.Microbench/Buffers/ByteBufUtilBenchmark.cs +++ b/test/DotNetty.Microbench/Buffers/ByteBufUtilBenchmark.cs @@ -5,7 +5,6 @@ namespace DotNetty.Microbench.Buffers { using System.Text; using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; using DotNetty.Buffers; using DotNetty.Common; diff --git a/test/DotNetty.Microbench/Buffers/ByteBufferBenchmark.cs b/test/DotNetty.Microbench/Buffers/ByteBufferBenchmark.cs index fc181a654..861c5f62e 100644 --- a/test/DotNetty.Microbench/Buffers/ByteBufferBenchmark.cs +++ b/test/DotNetty.Microbench/Buffers/ByteBufferBenchmark.cs @@ -5,18 +5,19 @@ namespace DotNetty.Microbench.Buffers { using System; using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; + using BenchmarkDotNet.Diagnostics.Windows.Configs; + using BenchmarkDotNet.Jobs; using DotNetty.Buffers; using DotNetty.Common; #if NET46 using BenchmarkDotNet.Diagnostics.Windows.Configs; #endif -#if !NET46 - [CoreJob] +#if !NET472 + [SimpleJob(RuntimeMoniker.NetCoreApp31)] #else - [ClrJob] - [InliningDiagnoser] + [SimpleJob(RuntimeMoniker.Net472)] + [InliningDiagnoser(true, true)] #endif [BenchmarkCategory("ByteBuffer")] public class ByteBufferBenchmark diff --git a/test/DotNetty.Microbench/Buffers/PooledByteBufferBenchmark.cs b/test/DotNetty.Microbench/Buffers/PooledByteBufferBenchmark.cs index 5edecf7f8..9707d7908 100644 --- a/test/DotNetty.Microbench/Buffers/PooledByteBufferBenchmark.cs +++ b/test/DotNetty.Microbench/Buffers/PooledByteBufferBenchmark.cs @@ -4,18 +4,19 @@ namespace DotNetty.Microbench.Buffers { using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; + using BenchmarkDotNet.Diagnostics.Windows.Configs; + using BenchmarkDotNet.Jobs; using DotNetty.Buffers; using DotNetty.Common; -#if NET46 +#if NET472 using BenchmarkDotNet.Diagnostics.Windows.Configs; #endif -#if !NET46 - [CoreJob] +#if !NET472 + [SimpleJob(RuntimeMoniker.NetCoreApp31)] #else - [ClrJob] - [InliningDiagnoser] + [SimpleJob(RuntimeMoniker.Net472)] + [InliningDiagnoser(true, true)] #endif [BenchmarkCategory("ByteBuffer")] public class PooledByteBufferBenchmark diff --git a/test/DotNetty.Microbench/Buffers/UnpooledByteBufferBenchmark.cs b/test/DotNetty.Microbench/Buffers/UnpooledByteBufferBenchmark.cs index 68d0f520e..dee347e17 100644 --- a/test/DotNetty.Microbench/Buffers/UnpooledByteBufferBenchmark.cs +++ b/test/DotNetty.Microbench/Buffers/UnpooledByteBufferBenchmark.cs @@ -4,18 +4,18 @@ namespace DotNetty.Microbench.Buffers { using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; + using BenchmarkDotNet.Jobs; using DotNetty.Buffers; using DotNetty.Common; -#if NET46 +#if NET472 using BenchmarkDotNet.Diagnostics.Windows.Configs; #endif -#if !NET46 - [CoreJob] +#if !NET472 + [SimpleJob(RuntimeMoniker.NetCoreApp31)] #else - [ClrJob] - [InliningDiagnoser] + [SimpleJob(RuntimeMoniker.Net472)] + [InliningDiagnoser(true, true)] #endif [BenchmarkCategory("ByteBuffer")] public class UnpooledByteBufferBenchmark diff --git a/test/DotNetty.Microbench/Codecs/DateFormatterBenchmark.cs b/test/DotNetty.Microbench/Codecs/DateFormatterBenchmark.cs index 615e73c7e..c7ea47d0b 100644 --- a/test/DotNetty.Microbench/Codecs/DateFormatterBenchmark.cs +++ b/test/DotNetty.Microbench/Codecs/DateFormatterBenchmark.cs @@ -5,10 +5,10 @@ namespace DotNetty.Microbench.Codecs { using System; using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; + using BenchmarkDotNet.Jobs; using DotNetty.Codecs; - [CoreJob] + [SimpleJob(RuntimeMoniker.NetCoreApp31)] [BenchmarkCategory("Codecs")] public class DateFormatterBenchmark { diff --git a/test/DotNetty.Microbench/Common/AsciiStringBenchmark.cs b/test/DotNetty.Microbench/Common/AsciiStringBenchmark.cs index bad2dcf71..e84615f4b 100644 --- a/test/DotNetty.Microbench/Common/AsciiStringBenchmark.cs +++ b/test/DotNetty.Microbench/Common/AsciiStringBenchmark.cs @@ -6,18 +6,18 @@ namespace DotNetty.Microbench.Common using System; using System.Text; using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; + using BenchmarkDotNet.Jobs; using DotNetty.Common.Internal; using DotNetty.Common.Utilities; -#if NET46 +#if NET472 using BenchmarkDotNet.Diagnostics.Windows.Configs; #endif -#if !NET46 - [CoreJob] +#if !NET472 + [SimpleJob(RuntimeMoniker.NetCoreApp31)] #else - [ClrJob] - [InliningDiagnoser] + [SimpleJob(RuntimeMoniker.Net472)] + [InliningDiagnoser(true, true)] #endif [BenchmarkCategory("Common")] public class AsciiStringBenchmark diff --git a/test/DotNetty.Microbench/Concurrency/FastThreadLocalBenchmark.cs b/test/DotNetty.Microbench/Concurrency/FastThreadLocalBenchmark.cs index a948486bd..870f6e142 100644 --- a/test/DotNetty.Microbench/Concurrency/FastThreadLocalBenchmark.cs +++ b/test/DotNetty.Microbench/Concurrency/FastThreadLocalBenchmark.cs @@ -4,10 +4,10 @@ namespace DotNetty.Microbench.Concurrency { using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; + using BenchmarkDotNet.Jobs; using DotNetty.Common; - [CoreJob] + [SimpleJob(RuntimeMoniker.NetCoreApp31)] [BenchmarkCategory("Concurrency")] public class FastThreadLocalBenchmark { diff --git a/test/DotNetty.Microbench/Concurrency/SingleThreadEventExecutorBenchmark.cs b/test/DotNetty.Microbench/Concurrency/SingleThreadEventExecutorBenchmark.cs index 0eef5e13f..8c6f0384e 100644 --- a/test/DotNetty.Microbench/Concurrency/SingleThreadEventExecutorBenchmark.cs +++ b/test/DotNetty.Microbench/Concurrency/SingleThreadEventExecutorBenchmark.cs @@ -6,7 +6,6 @@ namespace DotNetty.Microbench.Concurrency using System; using System.Threading; using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; using BenchmarkDotNet.Engines; using DotNetty.Common.Concurrency; using DotNetty.Common.Internal; diff --git a/test/DotNetty.Microbench/DotNetty.Microbench.csproj b/test/DotNetty.Microbench/DotNetty.Microbench.csproj index 4f66aca53..8be7693c2 100644 --- a/test/DotNetty.Microbench/DotNetty.Microbench.csproj +++ b/test/DotNetty.Microbench/DotNetty.Microbench.csproj @@ -2,20 +2,18 @@ Exe true - netcoreapp2.0;net46 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + win-x64 - - - - - + + + diff --git a/test/DotNetty.Microbench/Headers/HeadersBenchmark.cs b/test/DotNetty.Microbench/Headers/HeadersBenchmark.cs index 305f96ba4..dd1b63307 100644 --- a/test/DotNetty.Microbench/Headers/HeadersBenchmark.cs +++ b/test/DotNetty.Microbench/Headers/HeadersBenchmark.cs @@ -5,7 +5,6 @@ namespace DotNetty.Microbench.Headers { using System.Collections.Generic; using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; using BenchmarkDotNet.Engines; using DotNetty.Codecs; using DotNetty.Codecs.Http; diff --git a/test/DotNetty.Microbench/Http/ClientCookieDecoderBenchmark.cs b/test/DotNetty.Microbench/Http/ClientCookieDecoderBenchmark.cs index b7f1a9b8d..8573b80c8 100644 --- a/test/DotNetty.Microbench/Http/ClientCookieDecoderBenchmark.cs +++ b/test/DotNetty.Microbench/Http/ClientCookieDecoderBenchmark.cs @@ -4,11 +4,11 @@ namespace DotNetty.Microbench.Http { using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; + using BenchmarkDotNet.Jobs; using DotNetty.Codecs.Http.Cookies; using DotNetty.Common; - [CoreJob] + [SimpleJob(RuntimeMoniker.NetCoreApp31)] [BenchmarkCategory("Http")] public class ClientCookieDecoderBenchmark { diff --git a/test/DotNetty.Microbench/Http/HttpRequestDecoderBenchmark.cs b/test/DotNetty.Microbench/Http/HttpRequestDecoderBenchmark.cs index bc7096690..ad1cc3375 100644 --- a/test/DotNetty.Microbench/Http/HttpRequestDecoderBenchmark.cs +++ b/test/DotNetty.Microbench/Http/HttpRequestDecoderBenchmark.cs @@ -5,7 +5,6 @@ namespace DotNetty.Microbench.Http { using System.Text; using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; using BenchmarkDotNet.Engines; using DotNetty.Buffers; using DotNetty.Codecs.Http; diff --git a/test/DotNetty.Microbench/Http/HttpRequestEncoderInsertBenchmark.cs b/test/DotNetty.Microbench/Http/HttpRequestEncoderInsertBenchmark.cs index f428c8999..2b10889f9 100644 --- a/test/DotNetty.Microbench/Http/HttpRequestEncoderInsertBenchmark.cs +++ b/test/DotNetty.Microbench/Http/HttpRequestEncoderInsertBenchmark.cs @@ -4,12 +4,12 @@ namespace DotNetty.Microbench.Http { using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; + using BenchmarkDotNet.Jobs; using DotNetty.Buffers; using DotNetty.Codecs.Http; using DotNetty.Common; - [CoreJob] + [SimpleJob(RuntimeMoniker.NetCoreApp31)] [BenchmarkCategory("Http")] public class HttpRequestEncoderInsertBenchmark { diff --git a/test/DotNetty.Microbench/Http/WriteBytesVsShortOrMediumBenchmark.cs b/test/DotNetty.Microbench/Http/WriteBytesVsShortOrMediumBenchmark.cs index ddb5a9194..c7146f4ac 100644 --- a/test/DotNetty.Microbench/Http/WriteBytesVsShortOrMediumBenchmark.cs +++ b/test/DotNetty.Microbench/Http/WriteBytesVsShortOrMediumBenchmark.cs @@ -4,13 +4,13 @@ namespace DotNetty.Microbench.Http { using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; + using BenchmarkDotNet.Jobs; using DotNetty.Buffers; using DotNetty.Codecs.Http; using DotNetty.Common; using DotNetty.Common.Utilities; - [CoreJob] + [SimpleJob(RuntimeMoniker.NetCoreApp31)] [BenchmarkCategory("Http")] public class WriteBytesVsShortOrMediumBenchmark { diff --git a/test/DotNetty.Microbench/Internal/PlatformDependentBenchmark.cs b/test/DotNetty.Microbench/Internal/PlatformDependentBenchmark.cs index 51292afb7..67a64795f 100644 --- a/test/DotNetty.Microbench/Internal/PlatformDependentBenchmark.cs +++ b/test/DotNetty.Microbench/Internal/PlatformDependentBenchmark.cs @@ -4,10 +4,11 @@ namespace DotNetty.Microbench.Internal { using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Attributes.Jobs; + using BenchmarkDotNet.Jobs; using DotNetty.Common.Internal; - [CoreJob] + // [CoreJob] + [SimpleJob(RuntimeMoniker.NetCoreApp31)] [BenchmarkCategory("Internal")] public class PlatformDependentBenchmark { diff --git a/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj b/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj index 9eb990247..946f21561 100644 --- a/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj +++ b/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj @@ -2,7 +2,7 @@ true false - netcoreapp2.0;net452 + netcoreapp3.1;net472 ../../DotNetty.snk true @@ -11,7 +11,7 @@ - + diff --git a/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj b/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj index dad82b080..c1a9f7130 100644 --- a/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj +++ b/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj @@ -1,13 +1,13 @@  true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + diff --git a/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj b/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj index 83ad08e13..1bad6c058 100644 --- a/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj +++ b/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj @@ -1,16 +1,16 @@ true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + win-x64 - + diff --git a/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj b/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj index d0126f46c..72cb185f7 100644 --- a/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj +++ b/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj @@ -4,14 +4,14 @@ true - net452 + net472 false library - + diff --git a/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj b/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj index 6151acd5a..b1909e485 100644 --- a/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj +++ b/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj @@ -1,13 +1,13 @@  true - netcoreapp2.0;net452 + netcoreapp3.1;net472 false ../../DotNetty.snk true - + From 05e5aa40c3b1078ee80d520f3516bed7ebf11520 Mon Sep 17 00:00:00 2001 From: Max Gortman Date: Fri, 16 Jul 2021 18:26:30 -0700 Subject: [PATCH 14/33] Remove XThread as obsolete --- src/DotNetty.Buffers/PoolThreadCache.cs | 2 +- .../Concurrency/AbstractEventExecutor.cs | 1 - .../Concurrency/IEventExecutor.cs | 4 +- .../Concurrency/SingleThreadEventExecutor.cs | 1 - src/DotNetty.Common/Concurrency/XThread.cs | 107 ------------------ src/DotNetty.Common/ThreadDeathWatcher.cs | 1 - src/DotNetty.Common/ThreadLocalPool.cs | 1 - .../Utilities/HashedWheelTimer.cs | 6 +- .../Utilities/ReferenceCountUtil.cs | 1 - .../Utilities/ThreadExtensions.cs | 1 - .../EventLoopGroup.cs | 2 +- src/DotNetty.Transport.Libuv/LoopExecutor.cs | 8 +- .../Channels/DefaultChannelPipeline.cs | 1 - .../Channels/Embedded/EmbeddedEventLoop.cs | 2 +- .../ThreadLocalPoolTest.cs | 7 +- 15 files changed, 14 insertions(+), 131 deletions(-) delete mode 100644 src/DotNetty.Common/Concurrency/XThread.cs diff --git a/src/DotNetty.Buffers/PoolThreadCache.cs b/src/DotNetty.Buffers/PoolThreadCache.cs index 5c8e1cc3d..5d2fd6cf4 100644 --- a/src/DotNetty.Buffers/PoolThreadCache.cs +++ b/src/DotNetty.Buffers/PoolThreadCache.cs @@ -6,10 +6,10 @@ namespace DotNetty.Buffers using System; using System.Diagnostics; using System.Diagnostics.Contracts; + using System.Threading; using DotNetty.Common; using DotNetty.Common.Internal; using DotNetty.Common.Internal.Logging; - using Thread = DotNetty.Common.Concurrency.XThread; /// /// Acts a Thread cache for allocations. This implementation is moduled after diff --git a/src/DotNetty.Common/Concurrency/AbstractEventExecutor.cs b/src/DotNetty.Common/Concurrency/AbstractEventExecutor.cs index 36a2ddd2e..29d3cdaa2 100644 --- a/src/DotNetty.Common/Concurrency/AbstractEventExecutor.cs +++ b/src/DotNetty.Common/Concurrency/AbstractEventExecutor.cs @@ -8,7 +8,6 @@ namespace DotNetty.Common.Concurrency using System.Threading; using System.Threading.Tasks; using DotNetty.Common.Internal.Logging; - using Thread = XThread; /// /// Abstract base class for implementations diff --git a/src/DotNetty.Common/Concurrency/IEventExecutor.cs b/src/DotNetty.Common/Concurrency/IEventExecutor.cs index 04fd893e2..185340f32 100644 --- a/src/DotNetty.Common/Concurrency/IEventExecutor.cs +++ b/src/DotNetty.Common/Concurrency/IEventExecutor.cs @@ -3,8 +3,8 @@ namespace DotNetty.Common.Concurrency { - using Thread = DotNetty.Common.Concurrency.XThread; - + using System.Threading; + public interface IEventExecutor : IEventExecutorGroup { /// diff --git a/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs b/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs index 225871962..4e9758fab 100644 --- a/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs +++ b/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs @@ -12,7 +12,6 @@ namespace DotNetty.Common.Concurrency using System.Threading.Tasks; using DotNetty.Common.Internal; using DotNetty.Common.Internal.Logging; - using Thread = XThread; /// /// backed by a single thread. diff --git a/src/DotNetty.Common/Concurrency/XThread.cs b/src/DotNetty.Common/Concurrency/XThread.cs deleted file mode 100644 index ec18d7122..000000000 --- a/src/DotNetty.Common/Concurrency/XThread.cs +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace DotNetty.Common.Concurrency -{ - using System; - using System.Diagnostics; - using System.Threading; - using System.Threading.Tasks; - - public delegate void XParameterizedThreadStart(object obj); - - [DebuggerDisplay("ID={threadId}, Name={Name}, IsExplicit={isExplicit}")] - public sealed class XThread - { - static int maxThreadId; - - [ThreadStatic] - static XThread currentThread; - - readonly int threadId; -#pragma warning disable CS0414 - readonly bool isExplicit; // For debugging only -#pragma warning restore CS0414 - Task task; - readonly EventWaitHandle completed = new EventWaitHandle(false, EventResetMode.AutoReset); - readonly EventWaitHandle readyToStart = new EventWaitHandle(false, EventResetMode.AutoReset); - object startupParameter; - - static int GetNewThreadId() => Interlocked.Increment(ref maxThreadId); - - XThread() - { - this.threadId = GetNewThreadId(); - this.isExplicit = false; - this.IsAlive = false; - } - - public XThread(Action action) - { - this.threadId = GetNewThreadId(); - this.isExplicit = true; - this.IsAlive = false; - this.CreateLongRunningTask(x => action()); - } - - public XThread(XParameterizedThreadStart threadStartFunc) - { - this.threadId = GetNewThreadId(); - this.isExplicit = true; - this.IsAlive = false; - this.CreateLongRunningTask(threadStartFunc); - } - - public void Start() - { - this.readyToStart.Set(); - this.IsAlive = true; - } - - void CreateLongRunningTask(XParameterizedThreadStart threadStartFunc) - { - this.task = Task.Factory.StartNew( - () => - { - // We start the task running, then unleash it by signaling the readyToStart event. - // This is needed to avoid thread reuse for tasks (see below) - this.readyToStart.WaitOne(); - // This is the first time we're using this thread, therefore the TLS slot must be empty - if (currentThread != null) - { - Debug.WriteLine("warning: currentThread already created; OS thread reused"); - Debug.Assert(false); - } - currentThread = this; - threadStartFunc(this.startupParameter); - this.completed.Set(); - }, - CancellationToken.None, - // .NET always creates a brand new thread for LongRunning tasks - // This is not documented but unlikely to ever change: - // https://github.com/dotnet/corefx/issues/2576#issuecomment-126693306 - TaskCreationOptions.LongRunning, - TaskScheduler.Default); - } - - public void Start(object parameter) - { - this.startupParameter = parameter; - this.Start(); - } - - public static void Sleep(int millisecondsTimeout) => Task.Delay(millisecondsTimeout).Wait(); - - public int Id => this.threadId; - - public string Name { get; set; } - - public bool IsAlive { get; private set; } - - public static XThread CurrentThread => currentThread ?? (currentThread = new XThread()); - - public bool Join(TimeSpan timeout) => this.completed.WaitOne(timeout); - - public bool Join(int millisecondsTimeout) => this.completed.WaitOne(millisecondsTimeout); - } -} \ No newline at end of file diff --git a/src/DotNetty.Common/ThreadDeathWatcher.cs b/src/DotNetty.Common/ThreadDeathWatcher.cs index c824c7e47..026decfb7 100644 --- a/src/DotNetty.Common/ThreadDeathWatcher.cs +++ b/src/DotNetty.Common/ThreadDeathWatcher.cs @@ -10,7 +10,6 @@ namespace DotNetty.Common using DotNetty.Common.Concurrency; using DotNetty.Common.Internal; using DotNetty.Common.Internal.Logging; - using Thread = DotNetty.Common.Concurrency.XThread; public static class ThreadDeathWatcher { diff --git a/src/DotNetty.Common/ThreadLocalPool.cs b/src/DotNetty.Common/ThreadLocalPool.cs index cbcc28290..327cb15e9 100644 --- a/src/DotNetty.Common/ThreadLocalPool.cs +++ b/src/DotNetty.Common/ThreadLocalPool.cs @@ -10,7 +10,6 @@ namespace DotNetty.Common using System.Diagnostics.Contracts; using System.Runtime.CompilerServices; using System.Threading; - using Thread = DotNetty.Common.Concurrency.XThread; public class ThreadLocalPool { diff --git a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs index af96b56c6..1ccd1c23b 100644 --- a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs +++ b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs @@ -27,7 +27,7 @@ public sealed class HashedWheelTimer : ITimer const int InstanceCountLimit = 64; readonly Worker worker; - readonly XThread workerThread; + readonly Thread workerThread; readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); const int WorkerStateInit = 0; @@ -98,7 +98,7 @@ public HashedWheelTimer( tickInterval, long.MaxValue / this.wheel.Length)); } - this.workerThread = new XThread(st => this.worker.Run()); + this.workerThread = new Thread(st => this.worker.Run()); this.maxPendingTimeouts = maxPendingTimeouts; @@ -187,7 +187,7 @@ public async Task> StopAsync() { GC.SuppressFinalize(this); - if (XThread.CurrentThread == this.workerThread) + if (Thread.CurrentThread == this.workerThread) { throw new InvalidOperationException($"{nameof(HashedWheelTimer)}.stop() cannot be called from timer task."); } diff --git a/src/DotNetty.Common/Utilities/ReferenceCountUtil.cs b/src/DotNetty.Common/Utilities/ReferenceCountUtil.cs index 86bf433a1..2f453a0e6 100644 --- a/src/DotNetty.Common/Utilities/ReferenceCountUtil.cs +++ b/src/DotNetty.Common/Utilities/ReferenceCountUtil.cs @@ -6,7 +6,6 @@ namespace DotNetty.Common.Utilities using System; using System.Threading; using DotNetty.Common.Internal.Logging; - using Thread = DotNetty.Common.Concurrency.XThread; public static class ReferenceCountUtil { diff --git a/src/DotNetty.Common/Utilities/ThreadExtensions.cs b/src/DotNetty.Common/Utilities/ThreadExtensions.cs index 7f9431a74..d39dcf237 100644 --- a/src/DotNetty.Common/Utilities/ThreadExtensions.cs +++ b/src/DotNetty.Common/Utilities/ThreadExtensions.cs @@ -6,7 +6,6 @@ namespace DotNetty.Common.Utilities using System; using System.Diagnostics.Contracts; using System.Threading; - using Thread = DotNetty.Common.Concurrency.XThread; public static class ThreadExtensions { diff --git a/src/DotNetty.Transport.Libuv/EventLoopGroup.cs b/src/DotNetty.Transport.Libuv/EventLoopGroup.cs index d58e8bded..c82f3c670 100644 --- a/src/DotNetty.Transport.Libuv/EventLoopGroup.cs +++ b/src/DotNetty.Transport.Libuv/EventLoopGroup.cs @@ -74,7 +74,7 @@ public EventLoopGroup(int eventLoopCount) public override IEventExecutor GetNext() { // Attempt to select event loop based on thread first - int threadId = XThread.CurrentThread.Id; + int threadId = Thread.CurrentThread.ManagedThreadId; int i; for (i = 0; i < this.eventLoops.Length; i++) { diff --git a/src/DotNetty.Transport.Libuv/LoopExecutor.cs b/src/DotNetty.Transport.Libuv/LoopExecutor.cs index 373624c37..3eef653e8 100644 --- a/src/DotNetty.Transport.Libuv/LoopExecutor.cs +++ b/src/DotNetty.Transport.Libuv/LoopExecutor.cs @@ -36,7 +36,7 @@ class LoopExecutor : AbstractScheduledEventExecutor readonly ThreadLocalPool writeRequestPool = new ThreadLocalPool(handle => new WriteRequest(handle)); readonly long preciseBreakoutInterval; readonly IQueue taskQueue; - readonly XThread thread; + readonly Thread thread; readonly TaskScheduler scheduler; readonly ManualResetEventSlim loopRunStart; readonly TaskCompletionSource terminationCompletionSource; @@ -80,7 +80,7 @@ public LoopExecutor(IEventLoopGroup parent, string threadName, TimeSpan breakout { name = $"{name}({threadName})"; } - this.thread = new XThread(Run) { Name = name }; + this.thread = new Thread(Run) { Name = name }; this.loopRunStart = new ManualResetEventSlim(false, 1); } @@ -97,7 +97,7 @@ protected void Start() internal Loop UnsafeLoop => this.loop; - internal int LoopThreadId => this.thread.Id; + internal int LoopThreadId => this.thread.ManagedThreadId; static void Run(object state) { @@ -424,7 +424,7 @@ static IRunnable PollTaskFrom(IQueue taskQueue) => public override bool IsTerminated => this.executionState == TerminatedState; - public override bool IsInEventLoop(XThread t) => this.thread == t; + public override bool IsInEventLoop(Thread t) => this.thread == t; void WakeUp(bool inEventLoop) { diff --git a/src/DotNetty.Transport/Channels/DefaultChannelPipeline.cs b/src/DotNetty.Transport/Channels/DefaultChannelPipeline.cs index 1531f5676..1390b7a01 100644 --- a/src/DotNetty.Transport/Channels/DefaultChannelPipeline.cs +++ b/src/DotNetty.Transport/Channels/DefaultChannelPipeline.cs @@ -16,7 +16,6 @@ namespace DotNetty.Transport.Channels using DotNetty.Common.Concurrency; using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; - using Thread = DotNetty.Common.Concurrency.XThread; public class DefaultChannelPipeline : IChannelPipeline { diff --git a/src/DotNetty.Transport/Channels/Embedded/EmbeddedEventLoop.cs b/src/DotNetty.Transport/Channels/Embedded/EmbeddedEventLoop.cs index 6e5b0f557..8f2fa3b1f 100644 --- a/src/DotNetty.Transport/Channels/Embedded/EmbeddedEventLoop.cs +++ b/src/DotNetty.Transport/Channels/Embedded/EmbeddedEventLoop.cs @@ -5,10 +5,10 @@ namespace DotNetty.Transport.Channels.Embedded { using System; using System.Collections.Generic; + using System.Threading; using System.Threading.Tasks; using DotNetty.Common; using DotNetty.Common.Concurrency; - using Thread = DotNetty.Common.Concurrency.XThread; sealed class EmbeddedEventLoop : AbstractScheduledEventExecutor, IEventLoop { diff --git a/test/DotNetty.Common.Tests/ThreadLocalPoolTest.cs b/test/DotNetty.Common.Tests/ThreadLocalPoolTest.cs index ace0d40bb..a0ebeb182 100644 --- a/test/DotNetty.Common.Tests/ThreadLocalPoolTest.cs +++ b/test/DotNetty.Common.Tests/ThreadLocalPoolTest.cs @@ -23,14 +23,13 @@ public void ThreadCanBeCollectedEvenIfHandledObjectIsReferencedTest() ThreadLocalPool pool = NewPool(1024); HandledObject reference = null; WeakReference threadRef = null; - WeakReference xThreadRef = null; var thread1 = new Thread(() => { //Don't know the reason, but thread2 will not be collected without wrapped with thread1 var thread2 = new Thread(() => { - Volatile.Write(ref xThreadRef, new WeakReference(XThread.CurrentThread)); + Volatile.Write(ref threadRef, new WeakReference(Thread.CurrentThread)); HandledObject data = pool.Take(); // Store a reference to the HandledObject to ensure it is not collected when the run method finish. Volatile.Write(ref reference, data); @@ -39,7 +38,6 @@ public void ThreadCanBeCollectedEvenIfHandledObjectIsReferencedTest() thread2.Start(); thread2.Join(); Assert.True(Volatile.Read(ref threadRef)?.TryGetTarget(out _)); - Assert.True(Volatile.Read(ref xThreadRef)?.TryGetTarget(out _)); GC.KeepAlive(thread2); // Null out so it can be collected. @@ -53,12 +51,11 @@ public void ThreadCanBeCollectedEvenIfHandledObjectIsReferencedTest() GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true); GC.WaitForPendingFinalizers(); - if (Volatile.Read(ref threadRef)?.TryGetTarget(out _) == true || Volatile.Read(ref xThreadRef)?.TryGetTarget(out _) == true) + if (Volatile.Read(ref threadRef)?.TryGetTarget(out _) == true || Volatile.Read(ref threadRef)?.TryGetTarget(out _) == true) Thread.Sleep(100); } Assert.False(Volatile.Read(ref threadRef)?.TryGetTarget(out _)); - Assert.False(Volatile.Read(ref xThreadRef)?.TryGetTarget(out _)); // Now call recycle after the Thread was collected to ensure this still works... reference.Release(); From 7d1017c071ba926e4685a42efa3f376656cd70d4 Mon Sep 17 00:00:00 2001 From: Max Gortman Date: Fri, 16 Jul 2021 20:33:28 -0700 Subject: [PATCH 15/33] refreshing build --- appveyor.yaml => appveyor.yml | 6 +++--- build.cake | 8 ++++---- build.ps1 | 2 +- src/shared/SharedAssemblyInfo.cs | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) rename appveyor.yaml => appveyor.yml (76%) diff --git a/appveyor.yaml b/appveyor.yml similarity index 76% rename from appveyor.yaml rename to appveyor.yml index c481be338..b3954a098 100644 --- a/appveyor.yaml +++ b/appveyor.yml @@ -1,9 +1,9 @@ -version: 0.4.{build} -image: Visual Studio 2017 RC +version: 0.7.0.{build} pull_requests: do_not_increment_build_number: true +image: Visual Studio 2019 build_script: -- cmd: powershell .\build.ps1 --target=PR +- cmd: powershell .\build.ps1 -target PR test: off deploy: off notifications: diff --git a/build.cake b/build.cake index acc9db369..92448f42b 100644 --- a/build.cake +++ b/build.cake @@ -23,8 +23,8 @@ var csProjectFiles = GetFiles("./src/**/*.csproj"); var nuget = Directory("tools"); var output = Directory("build"); var outputBinaries = output + Directory("binaries"); -var outputBinariesNet45 = outputBinaries + Directory("net45"); -var outputBinariesNetstandard = outputBinaries + Directory("netstandard1.3"); +var outputBinariesNet = outputBinaries + Directory("net472"); +var outputBinariesNetStandard = outputBinaries + Directory("netstandard2.0"); var outputPackages = output + Directory("packages"); var outputNuGet = output + Directory("nuget"); var outputPerfResults = Directory("perfResults"); @@ -37,7 +37,7 @@ Task("Clean") // Clean artifact directories. CleanDirectories(new DirectoryPath[] { output, outputBinaries, outputPackages, outputNuGet, - outputBinariesNet45, outputBinariesNetstandard + outputBinariesNet, outputBinariesNetStandard }); if(!skipClean) { @@ -311,7 +311,7 @@ Task("Mono") Task("PR") //.IsDependentOn("Update-Version") .IsDependentOn("Test") - .IsDependentOn("Benchmark") + //.IsDependentOn("Benchmark") .IsDependentOn("Package-NuGet"); Task("Nightly") diff --git a/build.ps1 b/build.ps1 index 7b1628aaf..291b9efdc 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ Param( $CakeVersion = "0.27.1" $DotNetChannel = "Current"; -$DotNetVersion = "2.1.101"; +$DotNetVersion = "3.1.411"; $DotNetInstallerUri = "https://dot.net/v1/dotnet-install.ps1"; $NugetUrl = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" # Temporarily skip verification of addins. diff --git a/src/shared/SharedAssemblyInfo.cs b/src/shared/SharedAssemblyInfo.cs index 37003f66d..4e6c470d8 100644 --- a/src/shared/SharedAssemblyInfo.cs +++ b/src/shared/SharedAssemblyInfo.cs @@ -9,5 +9,5 @@ [assembly: AssemblyProduct("DotNetty")] [assembly: AssemblyVersion("0.7.0")] [assembly: AssemblyFileVersion("0.7.0")] -[assembly: AssemblyCopyright("(c) Microsoft 2015 - 2018")] +[assembly: AssemblyCopyright("(c) Microsoft 2015 - 2021")] From d60a1d44a83ccc3ca3199e7cc687d8c7b980e572 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?James=20Davis=20=E2=9B=BA=EF=B8=8F=F0=9F=8F=94?= Date: Tue, 30 Nov 2021 13:11:13 -0700 Subject: [PATCH 16/33] Make thread executor a background thread. --- src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs b/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs index 4e9758fab..d1f690516 100644 --- a/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs +++ b/src/DotNetty.Common/Concurrency/SingleThreadEventExecutor.cs @@ -78,6 +78,7 @@ protected SingleThreadEventExecutor(IEventExecutorGroup parent, string threadNam { this.thread.Name = threadName; } + this.thread.IsBackground = true; this.thread.Start(); } From 4c4adebce921303946e00451cb24a17f5367a11b Mon Sep 17 00:00:00 2001 From: Max Gortman Date: Wed, 15 Dec 2021 14:24:55 -0800 Subject: [PATCH 17/33] up version to 0.7.1 --- RELEASE_NOTES.md | 9 ++++++--- src/DotNetty.Buffers/DotNetty.Buffers.csproj | 2 +- src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj | 2 +- src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj | 2 +- .../DotNetty.Codecs.Protobuf.csproj | 2 +- .../DotNetty.Codecs.ProtocolBuffers.csproj | 2 +- src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj | 2 +- src/DotNetty.Codecs/DotNetty.Codecs.csproj | 2 +- src/DotNetty.Common/DotNetty.Common.csproj | 2 +- src/DotNetty.Handlers/DotNetty.Handlers.csproj | 2 +- .../DotNetty.Transport.Libuv.csproj | 2 +- src/DotNetty.Transport/DotNetty.Transport.csproj | 2 +- src/shared/SharedAssemblyInfo.cs | 4 ++-- 13 files changed, 19 insertions(+), 16 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index fee9a0bf2..6d820b8a7 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,10 @@ +#### 0.7.1 December 15, 2021 +- Revert to use background threads + #### 0.7.0 June 11, 2021 -- target net472 and netstandard2.0 -- microsoft.extensions.logging 5.0.0 -- microsoft.extensions.configuration 5.0.0 +- Target net472 and netstandard2.0 +- Microsoft.Extensions.Logging 5.0.0 +- Microsoft.Extensions.Configuration 5.0.0 #### 0.6.0 October 9, 2018 - Clearly marks Unsafe Buffer management routines as `unsafe` diff --git a/src/DotNetty.Buffers/DotNetty.Buffers.csproj b/src/DotNetty.Buffers/DotNetty.Buffers.csproj index a48ae7618..f6f56a8cf 100644 --- a/src/DotNetty.Buffers/DotNetty.Buffers.csproj +++ b/src/DotNetty.Buffers/DotNetty.Buffers.csproj @@ -6,7 +6,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: buffer management en-US - 0.7.0 + 0.7.1 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj index c1833227d..6338ce062 100644 --- a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj +++ b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Http codec en-US - 0.7.0 + 0.7.1 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj index e851eefec..563e9726a 100644 --- a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj +++ b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: MQTT codec en-US - 0.7.0 + 0.7.1 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj index 8e02867e9..7f60d2499 100644 --- a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj +++ b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Protobuf Proto3 codec en-US - 0.7.0 + 0.7.1 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj index 3ff1a6e8d..e03592e22 100644 --- a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj +++ b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: ProtocolBuffers Proto2 codec en-US - 0.7.0 + 0.7.1 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj index 203ca7100..5b4c8b2fd 100644 --- a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj +++ b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Redis codec en-US - 0.7.0 + 0.7.1 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs/DotNetty.Codecs.csproj b/src/DotNetty.Codecs/DotNetty.Codecs.csproj index 4a8a5b2d4..372a703f3 100644 --- a/src/DotNetty.Codecs/DotNetty.Codecs.csproj +++ b/src/DotNetty.Codecs/DotNetty.Codecs.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: codecs en-US - 0.7.0 + 0.7.1 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Common/DotNetty.Common.csproj b/src/DotNetty.Common/DotNetty.Common.csproj index 0627ff11d..5640fc467 100644 --- a/src/DotNetty.Common/DotNetty.Common.csproj +++ b/src/DotNetty.Common/DotNetty.Common.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: common routines en-US - 0.7.0 + 0.7.1 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Handlers/DotNetty.Handlers.csproj b/src/DotNetty.Handlers/DotNetty.Handlers.csproj index d755ec7c4..e44929f4b 100644 --- a/src/DotNetty.Handlers/DotNetty.Handlers.csproj +++ b/src/DotNetty.Handlers/DotNetty.Handlers.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: handlers en-US - 0.7.0 + 0.7.1 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj index 41fbf1426..172507379 100644 --- a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj +++ b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: libuv transport model Experimental en-US - 0.7.0 + 0.7.1 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Transport/DotNetty.Transport.csproj b/src/DotNetty.Transport/DotNetty.Transport.csproj index e9b1687be..a2a4c226f 100644 --- a/src/DotNetty.Transport/DotNetty.Transport.csproj +++ b/src/DotNetty.Transport/DotNetty.Transport.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: transport model en-US - 0.7.0 + 0.7.1 Microsoft $(NoWarn);CS1591 false diff --git a/src/shared/SharedAssemblyInfo.cs b/src/shared/SharedAssemblyInfo.cs index 4e6c470d8..10c71f0b7 100644 --- a/src/shared/SharedAssemblyInfo.cs +++ b/src/shared/SharedAssemblyInfo.cs @@ -7,7 +7,7 @@ [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("DotNetty")] -[assembly: AssemblyVersion("0.7.0")] -[assembly: AssemblyFileVersion("0.7.0")] +[assembly: AssemblyVersion("0.7.1")] +[assembly: AssemblyFileVersion("0.7.1")] [assembly: AssemblyCopyright("(c) Microsoft 2015 - 2021")] From df5cd79cab85a5b09f6d41b2680594b3a0bd457c Mon Sep 17 00:00:00 2001 From: Andrey Ilnitsky Date: Mon, 14 Feb 2022 11:31:00 -0800 Subject: [PATCH 18/33] [0.7.2] Start threads as background in HashedWheelTimer, LoopExecutor, ThreadDeathWatcher --- RELEASE_NOTES.md | 11 +++++++---- src/DotNetty.Buffers/DotNetty.Buffers.csproj | 2 +- src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj | 2 +- src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj | 2 +- .../DotNetty.Codecs.Protobuf.csproj | 2 +- .../DotNetty.Codecs.ProtocolBuffers.csproj | 2 +- .../DotNetty.Codecs.Redis.csproj | 2 +- src/DotNetty.Codecs/DotNetty.Codecs.csproj | 2 +- src/DotNetty.Common/DotNetty.Common.csproj | 2 +- src/DotNetty.Common/ThreadDeathWatcher.cs | 5 ++++- src/DotNetty.Common/Utilities/HashedWheelTimer.cs | 5 ++++- src/DotNetty.Handlers/DotNetty.Handlers.csproj | 2 +- .../DotNetty.Transport.Libuv.csproj | 2 +- src/DotNetty.Transport.Libuv/LoopExecutor.cs | 6 +++++- src/DotNetty.Transport/DotNetty.Transport.csproj | 2 +- src/shared/SharedAssemblyInfo.cs | 4 ++-- 16 files changed, 33 insertions(+), 20 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 6d820b8a7..ac6471490 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,8 +1,11 @@ +#### 0.7.2 February 14, 2022 +- Start threads as background in HashedWheelTimer, LoopExecutor, ThreadDeathWatcher + #### 0.7.1 December 15, 2021 - Revert to use background threads #### 0.7.0 June 11, 2021 -- Target net472 and netstandard2.0 +- Target net472 and netstandard2.0 - Microsoft.Extensions.Logging 5.0.0 - Microsoft.Extensions.Configuration 5.0.0 @@ -129,13 +132,13 @@ - Channel ID - Complete `LengthFieldBasedFrameDecoder` and `LengthFieldPrepender` - Resource leak detection support (basic is on by default for pooled byte buffers) -- Proper internal logging +- Proper internal logging - Reacher byte buffer API - Proper utilities set for byte buffers, strings, system properties -- Performance improvements in SingleThreadEventExecutor +- Performance improvements in SingleThreadEventExecutor #### 0.1.3 September 21 2015 -- Fixed `TcpSocketChannel` closure on graceful socket closure +- Fixed `TcpSocketChannel` closure on graceful socket closure - Better alignment of IChannel implementations to netty's expected behavior for `Open`, `Active`, `LocalAddress`, `RemoteAddress` - Proper port of `Default/IChannelPipeline` and `AbstractChannelHandlerContext` to enable channel handlers to run on different invoker. diff --git a/src/DotNetty.Buffers/DotNetty.Buffers.csproj b/src/DotNetty.Buffers/DotNetty.Buffers.csproj index f6f56a8cf..ba7da0fb5 100644 --- a/src/DotNetty.Buffers/DotNetty.Buffers.csproj +++ b/src/DotNetty.Buffers/DotNetty.Buffers.csproj @@ -6,7 +6,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: buffer management en-US - 0.7.1 + 0.7.2 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj index 6338ce062..567db2273 100644 --- a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj +++ b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Http codec en-US - 0.7.1 + 0.7.2 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj index 563e9726a..7e14a1ed5 100644 --- a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj +++ b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: MQTT codec en-US - 0.7.1 + 0.7.2 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj index 7f60d2499..e8e7b3cca 100644 --- a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj +++ b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Protobuf Proto3 codec en-US - 0.7.1 + 0.7.2 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj index e03592e22..884946bde 100644 --- a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj +++ b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: ProtocolBuffers Proto2 codec en-US - 0.7.1 + 0.7.2 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj index 5b4c8b2fd..586377cdb 100644 --- a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj +++ b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Redis codec en-US - 0.7.1 + 0.7.2 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs/DotNetty.Codecs.csproj b/src/DotNetty.Codecs/DotNetty.Codecs.csproj index 372a703f3..b89c9edb6 100644 --- a/src/DotNetty.Codecs/DotNetty.Codecs.csproj +++ b/src/DotNetty.Codecs/DotNetty.Codecs.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: codecs en-US - 0.7.1 + 0.7.2 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Common/DotNetty.Common.csproj b/src/DotNetty.Common/DotNetty.Common.csproj index 5640fc467..13632d123 100644 --- a/src/DotNetty.Common/DotNetty.Common.csproj +++ b/src/DotNetty.Common/DotNetty.Common.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: common routines en-US - 0.7.1 + 0.7.2 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Common/ThreadDeathWatcher.cs b/src/DotNetty.Common/ThreadDeathWatcher.cs index 026decfb7..7b3f736fb 100644 --- a/src/DotNetty.Common/ThreadDeathWatcher.cs +++ b/src/DotNetty.Common/ThreadDeathWatcher.cs @@ -59,7 +59,10 @@ static void Schedule(Thread thread, Action task, bool isWatch) if (Interlocked.CompareExchange(ref started, 1, 0) == 0) { - var watcherThread = new Thread(s => ((IRunnable)s).Run()); + var watcherThread = new Thread(s => ((IRunnable)s).Run()) + { + IsBackground = true + }; watcherThread.Start(watcher); ThreadDeathWatcher.watcherThread = watcherThread; } diff --git a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs index 1ccd1c23b..2ecef70c8 100644 --- a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs +++ b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs @@ -98,7 +98,10 @@ public HashedWheelTimer( tickInterval, long.MaxValue / this.wheel.Length)); } - this.workerThread = new Thread(st => this.worker.Run()); + this.workerThread = new Thread(st => this.worker.Run()) + { + IsBackground = true + }; this.maxPendingTimeouts = maxPendingTimeouts; diff --git a/src/DotNetty.Handlers/DotNetty.Handlers.csproj b/src/DotNetty.Handlers/DotNetty.Handlers.csproj index e44929f4b..83fed99c9 100644 --- a/src/DotNetty.Handlers/DotNetty.Handlers.csproj +++ b/src/DotNetty.Handlers/DotNetty.Handlers.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: handlers en-US - 0.7.1 + 0.7.2 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj index 172507379..b9abbe773 100644 --- a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj +++ b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: libuv transport model Experimental en-US - 0.7.1 + 0.7.2 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Transport.Libuv/LoopExecutor.cs b/src/DotNetty.Transport.Libuv/LoopExecutor.cs index 3eef653e8..69ffa8f26 100644 --- a/src/DotNetty.Transport.Libuv/LoopExecutor.cs +++ b/src/DotNetty.Transport.Libuv/LoopExecutor.cs @@ -80,7 +80,11 @@ public LoopExecutor(IEventLoopGroup parent, string threadName, TimeSpan breakout { name = $"{name}({threadName})"; } - this.thread = new Thread(Run) { Name = name }; + this.thread = new Thread(Run) + { + Name = name, + IsBackground = true + }; this.loopRunStart = new ManualResetEventSlim(false, 1); } diff --git a/src/DotNetty.Transport/DotNetty.Transport.csproj b/src/DotNetty.Transport/DotNetty.Transport.csproj index a2a4c226f..6530c18db 100644 --- a/src/DotNetty.Transport/DotNetty.Transport.csproj +++ b/src/DotNetty.Transport/DotNetty.Transport.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: transport model en-US - 0.7.1 + 0.7.2 Microsoft $(NoWarn);CS1591 false diff --git a/src/shared/SharedAssemblyInfo.cs b/src/shared/SharedAssemblyInfo.cs index 10c71f0b7..ed949d621 100644 --- a/src/shared/SharedAssemblyInfo.cs +++ b/src/shared/SharedAssemblyInfo.cs @@ -7,7 +7,7 @@ [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("DotNetty")] -[assembly: AssemblyVersion("0.7.1")] -[assembly: AssemblyFileVersion("0.7.1")] +[assembly: AssemblyVersion("0.7.2")] +[assembly: AssemblyFileVersion("0.7.2")] [assembly: AssemblyCopyright("(c) Microsoft 2015 - 2021")] From 899e53f66432e7c53944c4e564ef31877a4b3dd4 Mon Sep 17 00:00:00 2001 From: Andrey Ilnitsky Date: Mon, 14 Feb 2022 12:39:19 -0800 Subject: [PATCH 19/33] + code formatting --- src/DotNetty.Common/ThreadDeathWatcher.cs | 6 ++---- src/DotNetty.Common/Utilities/HashedWheelTimer.cs | 7 +++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/DotNetty.Common/ThreadDeathWatcher.cs b/src/DotNetty.Common/ThreadDeathWatcher.cs index 7b3f736fb..f043db778 100644 --- a/src/DotNetty.Common/ThreadDeathWatcher.cs +++ b/src/DotNetty.Common/ThreadDeathWatcher.cs @@ -59,10 +59,8 @@ static void Schedule(Thread thread, Action task, bool isWatch) if (Interlocked.CompareExchange(ref started, 1, 0) == 0) { - var watcherThread = new Thread(s => ((IRunnable)s).Run()) - { - IsBackground = true - }; + var watcherThread = new Thread(s => ((IRunnable)s).Run()); + watcherThread.IsBackground = true; watcherThread.Start(watcher); ThreadDeathWatcher.watcherThread = watcherThread; } diff --git a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs index 2ecef70c8..a1dd13782 100644 --- a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs +++ b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs @@ -98,10 +98,9 @@ public HashedWheelTimer( tickInterval, long.MaxValue / this.wheel.Length)); } - this.workerThread = new Thread(st => this.worker.Run()) - { - IsBackground = true - }; + + this.workerThread = new Thread(st => this.worker.Run()); + this.workerThread.IsBackground = true; this.maxPendingTimeouts = maxPendingTimeouts; From 54fd364a9319c4b888296b4a6a20eb8f9d28285f Mon Sep 17 00:00:00 2001 From: Andrey Ilnitsky Date: Tue, 1 Mar 2022 09:51:59 -0800 Subject: [PATCH 20/33] Google.Protobuf 3.19.4 (latest) (#579) --- RELEASE_NOTES.md | 1 + src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index ac6471490..b99a9b86f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,6 @@ #### 0.7.2 February 14, 2022 - Start threads as background in HashedWheelTimer, LoopExecutor, ThreadDeathWatcher +- Google.Protobuf 3.19.4 (latest) #### 0.7.1 December 15, 2021 - Revert to use background threads diff --git a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj index e8e7b3cca..4c4a6e2ff 100644 --- a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj +++ b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj @@ -34,6 +34,6 @@ - + \ No newline at end of file From f754c83069e60bc93b7992230382d5289fdac03d Mon Sep 17 00:00:00 2001 From: Andrey Ilnitsky Date: Tue, 2 Aug 2022 16:37:48 -0700 Subject: [PATCH 21/33] [0.7.3] Target net5 and net6 (#588) * [0.7.2] Start threads as background in HashedWheelTimer, LoopExecutor, ThreadDeathWatcher * + code formatting * [0.7.3] Target net5 and net6 (#2) target net5 and net6 Adopted TlsHandler for the case when Handshake completion callback is dispatched asynchronously to thread pool Introduced SingleThreadedEmbededChannel for TlsHandler and SniHandler tests * + Update DotNetVersion to "6.0.302" in build.ps1 --- DotNetty.sln | 55 ++ RELEASE_NOTES.md | 5 + build.ps1 | 2 +- examples/Discard.Client/Discard.Client.csproj | 4 +- examples/Discard.Server/Discard.Server.csproj | 4 +- examples/Echo.Client/Echo.Client.csproj | 4 +- examples/Echo.Server/Echo.Server.csproj | 4 +- examples/Examples.Common/ExampleHelper.cs | 2 +- .../Examples.Common/Examples.Common.csproj | 4 +- .../Factorial.Client/Factorial.Client.csproj | 4 +- .../Factorial.Server/Factorial.Server.csproj | 4 +- examples/Factorial/Factorial.csproj | 4 +- examples/HttpServer/HttpServer.csproj | 4 +- .../QuoteOfTheMoment.Client.csproj | 4 +- .../QuoteOfTheMoment.Server.csproj | 4 +- .../SecureChat.Client.csproj | 4 +- .../SecureChat.Server.csproj | 4 +- examples/Telnet.Client/Telnet.Client.csproj | 4 +- examples/Telnet.Server/Telnet.Server.csproj | 4 +- .../WebSocketClientHandler.cs | 1 + .../WebSockets.Client.csproj | 4 +- .../WebSockets.Server.csproj | 4 +- src/Directory.Build.props | 23 + src/DotNetty.Buffers/DotNetty.Buffers.csproj | 4 +- src/DotNetty.Buffers/UnsafeByteBufferUtil.cs | 2 +- .../DotNetty.Codecs.Http.csproj | 4 +- .../WebSockets/WebSocketClientHandshaker.cs | 1 + .../WebSockets/WebSocketServerHandshaker.cs | 1 + .../DotNetty.Codecs.Mqtt.csproj | 4 +- .../DotNetty.Codecs.Protobuf.csproj | 4 +- .../DotNetty.Codecs.ProtocolBuffers.csproj | 4 +- .../DotNetty.Codecs.Redis.csproj | 4 +- src/DotNetty.Codecs/DotNetty.Codecs.csproj | 4 +- src/DotNetty.Common/DotNetty.Common.csproj | 4 +- .../Utilities/HashedWheelTimer.cs | 1 + src/DotNetty.Common/Utilities/TaskEx.cs | 1 + .../DotNetty.Handlers.csproj | 4 +- .../Streams/ChunkedWriteHandler.cs | 1 + src/DotNetty.Handlers/Tls/SniHandler.cs | 2 +- .../Tls/TlsHandler.MediationStream.Net.cs | 302 +++++++++++ .../Tls/TlsHandler.MediationStream.cs | 338 ++++++++++++ .../Tls/TlsHandler.MediationStreamBase.cs | 70 +++ src/DotNetty.Handlers/Tls/TlsHandler.cs | 510 +++++------------- src/DotNetty.Handlers/Tls/TlsUtils.cs | 28 +- .../DotNetty.Transport.Libuv.csproj | 4 +- src/DotNetty.Transport.Libuv/LoopExecutor.cs | 1 + .../Native/NativeMethods.cs | 6 +- .../Native/WindowsApi.cs | 2 +- .../Native/WriteRequest.cs | 2 +- src/DotNetty.Transport.Libuv/NativeChannel.cs | 1 + .../WorkerEventLoop.cs | 1 + .../Bootstrapping/AbstractBootstrap.cs | 1 + .../Bootstrapping/Bootstrap.cs | 1 + .../Channels/AbstractChannel.cs | 1 + .../Channels/AbstractChannelHandlerContext.cs | 1 + .../Channels/BatchingPendingWriteQueue.cs | 1 + .../Channels/DefaultChannelPipeline.cs | 1 + .../Channels/Embedded/EmbeddedChannel.cs | 2 +- .../Channels/Embedded/IEmbeddedChannel.cs | 18 + .../Embedded/SingleThreadedEmbeddedChannel.cs | 468 ++++++++++++++++ .../Channels/Local/LocalChannel.cs | 1 + .../Channels/PendingWriteQueue.cs | 1 + .../Sockets/AbstractSocketByteChannel.cs | 4 +- .../Channels/Sockets/AbstractSocketChannel.cs | 1 + .../Channels/Sockets/IDatagramChannel.cs | 1 + .../Channels/Sockets/SocketDatagramChannel.cs | 3 +- .../Channels/Sockets/TcpSocketChannel.cs | 1 + src/DotNetty.Transport/Channels/Util.cs | 1 + .../DotNetty.Transport.csproj | 4 +- src/shared/SharedAssemblyInfo.cs | 4 +- .../DotNetty.Buffers.Tests.csproj | 4 +- .../DotNetty.Codecs.Http.Tests.csproj | 4 +- .../HttpClientCodecTest.cs | 1 + .../HttpServerUpgradeHandlerTest.cs | 1 + .../WebSocketHandshakeHandOverTest.cs | 1 + .../DotNetty.Codecs.Mqtt.Tests.csproj | 4 +- .../DotNetty.Codecs.Protobuf.Tests.csproj | 4 +- ...tNetty.Codecs.ProtocolBuffers.Tests.csproj | 4 +- .../DotNetty.Codecs.Redis.Tests.csproj | 4 +- .../DotNetty.Codecs.Tests.csproj | 4 +- .../SingleThreadEventExecutorTests.cs | 1 + .../DotNetty.Common.Tests.csproj | 4 +- .../AsIsWriteStrategy.cs | 2 +- .../BatchingWriteStrategy.cs | 4 +- .../DotNetty.Handlers.Tests.csproj | 4 +- .../DotNetty.Handlers.Tests/IWriteStrategy.cs | 2 +- .../DotNetty.Handlers.Tests/SniHandlerTest.cs | 24 +- .../DotNetty.Handlers.Tests/TlsHandlerTest.cs | 64 ++- .../DotNetty.Microbench.csproj | 4 +- .../DotNetty.Tests.Common.csproj | 4 +- .../DotNetty.Tests.End2End.csproj | 4 +- test/DotNetty.Tests.End2End/End2EndTests.cs | 1 + .../BufReleaseTests.cs | 1 + .../CompositeBufferGatheringWriteTests.cs | 1 + .../DetectPeerCloseWithoutReadTests.cs | 1 + .../DotNetty.Transport.Libuv.Tests.csproj | 4 +- .../EchoTests.cs | 1 + .../EventLoopTests.cs | 1 + .../ExceptionHandlingTests.cs | 1 + .../ReadPendingTests.cs | 1 + .../ResetTests.cs | 1 + ...otNetty.Transport.Tests.Performance.csproj | 4 +- .../Transport/AbstractPingPongPerfSpecs.cs | 1 + .../DotNetty.Transport.Tests.csproj | 4 +- 104 files changed, 1673 insertions(+), 478 deletions(-) create mode 100644 src/Directory.Build.props create mode 100644 src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.Net.cs create mode 100644 src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.cs create mode 100644 src/DotNetty.Handlers/Tls/TlsHandler.MediationStreamBase.cs create mode 100644 src/DotNetty.Transport/Channels/Embedded/IEmbeddedChannel.cs create mode 100644 src/DotNetty.Transport/Channels/Embedded/SingleThreadedEmbeddedChannel.cs diff --git a/DotNetty.sln b/DotNetty.sln index f2809a025..5077ced52 100644 --- a/DotNetty.sln +++ b/DotNetty.sln @@ -111,180 +111,235 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU + Package|Any CPU = Package|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Debug|Any CPU.Build.0 = Debug|Any CPU {DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Release|Any CPU.ActiveCfg = Release|Any CPU {DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Release|Any CPU.Build.0 = Release|Any CPU + {DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Package|Any CPU.ActiveCfg = Package|Any CPU + {DF4FF0D0-A5CE-471F-B946-538C28C21CBB}.Package|Any CPU.Build.0 = Package|Any CPU {64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Debug|Any CPU.Build.0 = Debug|Any CPU {64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Release|Any CPU.ActiveCfg = Release|Any CPU {64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Release|Any CPU.Build.0 = Release|Any CPU + {64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Package|Any CPU.ActiveCfg = Package|Any CPU + {64508DA2-40F1-4CC3-93E8-EA3B18A64E7E}.Package|Any CPU.Build.0 = Package|Any CPU {82796E9E-1331-4858-90C3-8E74BA4CC383}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {82796E9E-1331-4858-90C3-8E74BA4CC383}.Debug|Any CPU.Build.0 = Debug|Any CPU {82796E9E-1331-4858-90C3-8E74BA4CC383}.Release|Any CPU.ActiveCfg = Release|Any CPU {82796E9E-1331-4858-90C3-8E74BA4CC383}.Release|Any CPU.Build.0 = Release|Any CPU + {82796E9E-1331-4858-90C3-8E74BA4CC383}.Package|Any CPU.ActiveCfg = Package|Any CPU + {82796E9E-1331-4858-90C3-8E74BA4CC383}.Package|Any CPU.Build.0 = Package|Any CPU {25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Debug|Any CPU.Build.0 = Debug|Any CPU {25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Release|Any CPU.ActiveCfg = Release|Any CPU {25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Release|Any CPU.Build.0 = Release|Any CPU + {25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Package|Any CPU.ActiveCfg = Package|Any CPU + {25F7AD69-7836-46E8-9B29-0FBB3C128FFB}.Package|Any CPU.Build.0 = Package|Any CPU {12DCCEFD-623B-46CC-979C-407FA265E239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {12DCCEFD-623B-46CC-979C-407FA265E239}.Debug|Any CPU.Build.0 = Debug|Any CPU {12DCCEFD-623B-46CC-979C-407FA265E239}.Release|Any CPU.ActiveCfg = Release|Any CPU {12DCCEFD-623B-46CC-979C-407FA265E239}.Release|Any CPU.Build.0 = Release|Any CPU + {12DCCEFD-623B-46CC-979C-407FA265E239}.Package|Any CPU.ActiveCfg = Package|Any CPU + {12DCCEFD-623B-46CC-979C-407FA265E239}.Package|Any CPU.Build.0 = Package|Any CPU {5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Debug|Any CPU.Build.0 = Debug|Any CPU {5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Release|Any CPU.ActiveCfg = Release|Any CPU {5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Release|Any CPU.Build.0 = Release|Any CPU + {5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Package|Any CPU.ActiveCfg = Package|Any CPU + {5ADB0FF5-8EFC-475A-BF08-6B35EF728329}.Package|Any CPU.Build.0 = Package|Any CPU {D284C2BF-E06E-481B-B301-503A9D477B0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D284C2BF-E06E-481B-B301-503A9D477B0E}.Debug|Any CPU.Build.0 = Debug|Any CPU {D284C2BF-E06E-481B-B301-503A9D477B0E}.Release|Any CPU.ActiveCfg = Release|Any CPU {D284C2BF-E06E-481B-B301-503A9D477B0E}.Release|Any CPU.Build.0 = Release|Any CPU + {D284C2BF-E06E-481B-B301-503A9D477B0E}.Package|Any CPU.ActiveCfg = Package|Any CPU + {D284C2BF-E06E-481B-B301-503A9D477B0E}.Package|Any CPU.Build.0 = Package|Any CPU {75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Debug|Any CPU.Build.0 = Debug|Any CPU {75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Release|Any CPU.ActiveCfg = Release|Any CPU {75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Release|Any CPU.Build.0 = Release|Any CPU + {75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Package|Any CPU.ActiveCfg = Package|Any CPU + {75A1BCC1-A7F3-4893-99C5-3235F87DB00E}.Package|Any CPU.Build.0 = Package|Any CPU {1F442118-A665-4891-B056-FE9E54C5B049}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1F442118-A665-4891-B056-FE9E54C5B049}.Debug|Any CPU.Build.0 = Debug|Any CPU {1F442118-A665-4891-B056-FE9E54C5B049}.Release|Any CPU.ActiveCfg = Release|Any CPU {1F442118-A665-4891-B056-FE9E54C5B049}.Release|Any CPU.Build.0 = Release|Any CPU + {1F442118-A665-4891-B056-FE9E54C5B049}.Package|Any CPU.ActiveCfg = Package|Any CPU + {1F442118-A665-4891-B056-FE9E54C5B049}.Package|Any CPU.Build.0 = Package|Any CPU {572E1914-489F-402D-944F-71EE0632E5D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {572E1914-489F-402D-944F-71EE0632E5D8}.Debug|Any CPU.Build.0 = Debug|Any CPU {572E1914-489F-402D-944F-71EE0632E5D8}.Release|Any CPU.ActiveCfg = Release|Any CPU {572E1914-489F-402D-944F-71EE0632E5D8}.Release|Any CPU.Build.0 = Release|Any CPU + {572E1914-489F-402D-944F-71EE0632E5D8}.Package|Any CPU.ActiveCfg = Package|Any CPU {DA54DBAF-CCDA-4AD1-9FF9-EB6F890D1091}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DA54DBAF-CCDA-4AD1-9FF9-EB6F890D1091}.Debug|Any CPU.Build.0 = Debug|Any CPU {DA54DBAF-CCDA-4AD1-9FF9-EB6F890D1091}.Release|Any CPU.ActiveCfg = Release|Any CPU {DA54DBAF-CCDA-4AD1-9FF9-EB6F890D1091}.Release|Any CPU.Build.0 = Release|Any CPU + {DA54DBAF-CCDA-4AD1-9FF9-EB6F890D1091}.Package|Any CPU.ActiveCfg = Package|Any CPU {72C92F76-F804-4300-BFF1-459420D9EF0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {72C92F76-F804-4300-BFF1-459420D9EF0B}.Debug|Any CPU.Build.0 = Debug|Any CPU {72C92F76-F804-4300-BFF1-459420D9EF0B}.Release|Any CPU.ActiveCfg = Release|Any CPU {72C92F76-F804-4300-BFF1-459420D9EF0B}.Release|Any CPU.Build.0 = Release|Any CPU + {72C92F76-F804-4300-BFF1-459420D9EF0B}.Package|Any CPU.ActiveCfg = Package|Any CPU {E31A5D46-71B7-4B7E-A9F8-3F011822F28A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E31A5D46-71B7-4B7E-A9F8-3F011822F28A}.Debug|Any CPU.Build.0 = Debug|Any CPU {E31A5D46-71B7-4B7E-A9F8-3F011822F28A}.Release|Any CPU.ActiveCfg = Release|Any CPU {E31A5D46-71B7-4B7E-A9F8-3F011822F28A}.Release|Any CPU.Build.0 = Release|Any CPU + {E31A5D46-71B7-4B7E-A9F8-3F011822F28A}.Package|Any CPU.ActiveCfg = Package|Any CPU {3AF8A62F-F5CE-4C2D-B356-8B9FDFA51668}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3AF8A62F-F5CE-4C2D-B356-8B9FDFA51668}.Debug|Any CPU.Build.0 = Debug|Any CPU {3AF8A62F-F5CE-4C2D-B356-8B9FDFA51668}.Release|Any CPU.ActiveCfg = Release|Any CPU {3AF8A62F-F5CE-4C2D-B356-8B9FDFA51668}.Release|Any CPU.Build.0 = Release|Any CPU + {3AF8A62F-F5CE-4C2D-B356-8B9FDFA51668}.Package|Any CPU.ActiveCfg = Package|Any CPU {A7FC497E-790A-4980-B57C-32AF4AD4AB9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A7FC497E-790A-4980-B57C-32AF4AD4AB9D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A7FC497E-790A-4980-B57C-32AF4AD4AB9D}.Release|Any CPU.ActiveCfg = Release|Any CPU {A7FC497E-790A-4980-B57C-32AF4AD4AB9D}.Release|Any CPU.Build.0 = Release|Any CPU + {A7FC497E-790A-4980-B57C-32AF4AD4AB9D}.Package|Any CPU.ActiveCfg = Package|Any CPU {08C19033-23B2-47D7-8332-86273AE287BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {08C19033-23B2-47D7-8332-86273AE287BC}.Debug|Any CPU.Build.0 = Debug|Any CPU {08C19033-23B2-47D7-8332-86273AE287BC}.Release|Any CPU.ActiveCfg = Release|Any CPU {08C19033-23B2-47D7-8332-86273AE287BC}.Release|Any CPU.Build.0 = Release|Any CPU + {08C19033-23B2-47D7-8332-86273AE287BC}.Package|Any CPU.ActiveCfg = Package|Any CPU {CE97D2EC-3EA9-4FEC-B304-F57646DB54FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE97D2EC-3EA9-4FEC-B304-F57646DB54FD}.Debug|Any CPU.Build.0 = Debug|Any CPU {CE97D2EC-3EA9-4FEC-B304-F57646DB54FD}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE97D2EC-3EA9-4FEC-B304-F57646DB54FD}.Release|Any CPU.Build.0 = Release|Any CPU + {CE97D2EC-3EA9-4FEC-B304-F57646DB54FD}.Package|Any CPU.ActiveCfg = Package|Any CPU {D0DBB346-BDDA-4E28-A335-6D3E1F9902DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D0DBB346-BDDA-4E28-A335-6D3E1F9902DF}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0DBB346-BDDA-4E28-A335-6D3E1F9902DF}.Release|Any CPU.ActiveCfg = Release|Any CPU {D0DBB346-BDDA-4E28-A335-6D3E1F9902DF}.Release|Any CPU.Build.0 = Release|Any CPU + {D0DBB346-BDDA-4E28-A335-6D3E1F9902DF}.Package|Any CPU.ActiveCfg = Package|Any CPU {5D5A3137-F118-4F6C-ABE7-2523184A3A2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5D5A3137-F118-4F6C-ABE7-2523184A3A2D}.Debug|Any CPU.Build.0 = Debug|Any CPU {5D5A3137-F118-4F6C-ABE7-2523184A3A2D}.Release|Any CPU.ActiveCfg = Release|Any CPU {5D5A3137-F118-4F6C-ABE7-2523184A3A2D}.Release|Any CPU.Build.0 = Release|Any CPU + {5D5A3137-F118-4F6C-ABE7-2523184A3A2D}.Package|Any CPU.ActiveCfg = Package|Any CPU {BDA099C5-E435-49DF-9922-58D63E11B764}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BDA099C5-E435-49DF-9922-58D63E11B764}.Debug|Any CPU.Build.0 = Debug|Any CPU {BDA099C5-E435-49DF-9922-58D63E11B764}.Release|Any CPU.ActiveCfg = Release|Any CPU {BDA099C5-E435-49DF-9922-58D63E11B764}.Release|Any CPU.Build.0 = Release|Any CPU + {BDA099C5-E435-49DF-9922-58D63E11B764}.Package|Any CPU.ActiveCfg = Package|Any CPU {3DA49C12-3614-40F5-B5CE-8B95F872EFC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3DA49C12-3614-40F5-B5CE-8B95F872EFC1}.Debug|Any CPU.Build.0 = Debug|Any CPU {3DA49C12-3614-40F5-B5CE-8B95F872EFC1}.Release|Any CPU.ActiveCfg = Release|Any CPU {3DA49C12-3614-40F5-B5CE-8B95F872EFC1}.Release|Any CPU.Build.0 = Release|Any CPU + {3DA49C12-3614-40F5-B5CE-8B95F872EFC1}.Package|Any CPU.ActiveCfg = Package|Any CPU {9AE188E0-F328-4A88-AF5F-CE0C1D4D0036}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9AE188E0-F328-4A88-AF5F-CE0C1D4D0036}.Debug|Any CPU.Build.0 = Debug|Any CPU {9AE188E0-F328-4A88-AF5F-CE0C1D4D0036}.Release|Any CPU.ActiveCfg = Release|Any CPU {9AE188E0-F328-4A88-AF5F-CE0C1D4D0036}.Release|Any CPU.Build.0 = Release|Any CPU + {9AE188E0-F328-4A88-AF5F-CE0C1D4D0036}.Package|Any CPU.ActiveCfg = Package|Any CPU {66491D47-2BFB-45CF-A582-C11860219512}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {66491D47-2BFB-45CF-A582-C11860219512}.Debug|Any CPU.Build.0 = Debug|Any CPU {66491D47-2BFB-45CF-A582-C11860219512}.Release|Any CPU.ActiveCfg = Release|Any CPU {66491D47-2BFB-45CF-A582-C11860219512}.Release|Any CPU.Build.0 = Release|Any CPU + {66491D47-2BFB-45CF-A582-C11860219512}.Package|Any CPU.ActiveCfg = Package|Any CPU {664ECD06-26EB-4F8F-8D88-5444A5E766E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {664ECD06-26EB-4F8F-8D88-5444A5E766E0}.Debug|Any CPU.Build.0 = Debug|Any CPU {664ECD06-26EB-4F8F-8D88-5444A5E766E0}.Release|Any CPU.ActiveCfg = Release|Any CPU {664ECD06-26EB-4F8F-8D88-5444A5E766E0}.Release|Any CPU.Build.0 = Release|Any CPU + {664ECD06-26EB-4F8F-8D88-5444A5E766E0}.Package|Any CPU.ActiveCfg = Package|Any CPU {EAE5000B-9A97-4308-B791-0B71DE0A8219}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EAE5000B-9A97-4308-B791-0B71DE0A8219}.Debug|Any CPU.Build.0 = Debug|Any CPU {EAE5000B-9A97-4308-B791-0B71DE0A8219}.Release|Any CPU.ActiveCfg = Release|Any CPU {EAE5000B-9A97-4308-B791-0B71DE0A8219}.Release|Any CPU.Build.0 = Release|Any CPU + {EAE5000B-9A97-4308-B791-0B71DE0A8219}.Package|Any CPU.ActiveCfg = Package|Any CPU {E854F61B-548A-4100-A766-35B972B9EE11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E854F61B-548A-4100-A766-35B972B9EE11}.Debug|Any CPU.Build.0 = Debug|Any CPU {E854F61B-548A-4100-A766-35B972B9EE11}.Release|Any CPU.ActiveCfg = Release|Any CPU {E854F61B-548A-4100-A766-35B972B9EE11}.Release|Any CPU.Build.0 = Release|Any CPU + {E854F61B-548A-4100-A766-35B972B9EE11}.Package|Any CPU.ActiveCfg = Package|Any CPU {22C53CFB-B54A-438E-820F-42C94D557345}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {22C53CFB-B54A-438E-820F-42C94D557345}.Debug|Any CPU.Build.0 = Debug|Any CPU {22C53CFB-B54A-438E-820F-42C94D557345}.Release|Any CPU.ActiveCfg = Release|Any CPU {22C53CFB-B54A-438E-820F-42C94D557345}.Release|Any CPU.Build.0 = Release|Any CPU + {22C53CFB-B54A-438E-820F-42C94D557345}.Package|Any CPU.ActiveCfg = Package|Any CPU {A4E85E94-383F-40EA-9478-0545070E52F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A4E85E94-383F-40EA-9478-0545070E52F5}.Debug|Any CPU.Build.0 = Debug|Any CPU {A4E85E94-383F-40EA-9478-0545070E52F5}.Release|Any CPU.ActiveCfg = Release|Any CPU {A4E85E94-383F-40EA-9478-0545070E52F5}.Release|Any CPU.Build.0 = Release|Any CPU + {A4E85E94-383F-40EA-9478-0545070E52F5}.Package|Any CPU.ActiveCfg = Package|Any CPU {928090A9-AAC7-496C-A8E3-D242D2D8BC74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {928090A9-AAC7-496C-A8E3-D242D2D8BC74}.Debug|Any CPU.Build.0 = Debug|Any CPU {928090A9-AAC7-496C-A8E3-D242D2D8BC74}.Release|Any CPU.ActiveCfg = Release|Any CPU {928090A9-AAC7-496C-A8E3-D242D2D8BC74}.Release|Any CPU.Build.0 = Release|Any CPU + {928090A9-AAC7-496C-A8E3-D242D2D8BC74}.Package|Any CPU.ActiveCfg = Package|Any CPU {D69B9924-5C2E-41BC-9354-A12DA7D03FDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D69B9924-5C2E-41BC-9354-A12DA7D03FDF}.Debug|Any CPU.Build.0 = Debug|Any CPU {D69B9924-5C2E-41BC-9354-A12DA7D03FDF}.Release|Any CPU.ActiveCfg = Release|Any CPU {D69B9924-5C2E-41BC-9354-A12DA7D03FDF}.Release|Any CPU.Build.0 = Release|Any CPU + {D69B9924-5C2E-41BC-9354-A12DA7D03FDF}.Package|Any CPU.ActiveCfg = Package|Any CPU {ED307D87-E1BF-49B6-9591-5250D431C758}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {ED307D87-E1BF-49B6-9591-5250D431C758}.Debug|Any CPU.Build.0 = Debug|Any CPU {ED307D87-E1BF-49B6-9591-5250D431C758}.Release|Any CPU.ActiveCfg = Release|Any CPU {ED307D87-E1BF-49B6-9591-5250D431C758}.Release|Any CPU.Build.0 = Release|Any CPU + {ED307D87-E1BF-49B6-9591-5250D431C758}.Package|Any CPU.ActiveCfg = Package|Any CPU {0E4B622A-063B-4A39-87CF-F18AEACBDDC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0E4B622A-063B-4A39-87CF-F18AEACBDDC5}.Debug|Any CPU.Build.0 = Debug|Any CPU {0E4B622A-063B-4A39-87CF-F18AEACBDDC5}.Release|Any CPU.ActiveCfg = Release|Any CPU {0E4B622A-063B-4A39-87CF-F18AEACBDDC5}.Release|Any CPU.Build.0 = Release|Any CPU + {0E4B622A-063B-4A39-87CF-F18AEACBDDC5}.Package|Any CPU.ActiveCfg = Package|Any CPU {E2BEAAAE-497B-49F4-AD27-03BE20924311}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E2BEAAAE-497B-49F4-AD27-03BE20924311}.Debug|Any CPU.Build.0 = Debug|Any CPU {E2BEAAAE-497B-49F4-AD27-03BE20924311}.Release|Any CPU.ActiveCfg = Release|Any CPU {E2BEAAAE-497B-49F4-AD27-03BE20924311}.Release|Any CPU.Build.0 = Release|Any CPU + {E2BEAAAE-497B-49F4-AD27-03BE20924311}.Package|Any CPU.ActiveCfg = Package|Any CPU {F2490822-51F7-4B65-8B21-EE0082B76745}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F2490822-51F7-4B65-8B21-EE0082B76745}.Debug|Any CPU.Build.0 = Debug|Any CPU {F2490822-51F7-4B65-8B21-EE0082B76745}.Release|Any CPU.ActiveCfg = Release|Any CPU {F2490822-51F7-4B65-8B21-EE0082B76745}.Release|Any CPU.Build.0 = Release|Any CPU + {F2490822-51F7-4B65-8B21-EE0082B76745}.Package|Any CPU.ActiveCfg = Package|Any CPU {07C97A77-61B6-4BB5-9436-3A7FC379B75E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {07C97A77-61B6-4BB5-9436-3A7FC379B75E}.Debug|Any CPU.Build.0 = Debug|Any CPU {07C97A77-61B6-4BB5-9436-3A7FC379B75E}.Release|Any CPU.ActiveCfg = Release|Any CPU {07C97A77-61B6-4BB5-9436-3A7FC379B75E}.Release|Any CPU.Build.0 = Release|Any CPU + {07C97A77-61B6-4BB5-9436-3A7FC379B75E}.Package|Any CPU.ActiveCfg = Package|Any CPU {7155D1E6-00CE-4081-B922-E6C5524EE600}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7155D1E6-00CE-4081-B922-E6C5524EE600}.Debug|Any CPU.Build.0 = Debug|Any CPU {7155D1E6-00CE-4081-B922-E6C5524EE600}.Release|Any CPU.ActiveCfg = Release|Any CPU {7155D1E6-00CE-4081-B922-E6C5524EE600}.Release|Any CPU.Build.0 = Release|Any CPU + {7155D1E6-00CE-4081-B922-E6C5524EE600}.Package|Any CPU.ActiveCfg = Package|Any CPU {9FE6A783-C20D-4097-9988-4178E2C4CE75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9FE6A783-C20D-4097-9988-4178E2C4CE75}.Debug|Any CPU.Build.0 = Debug|Any CPU {9FE6A783-C20D-4097-9988-4178E2C4CE75}.Release|Any CPU.ActiveCfg = Release|Any CPU {9FE6A783-C20D-4097-9988-4178E2C4CE75}.Release|Any CPU.Build.0 = Release|Any CPU + {9FE6A783-C20D-4097-9988-4178E2C4CE75}.Package|Any CPU.ActiveCfg = Package|Any CPU + {9FE6A783-C20D-4097-9988-4178E2C4CE75}.Package|Any CPU.Build.0 = Package|Any CPU {1012C962-7F6D-4EC5-A0EC-0741A95BAD6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1012C962-7F6D-4EC5-A0EC-0741A95BAD6B}.Debug|Any CPU.Build.0 = Debug|Any CPU {1012C962-7F6D-4EC5-A0EC-0741A95BAD6B}.Release|Any CPU.ActiveCfg = Release|Any CPU {1012C962-7F6D-4EC5-A0EC-0741A95BAD6B}.Release|Any CPU.Build.0 = Release|Any CPU + {1012C962-7F6D-4EC5-A0EC-0741A95BAD6B}.Package|Any CPU.ActiveCfg = Package|Any CPU {A7CACAE7-66E7-43DA-948B-28EB0DDDB582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A7CACAE7-66E7-43DA-948B-28EB0DDDB582}.Debug|Any CPU.Build.0 = Debug|Any CPU {A7CACAE7-66E7-43DA-948B-28EB0DDDB582}.Release|Any CPU.ActiveCfg = Release|Any CPU {A7CACAE7-66E7-43DA-948B-28EB0DDDB582}.Release|Any CPU.Build.0 = Release|Any CPU + {A7CACAE7-66E7-43DA-948B-28EB0DDDB582}.Package|Any CPU.ActiveCfg = Package|Any CPU {5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Debug|Any CPU.Build.0 = Debug|Any CPU {5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Release|Any CPU.ActiveCfg = Release|Any CPU {5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Release|Any CPU.Build.0 = Release|Any CPU + {5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Package|Any CPU.ActiveCfg = Package|Any CPU + {5F68A5B1-7907-4B16-8AFE-326E9DD7D65B}.Package|Any CPU.Build.0 = Package|Any CPU {16C89E7C-1575-4685-8DFA-8E7E2C6101BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16C89E7C-1575-4685-8DFA-8E7E2C6101BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {16C89E7C-1575-4685-8DFA-8E7E2C6101BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {16C89E7C-1575-4685-8DFA-8E7E2C6101BF}.Release|Any CPU.Build.0 = Release|Any CPU + {16C89E7C-1575-4685-8DFA-8E7E2C6101BF}.Package|Any CPU.ActiveCfg = Package|Any CPU {EA387B4B-DAD0-4E34-B8A3-79EA4616726A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EA387B4B-DAD0-4E34-B8A3-79EA4616726A}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA387B4B-DAD0-4E34-B8A3-79EA4616726A}.Release|Any CPU.ActiveCfg = Release|Any CPU {EA387B4B-DAD0-4E34-B8A3-79EA4616726A}.Release|Any CPU.Build.0 = Release|Any CPU + {EA387B4B-DAD0-4E34-B8A3-79EA4616726A}.Package|Any CPU.ActiveCfg = Package|Any CPU {3326DB6E-023E-483F-9A1C-5905D3091B57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3326DB6E-023E-483F-9A1C-5905D3091B57}.Debug|Any CPU.Build.0 = Debug|Any CPU {3326DB6E-023E-483F-9A1C-5905D3091B57}.Release|Any CPU.ActiveCfg = Release|Any CPU {3326DB6E-023E-483F-9A1C-5905D3091B57}.Release|Any CPU.Build.0 = Release|Any CPU + {3326DB6E-023E-483F-9A1C-5905D3091B57}.Package|Any CPU.ActiveCfg = Package|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b99a9b86f..f46e23530 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,8 @@ +#### 0.7.3 July 28, 2022 +- target net5 and net6 +- Adopted TlsHandler for the case when Handshake completion callback is dispatched asynchronously to thread pool +- Introduced SingleThreadedEmbededChannel for TlsHandler and SniHandler tests + #### 0.7.2 February 14, 2022 - Start threads as background in HashedWheelTimer, LoopExecutor, ThreadDeathWatcher - Google.Protobuf 3.19.4 (latest) diff --git a/build.ps1 b/build.ps1 index 291b9efdc..b843a9f5e 100644 --- a/build.ps1 +++ b/build.ps1 @@ -33,7 +33,7 @@ Param( $CakeVersion = "0.27.1" $DotNetChannel = "Current"; -$DotNetVersion = "3.1.411"; +$DotNetVersion = "6.0.302"; $DotNetInstallerUri = "https://dot.net/v1/dotnet-install.ps1"; $NugetUrl = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" # Temporarily skip verification of addins. diff --git a/examples/Discard.Client/Discard.Client.csproj b/examples/Discard.Client/Discard.Client.csproj index 96c39faba..fc5f66ab8 100644 --- a/examples/Discard.Client/Discard.Client.csproj +++ b/examples/Discard.Client/Discard.Client.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/Discard.Server/Discard.Server.csproj b/examples/Discard.Server/Discard.Server.csproj index 96c39faba..fc5f66ab8 100644 --- a/examples/Discard.Server/Discard.Server.csproj +++ b/examples/Discard.Server/Discard.Server.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/Echo.Client/Echo.Client.csproj b/examples/Echo.Client/Echo.Client.csproj index 96c39faba..fc5f66ab8 100644 --- a/examples/Echo.Client/Echo.Client.csproj +++ b/examples/Echo.Client/Echo.Client.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/Echo.Server/Echo.Server.csproj b/examples/Echo.Server/Echo.Server.csproj index defec1f72..0d2902c22 100644 --- a/examples/Echo.Server/Echo.Server.csproj +++ b/examples/Echo.Server/Echo.Server.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/Examples.Common/ExampleHelper.cs b/examples/Examples.Common/ExampleHelper.cs index 535170274..f2b775210 100644 --- a/examples/Examples.Common/ExampleHelper.cs +++ b/examples/Examples.Common/ExampleHelper.cs @@ -22,7 +22,7 @@ public static string ProcessDirectory { get { -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER return AppContext.BaseDirectory; #else return AppDomain.CurrentDomain.BaseDirectory; diff --git a/examples/Examples.Common/Examples.Common.csproj b/examples/Examples.Common/Examples.Common.csproj index 8e186c734..3ffab8ae0 100644 --- a/examples/Examples.Common/Examples.Common.csproj +++ b/examples/Examples.Common/Examples.Common.csproj @@ -1,8 +1,10 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU diff --git a/examples/Factorial.Client/Factorial.Client.csproj b/examples/Factorial.Client/Factorial.Client.csproj index f5a342a29..e359418af 100644 --- a/examples/Factorial.Client/Factorial.Client.csproj +++ b/examples/Factorial.Client/Factorial.Client.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/Factorial.Server/Factorial.Server.csproj b/examples/Factorial.Server/Factorial.Server.csproj index f5a342a29..e359418af 100644 --- a/examples/Factorial.Server/Factorial.Server.csproj +++ b/examples/Factorial.Server/Factorial.Server.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/Factorial/Factorial.csproj b/examples/Factorial/Factorial.csproj index d2ccbbd2f..157b1f550 100644 --- a/examples/Factorial/Factorial.csproj +++ b/examples/Factorial/Factorial.csproj @@ -1,8 +1,10 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU diff --git a/examples/HttpServer/HttpServer.csproj b/examples/HttpServer/HttpServer.csproj index 9e580ec6f..3337a67d1 100644 --- a/examples/HttpServer/HttpServer.csproj +++ b/examples/HttpServer/HttpServer.csproj @@ -1,10 +1,12 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false true + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj b/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj index 96c39faba..fc5f66ab8 100644 --- a/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj +++ b/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj b/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj index 96c39faba..fc5f66ab8 100644 --- a/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj +++ b/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/SecureChat.Client/SecureChat.Client.csproj b/examples/SecureChat.Client/SecureChat.Client.csproj index 96c39faba..fc5f66ab8 100644 --- a/examples/SecureChat.Client/SecureChat.Client.csproj +++ b/examples/SecureChat.Client/SecureChat.Client.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/SecureChat.Server/SecureChat.Server.csproj b/examples/SecureChat.Server/SecureChat.Server.csproj index 96c39faba..fc5f66ab8 100644 --- a/examples/SecureChat.Server/SecureChat.Server.csproj +++ b/examples/SecureChat.Server/SecureChat.Server.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/Telnet.Client/Telnet.Client.csproj b/examples/Telnet.Client/Telnet.Client.csproj index 96c39faba..fc5f66ab8 100644 --- a/examples/Telnet.Client/Telnet.Client.csproj +++ b/examples/Telnet.Client/Telnet.Client.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/Telnet.Server/Telnet.Server.csproj b/examples/Telnet.Server/Telnet.Server.csproj index 96c39faba..fc5f66ab8 100644 --- a/examples/Telnet.Server/Telnet.Server.csproj +++ b/examples/Telnet.Server/Telnet.Server.csproj @@ -1,9 +1,11 @@  Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/WebSockets.Client/WebSocketClientHandler.cs b/examples/WebSockets.Client/WebSocketClientHandler.cs index 6219b1b3a..04b2f7c6f 100644 --- a/examples/WebSockets.Client/WebSocketClientHandler.cs +++ b/examples/WebSockets.Client/WebSocketClientHandler.cs @@ -11,6 +11,7 @@ namespace WebSockets.Client using DotNetty.Common.Concurrency; using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public class WebSocketClientHandler : SimpleChannelInboundHandler { diff --git a/examples/WebSockets.Client/WebSockets.Client.csproj b/examples/WebSockets.Client/WebSockets.Client.csproj index 1beb17f74..cd4b150b3 100644 --- a/examples/WebSockets.Client/WebSockets.Client.csproj +++ b/examples/WebSockets.Client/WebSockets.Client.csproj @@ -2,9 +2,11 @@ Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false + Debug;Release;Package + AnyCPU win-x64 diff --git a/examples/WebSockets.Server/WebSockets.Server.csproj b/examples/WebSockets.Server/WebSockets.Server.csproj index 86c509dbf..597c37354 100644 --- a/examples/WebSockets.Server/WebSockets.Server.csproj +++ b/examples/WebSockets.Server/WebSockets.Server.csproj @@ -2,10 +2,12 @@ Exe - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 2.0.3 false true + Debug;Release;Package + AnyCPU win-x64 diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 000000000..679f1b4a0 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,23 @@ + + + + + Debug;Release;Package + AnyCPU + true + pdbonly + True + true + + + pdbonly + true + $(SolutionDir)build_output\packages + True + true + + 0.7.3 + $(PackageVersion) + + + diff --git a/src/DotNetty.Buffers/DotNetty.Buffers.csproj b/src/DotNetty.Buffers/DotNetty.Buffers.csproj index ba7da0fb5..c6d10c9b9 100644 --- a/src/DotNetty.Buffers/DotNetty.Buffers.csproj +++ b/src/DotNetty.Buffers/DotNetty.Buffers.csproj @@ -1,12 +1,12 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 true Buffer management in DotNetty © Microsoft Corporation. All rights reserved. DotNetty: buffer management en-US - 0.7.2 + 0.7.3 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs b/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs index 61680802b..a9c2fdef9 100644 --- a/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs +++ b/src/DotNetty.Buffers/UnsafeByteBufferUtil.cs @@ -386,7 +386,7 @@ internal static void SetZero(byte* addr, int length) internal static string GetString(byte* src, int length, Encoding encoding) { -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER return encoding.GetString(src, length); #else int charCount = encoding.GetCharCount(src, length); diff --git a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj index 567db2273..b6a4062f4 100644 --- a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj +++ b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 true DotNetty.Codecs.Http Http codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: Http codec en-US - 0.7.2 + 0.7.3 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Codecs.Http/WebSockets/WebSocketClientHandshaker.cs b/src/DotNetty.Codecs.Http/WebSockets/WebSocketClientHandshaker.cs index a2b32ff67..279612c96 100644 --- a/src/DotNetty.Codecs.Http/WebSockets/WebSocketClientHandshaker.cs +++ b/src/DotNetty.Codecs.Http/WebSockets/WebSocketClientHandshaker.cs @@ -11,6 +11,7 @@ namespace DotNetty.Codecs.Http.WebSockets using DotNetty.Common.Concurrency; using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public abstract class WebSocketClientHandshaker { diff --git a/src/DotNetty.Codecs.Http/WebSockets/WebSocketServerHandshaker.cs b/src/DotNetty.Codecs.Http/WebSockets/WebSocketServerHandshaker.cs index e5ec847d8..5449282eb 100644 --- a/src/DotNetty.Codecs.Http/WebSockets/WebSocketServerHandshaker.cs +++ b/src/DotNetty.Codecs.Http/WebSockets/WebSocketServerHandshaker.cs @@ -15,6 +15,7 @@ namespace DotNetty.Codecs.Http.WebSockets using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public abstract class WebSocketServerHandshaker { diff --git a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj index 7e14a1ed5..fb8cdfecc 100644 --- a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj +++ b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj @@ -1,13 +1,13 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 true DotNetty.Codecs.Mqtt MQTT codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: MQTT codec en-US - 0.7.2 + 0.7.3 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj index 4c4a6e2ff..096eee805 100644 --- a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj +++ b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj @@ -1,13 +1,13 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 true DotNetty.Codecs.Protobuf Protobuf Proto3 codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: Protobuf Proto3 codec en-US - 0.7.2 + 0.7.3 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj index 884946bde..8a00e147a 100644 --- a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj +++ b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 true DotNetty.Codecs.ProtocolBuffers ProtocolBuffers Proto2 codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: ProtocolBuffers Proto2 codec en-US - 0.7.2 + 0.7.3 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj index 586377cdb..ed156c65e 100644 --- a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj +++ b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj @@ -1,13 +1,13 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 true DotNetty.Codecs.Redis Redis codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: Redis codec en-US - 0.7.2 + 0.7.3 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs/DotNetty.Codecs.csproj b/src/DotNetty.Codecs/DotNetty.Codecs.csproj index b89c9edb6..ff6f47b93 100644 --- a/src/DotNetty.Codecs/DotNetty.Codecs.csproj +++ b/src/DotNetty.Codecs/DotNetty.Codecs.csproj @@ -1,13 +1,13 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 true DotNetty.Codecs General purpose codecs for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: codecs en-US - 0.7.2 + 0.7.3 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Common/DotNetty.Common.csproj b/src/DotNetty.Common/DotNetty.Common.csproj index 13632d123..8d06f5b8a 100644 --- a/src/DotNetty.Common/DotNetty.Common.csproj +++ b/src/DotNetty.Common/DotNetty.Common.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 true DotNetty.Common DotNetty common routines © Microsoft Corporation. All rights reserved. DotNetty: common routines en-US - 0.7.2 + 0.7.3 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs index a1dd13782..7322dc9e6 100644 --- a/src/DotNetty.Common/Utilities/HashedWheelTimer.cs +++ b/src/DotNetty.Common/Utilities/HashedWheelTimer.cs @@ -15,6 +15,7 @@ namespace DotNetty.Common.Utilities using DotNetty.Common.Concurrency; using DotNetty.Common.Internal; using DotNetty.Common.Internal.Logging; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public sealed class HashedWheelTimer : ITimer { diff --git a/src/DotNetty.Common/Utilities/TaskEx.cs b/src/DotNetty.Common/Utilities/TaskEx.cs index d0093a97d..8c2c72d98 100644 --- a/src/DotNetty.Common/Utilities/TaskEx.cs +++ b/src/DotNetty.Common/Utilities/TaskEx.cs @@ -6,6 +6,7 @@ namespace DotNetty.Common.Utilities using System; using System.Threading.Tasks; using DotNetty.Common.Concurrency; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public static class TaskEx { diff --git a/src/DotNetty.Handlers/DotNetty.Handlers.csproj b/src/DotNetty.Handlers/DotNetty.Handlers.csproj index 83fed99c9..fe1ce05ec 100644 --- a/src/DotNetty.Handlers/DotNetty.Handlers.csproj +++ b/src/DotNetty.Handlers/DotNetty.Handlers.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 true DotNetty.Handlers Application handlers for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: handlers en-US - 0.7.2 + 0.7.3 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Handlers/Streams/ChunkedWriteHandler.cs b/src/DotNetty.Handlers/Streams/ChunkedWriteHandler.cs index 438856ae5..f31bbbdf5 100644 --- a/src/DotNetty.Handlers/Streams/ChunkedWriteHandler.cs +++ b/src/DotNetty.Handlers/Streams/ChunkedWriteHandler.cs @@ -11,6 +11,7 @@ namespace DotNetty.Handlers.Streams using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public class ChunkedWriteHandler : ChannelDuplexHandler { diff --git a/src/DotNetty.Handlers/Tls/SniHandler.cs b/src/DotNetty.Handlers/Tls/SniHandler.cs index 4f7b48827..c7148ef15 100644 --- a/src/DotNetty.Handlers/Tls/SniHandler.cs +++ b/src/DotNetty.Handlers/Tls/SniHandler.cs @@ -214,7 +214,7 @@ protected override void Decode(IChannelHandlerContext context, IByteBuffer input }; hostname = idn.GetAscii(hostname); -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER // TODO: netcore does not have culture sensitive tolower() hostname = hostname.ToLowerInvariant(); #else diff --git a/src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.Net.cs b/src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.Net.cs new file mode 100644 index 000000000..b8e48babd --- /dev/null +++ b/src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.Net.cs @@ -0,0 +1,302 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#if NET5_0_OR_GREATER +namespace DotNetty.Handlers.Tls +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.Contracts; + using System.Threading; + using System.Threading.Tasks; + + partial class TlsHandler + { + sealed class MediationStreamNet : MediationStreamBase + { + readonly CompositeSource source = new(); + TaskCompletionSource readCompletionSource; + Memory sslOwnedMemory; + int readByteCount; + + public MediationStreamNet(TlsHandler owner) + : base(owner) + { + } + + public override bool SourceIsReadable => this.source.IsReadable; + public override int SourceReadableBytes => this.source.GetTotalReadableBytes(); + + public override void SetSource(byte[] source, int offset) => this.source.AddSource(source, offset); + public override void ResetSource() => this.source.ResetSources(); + + public override void ExpandSource(int count) + { + this.source.Expand(count); + + Memory sslMemory = this.sslOwnedMemory; + if (sslMemory.IsEmpty) + { + return; + } + + this.sslOwnedMemory = default; + + this.readByteCount = this.ReadFromInput(sslMemory); + // hack: this tricks SslStream's continuation to run synchronously instead of dispatching to TP. Remove once Begin/EndRead are available. + new Task( + ms => + { + var self = (MediationStreamNet)ms; + TaskCompletionSource p = self.readCompletionSource; + self.readCompletionSource = null; + p.TrySetResult(self.readByteCount); + }, + this) + .RunSynchronously(TaskScheduler.Default); + } + + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) + => this.owner.capturedContext.Executor.InEventLoop + ? this.InLoopReadAsync(buffer, cancellationToken) + : new ValueTask(this.OutOfLoopReadAsync(buffer, cancellationToken)); + + ValueTask InLoopReadAsync(Memory buffer, CancellationToken cancellationToken) + { + if (this.SourceIsReadable) + { + // we have the bytes available upfront - write out synchronously + int read = this.ReadFromInput(buffer); + return new ValueTask(read); + } + + Contract.Assert(this.sslOwnedMemory.IsEmpty); + // take note of buffer - we will pass bytes there once available + this.sslOwnedMemory = buffer; + this.readCompletionSource = new TaskCompletionSource(); + return new ValueTask(this.readCompletionSource.Task); + } + + Task OutOfLoopReadAsync(Memory buffer, CancellationToken cancellationToken) + { + return this.owner.capturedContext.Executor.SubmitAsync( + () => + { + if (this.SourceIsReadable) + { + // we have the bytes available upfront - write out synchronously + int read = this.ReadFromInput(buffer); + return Task.FromResult(read); + } + + Contract.Assert(this.sslOwnedMemory.IsEmpty); + // take note of buffer - we will pass bytes there once available + this.sslOwnedMemory = buffer; + this.readCompletionSource = new TaskCompletionSource(); + return this.readCompletionSource.Task; + }, + cancellationToken).Unwrap(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + if (this.owner.capturedContext.Executor.InEventLoop) + { + this.owner.FinishWrap(buffer, offset, count); + } + else + { + this.owner.capturedContext.Executor.Execute(() => this.owner.FinishWrap(buffer, offset, count)); + } + } + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + if (this.owner.capturedContext.Executor.InEventLoop) + { + return this.owner.FinishWrapNonAppDataAsync(buffer, offset, count); + } + + return this.owner.capturedContext.Executor.SubmitAsync( + () => this.owner.FinishWrapNonAppDataAsync(buffer, offset, count), + cancellationToken + ).Unwrap(); + } + + public override void Flush() + { + // NOOP: called on SslStream.Close + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + { + TaskCompletionSource p = this.readCompletionSource; + if (p != null) + { + this.readCompletionSource = null; + p.TrySetResult(0); + } + } + } + + int ReadFromInput(Memory destination) => this.source.Read(destination); + + #region Source + + sealed class Source + { + byte[] input; + int startOffset; + int offset; + int length; + bool retained; + + public Source(byte[] input, int offset) + { + this.input = input; + this.startOffset = offset; + this.offset = 0; + this.length = 0; + } + + public int ReadableBytes => this.length - this.offset; + + public bool IsReadable => this.ReadableBytes > 0; + + public void Expand(int count) + { + Contract.Assert(!this.retained); // Retained source is not expected to be Expanded + this.length += count; + Contract.Assert(this.length <= this.input.Length); + } + + public int Read(Memory destination) + { + int len = Math.Min(this.ReadableBytes, destination.Length); + new ReadOnlySpan(this.input, this.startOffset + this.offset, len).CopyTo(destination.Span); + this.offset += len; + return len; + } + + // This is to avoid input bytes to be discarded by ref counting mechanism + public void Retain() + { + int readableBytes = this.ReadableBytes; + if (this.retained || readableBytes <= 0) + { + return; + } + + // todo: is there a way to not discard those bytes till they are read??? If not, then use context.Allocator??? + + // Copy only readable bytes to a new buffer + byte[] copy = new byte[readableBytes]; + Buffer.BlockCopy(this.input, this.startOffset + this.offset, copy, 0, readableBytes); + this.input = copy; + + // Set both offsets to 0 and length to readableBytes (so that this.ReadableBytes stays the same) + this.startOffset = 0; + this.offset = 0; + this.length = readableBytes; + + this.retained = true; + } + } + + sealed class CompositeSource + { + // Why not List? + // 1. It's unlikely this list to grow more than 10 nodes. In fact in most cases it'll have one element only + // 2. Cleanup removes from head, so it's cheaper compared to List which shifts elements in this case. + readonly LinkedList sources = new LinkedList(); + + public bool IsReadable + { + get + { + // The composite source is readable if any readable sources, so + // it's enough to check on last one as we always AddLast + LinkedListNode last = this.sources.Last; + return last != null && last.Value.IsReadable; + } + } + + public void AddSource(byte[] input, int offset) + { + // Always add to the tail + this.sources.AddLast(new Source(input, offset)); + } + + public void Expand(int count) + { + Contract.Assert(this.sources.Last != null); // AddSource is always called before + + // Always expand the last added source + this.sources.Last.Value.Expand(count); + } + + public int GetTotalReadableBytes() + { + int count = 0; + + LinkedListNode node = this.sources.First; + while (node != null) + { + count += node.Value.ReadableBytes; + node = node.Next; + } + + return count; + } + + // Read from all readable sources to the destination starting from head (oldest) + public int Read(Memory destination) + { + int totalRead = 0; + + LinkedListNode node = this.sources.First; + while (node != null && totalRead < destination.Length) + { + Source source = node.Value; + int read = source.Read(destination.Slice(totalRead, destination.Length - totalRead)); + totalRead += read; + + if (!source.IsReadable) + { + node = node.Next; + // Do not remove the node here as it can be expanded. Instead, + // remove in the CleanUp method below + } + } + + return totalRead; + } + + // Remove all not readable sources and retain readable. Start from first as it's the oldest + public void ResetSources() + { + LinkedListNode node = this.sources.First; + while (node != null) + { + if (!node.Value.IsReadable) + { + this.sources.RemoveFirst(); + node = this.sources.First; + } + else + { + node.Value.Retain(); + node = node.Next; + } + } + } + } + + #endregion + } + } +} +#endif \ No newline at end of file diff --git a/src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.cs b/src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.cs new file mode 100644 index 000000000..580292152 --- /dev/null +++ b/src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.cs @@ -0,0 +1,338 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace DotNetty.Handlers.Tls +{ + using System; + using System.Diagnostics; + using System.Diagnostics.Contracts; + using System.IO; + using System.Runtime.ExceptionServices; + using System.Threading; + using System.Threading.Tasks; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; + + partial class TlsHandler + { + sealed class MediationStream : MediationStreamBase + { + byte[] input; + int inputStartOffset; + int inputOffset; + int inputLength; + TaskCompletionSource readCompletionSource; + ArraySegment sslOwnedBuffer; +#if NETSTANDARD2_0 || NETCOREAPP3_1 + int readByteCount; +#else + SynchronousAsyncResult syncReadResult; + AsyncCallback readCallback; + TaskCompletionSource writeCompletion; + AsyncCallback writeCallback; +#endif + + public MediationStream(TlsHandler owner) + : base(owner) + { + } + + public override int SourceReadableBytes => this.inputLength - this.inputOffset; + + public override bool SourceIsReadable => this.SourceReadableBytes > 0; + + public override void SetSource(byte[] source, int offset) + { + this.input = source; + this.inputStartOffset = offset; + this.inputOffset = 0; + this.inputLength = 0; + } + + public override void ResetSource() + { + this.input = null; + this.inputLength = 0; + this.inputOffset = 0; + } + + public override void ExpandSource(int count) + { + Contract.Assert(this.input != null); + + this.inputLength += count; + + ArraySegment sslBuffer = this.sslOwnedBuffer; + if (sslBuffer.Array == null) + { + // there is no pending read operation - keep for future + return; + } + + this.sslOwnedBuffer = default(ArraySegment); + +#if NETSTANDARD2_0 || NETCOREAPP3_1 + this.readByteCount = this.ReadFromInput(sslBuffer.Array, sslBuffer.Offset, sslBuffer.Count); + // hack: this tricks SslStream's continuation to run synchronously instead of dispatching to TP. Remove once Begin/EndRead are available. + new Task( + ms => + { + var self = (MediationStream)ms; + TaskCompletionSource p = self.readCompletionSource; + self.readCompletionSource = null; + p.TrySetResult(self.readByteCount); + }, + this) + .RunSynchronously(TaskScheduler.Default); +#else + int read = this.ReadFromInput(sslBuffer.Array, sslBuffer.Offset, sslBuffer.Count); + + TaskCompletionSource promise = this.readCompletionSource; + this.readCompletionSource = null; + promise.TrySetResult(read); + + AsyncCallback callback = this.readCallback; + this.readCallback = null; + callback?.Invoke(promise.Task); +#endif + } + +#if NETSTANDARD2_0 || NETCOREAPP3_1 + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + if (this.SourceReadableBytes > 0) + { + // we have the bytes available upfront - write out synchronously + int read = this.ReadFromInput(buffer, offset, count); + return Task.FromResult(read); + } + + Contract.Assert(this.sslOwnedBuffer.Array == null); + // take note of buffer - we will pass bytes there once available + this.sslOwnedBuffer = new ArraySegment(buffer, offset, count); + this.readCompletionSource = new TaskCompletionSource(); + return this.readCompletionSource.Task; + } +#else + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + if (this.SourceReadableBytes > 0) + { + // we have the bytes available upfront - write out synchronously + int read = this.ReadFromInput(buffer, offset, count); + var res = this.PrepareSyncReadResult(read, state); + callback?.Invoke(res); + return res; + } + + Contract.Assert(this.sslOwnedBuffer.Array == null); + // take note of buffer - we will pass bytes there once available + this.sslOwnedBuffer = new ArraySegment(buffer, offset, count); + this.readCompletionSource = new TaskCompletionSource(state); + this.readCallback = callback; + return this.readCompletionSource.Task; + } + + public override int EndRead(IAsyncResult asyncResult) + { + SynchronousAsyncResult syncResult = this.syncReadResult; + if (ReferenceEquals(asyncResult, syncResult)) + { + return syncResult.Result; + } + + Debug.Assert(this.readCompletionSource == null || this.readCompletionSource.Task == asyncResult); + Contract.Assert(!((Task)asyncResult).IsCanceled); + + try + { + return ((Task)asyncResult).Result; + } + catch (AggregateException ex) + { + ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); + throw; // unreachable + } + } + + IAsyncResult PrepareSyncReadResult(int readBytes, object state) + { + // it is safe to reuse sync result object as it can't lead to leak (no way to attach to it via handle) + SynchronousAsyncResult result = this.syncReadResult ?? (this.syncReadResult = new SynchronousAsyncResult()); + result.Result = readBytes; + result.AsyncState = state; + return result; + } +#endif + + public override void Write(byte[] buffer, int offset, int count) => this.owner.FinishWrap(buffer, offset, count); + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + => this.owner.FinishWrapNonAppDataAsync(buffer, offset, count); + +#if !(NETSTANDARD2_0 || NETCOREAPP3_1) + static readonly Action WriteCompleteCallback = HandleChannelWriteComplete; + + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + Task task = this.WriteAsync(buffer, offset, count); + switch (task.Status) + { + case TaskStatus.RanToCompletion: + // write+flush completed synchronously (and successfully) + var result = new SynchronousAsyncResult(); + result.AsyncState = state; + callback?.Invoke(result); + return result; + default: + if (callback != null || state != task.AsyncState) + { + Contract.Assert(this.writeCompletion == null); + this.writeCallback = callback; + var tcs = new TaskCompletionSource(state); + this.writeCompletion = tcs; + task.ContinueWith(WriteCompleteCallback, this, TaskContinuationOptions.ExecuteSynchronously); + return tcs.Task; + } + else + { + return task; + } + } + } + + static void HandleChannelWriteComplete(Task writeTask, object state) + { + var self = (MediationStream)state; + + AsyncCallback callback = self.writeCallback; + self.writeCallback = null; + + var promise = self.writeCompletion; + self.writeCompletion = null; + + switch (writeTask.Status) + { + case TaskStatus.RanToCompletion: + promise.TryComplete(); + break; + case TaskStatus.Canceled: + promise.TrySetCanceled(); + break; + case TaskStatus.Faulted: + promise.TrySetException(writeTask.Exception); + break; + default: + throw new ArgumentOutOfRangeException("Unexpected task status: " + writeTask.Status); + } + + callback?.Invoke(promise.Task); + } + + public override void EndWrite(IAsyncResult asyncResult) + { + if (asyncResult is SynchronousAsyncResult) + { + return; + } + + try + { + ((Task)asyncResult).Wait(); + } + catch (AggregateException ex) + { + ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); + throw; + } + } +#endif + + int ReadFromInput(byte[] destination, int destinationOffset, int destinationCapacity) + { + Contract.Assert(destination != null); + + byte[] source = this.input; + int readableBytes = this.SourceReadableBytes; + int length = Math.Min(readableBytes, destinationCapacity); + Buffer.BlockCopy(source, this.inputStartOffset + this.inputOffset, destination, destinationOffset, length); + this.inputOffset += length; + return length; + } + + public override void Flush() + { + // NOOP: called on SslStream.Close + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + { + TaskCompletionSource p = this.readCompletionSource; + if (p != null) + { + this.readCompletionSource = null; + p.TrySetResult(0); + } + } + } + + #region plumbing + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + public override bool CanRead => true; + + public override bool CanSeek => false; + + public override bool CanWrite => true; + + public override long Length + { + get { throw new NotSupportedException(); } + } + + public override long Position + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + } + + #endregion + + #region sync result + + sealed class SynchronousAsyncResult : IAsyncResult + { + public T Result { get; set; } + + public bool IsCompleted => true; + + public WaitHandle AsyncWaitHandle + { + get { throw new InvalidOperationException("Cannot wait on a synchronous result."); } + } + + public object AsyncState { get; set; } + + public bool CompletedSynchronously => true; + } + + #endregion + } + } +} \ No newline at end of file diff --git a/src/DotNetty.Handlers/Tls/TlsHandler.MediationStreamBase.cs b/src/DotNetty.Handlers/Tls/TlsHandler.MediationStreamBase.cs new file mode 100644 index 000000000..1e0c6a085 --- /dev/null +++ b/src/DotNetty.Handlers/Tls/TlsHandler.MediationStreamBase.cs @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace DotNetty.Handlers.Tls +{ + using System; + using System.IO; + + partial class TlsHandler + { + abstract class MediationStreamBase : Stream + { + protected readonly TlsHandler owner; + + public MediationStreamBase(TlsHandler owner) + { + this.owner = owner; + } + + public static MediationStreamBase Create(TlsHandler owner) + { +#if NET5_0_OR_GREATER + return new TlsHandler.MediationStreamNet(owner); +#else + return new MediationStream(owner); +#endif + } + + public abstract bool SourceIsReadable { get; } + public abstract int SourceReadableBytes { get; } + + public abstract void SetSource(byte[] source, int offset); + public abstract void ExpandSource(int count); + public abstract void ResetSource(); + + #region plumbing + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + public override bool CanRead => true; + public override bool CanSeek => false; + public override bool CanWrite => true; + public override long Length + { + get { throw new NotSupportedException(); } + } + + public override long Position + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + } + + #endregion + } + } +} \ No newline at end of file diff --git a/src/DotNetty.Handlers/Tls/TlsHandler.cs b/src/DotNetty.Handlers/Tls/TlsHandler.cs index e46d8c32f..8e4749f44 100644 --- a/src/DotNetty.Handlers/Tls/TlsHandler.cs +++ b/src/DotNetty.Handlers/Tls/TlsHandler.cs @@ -5,21 +5,19 @@ namespace DotNetty.Handlers.Tls { using System; using System.Collections.Generic; - using System.Diagnostics; using System.Diagnostics.Contracts; using System.IO; using System.Net.Security; - using System.Runtime.ExceptionServices; using System.Security.Cryptography.X509Certificates; - using System.Threading; using System.Threading.Tasks; using DotNetty.Buffers; using DotNetty.Codecs; - using DotNetty.Common.Concurrency; + using DotNetty.Common; using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; - public sealed class TlsHandler : ByteToMessageDecoder + public sealed partial class TlsHandler : ByteToMessageDecoder { readonly TlsSettings settings; const int FallbackReadBufferSize = 256; @@ -29,11 +27,12 @@ public sealed class TlsHandler : ByteToMessageDecoder static readonly Action HandshakeCompletionCallback = new Action(HandleHandshakeCompleted); readonly SslStream sslStream; - readonly MediationStream mediationStream; + readonly MediationStreamBase mediationStream; readonly TaskCompletionSource closeFuture; TlsHandlerState state; - int packetLength; + (int packetLength, byte packetContentType) packetInfo; + List<(int packetLength, byte packetContentType)> pendingDataPackets; volatile IChannelHandlerContext capturedContext; BatchingPendingWriteQueue pendingUnencryptedWrites; Task lastContextWriteTask; @@ -53,7 +52,7 @@ public TlsHandler(Func sslStreamFactory, TlsSettings settings this.settings = settings; this.closeFuture = new TaskCompletionSource(); - this.mediationStream = new MediationStream(this); + this.mediationStream = MediationStreamBase.Create(this); this.sslStream = sslStreamFactory(this.mediationStream); } @@ -118,38 +117,74 @@ bool IgnoreException(Exception t) static void HandleHandshakeCompleted(Task task, object state) { var self = (TlsHandler)state; + if (self.capturedContext.Executor.InEventLoop) + { + HandleHandshakeCompletedInternal(task, self); + } + else + { + self.capturedContext.Executor.Execute(() => HandleHandshakeCompletedInternal(task, self)); + } + } + + static void HandleHandshakeCompletedInternal(Task task, TlsHandler self) + { switch (task.Status) { case TaskStatus.RanToCompletion: - { - TlsHandlerState oldState = self.state; - - Contract.Assert(!oldState.HasAny(TlsHandlerState.AuthenticationCompleted)); - self.state = (oldState | TlsHandlerState.Authenticated) & ~(TlsHandlerState.Authenticating | TlsHandlerState.FlushedBeforeHandshake); + { + TlsHandlerState oldState = self.state; - self.capturedContext.FireUserEventTriggered(TlsHandshakeCompletionEvent.Success); + Contract.Assert(!oldState.HasAny(TlsHandlerState.AuthenticationCompleted)); + self.state = (oldState | TlsHandlerState.Authenticated) & ~(TlsHandlerState.Authenticating | TlsHandlerState.FlushedBeforeHandshake); - if (oldState.Has(TlsHandlerState.ReadRequestedBeforeAuthenticated) && !self.capturedContext.Channel.Configuration.AutoRead) + self.capturedContext.FireUserEventTriggered(TlsHandshakeCompletionEvent.Success); + + // Due to possible async execution of HandleHandshakeCompleted continuation, we need to + // Unwrap any pending app data packets in case, when read completed and no more messages in the channel. + if (self.pendingDataPackets != null && self.pendingDataPackets.Count > 0) + { + ThreadLocalObjectList output = ThreadLocalObjectList.NewInstance(); + try { - self.capturedContext.Read(); + self.Unwrap(self.capturedContext, Unpooled.Empty, 0, 0, new List<(int packetLength, byte packetContentType)>(0), output); + for (int i = 0; i < output.Count; i++) + { + self.capturedContext.FireChannelRead(output[i]); + } } - - if (oldState.Has(TlsHandlerState.FlushedBeforeHandshake)) + catch (Exception ex) { - self.Wrap(self.capturedContext); - self.capturedContext.Flush(); + throw new DecoderException(ex); + } + finally + { + output.Return(); } - break; } - case TaskStatus.Canceled: - case TaskStatus.Faulted: + + if (oldState.Has(TlsHandlerState.ReadRequestedBeforeAuthenticated) && !self.capturedContext.Channel.Configuration.AutoRead) { - // ReSharper disable once AssignNullToNotNullAttribute -- task.Exception will be present as task is faulted - TlsHandlerState oldState = self.state; - Contract.Assert(!oldState.HasAny(TlsHandlerState.Authenticated)); - self.HandleFailure(task.Exception); - break; + self.capturedContext.Read(); } + + if (oldState.Has(TlsHandlerState.FlushedBeforeHandshake)) + { + self.Wrap(self.capturedContext); + self.capturedContext.Flush(); + } + + break; + } + case TaskStatus.Canceled: + case TaskStatus.Faulted: + { + // ReSharper disable once AssignNullToNotNullAttribute -- task.Exception will be present as task is faulted + TlsHandlerState oldState = self.state; + Contract.Assert(!oldState.HasAny(TlsHandlerState.Authenticated)); + self.HandleFailure(task.Exception); + break; + } default: throw new ArgumentOutOfRangeException(nameof(task), "Unexpected task status: " + task.Status); } @@ -183,27 +218,27 @@ protected override void Decode(IChannelHandlerContext context, IByteBuffer input int offset = startOffset; int totalLength = 0; - List packetLengths; + List<(int, byte)> packetInfos; // if we calculated the length of the current SSL record before, use that information. - if (this.packetLength > 0) + if (this.packetInfo.packetLength > 0) { - if (endOffset - startOffset < this.packetLength) + if (endOffset - startOffset < this.packetInfo.packetLength) { // input does not contain a single complete SSL record return; } else { - packetLengths = new List(4); - packetLengths.Add(this.packetLength); - offset += this.packetLength; - totalLength = this.packetLength; - this.packetLength = 0; + packetInfos = new List<(int, byte)>(4); + packetInfos.Add(this.packetInfo); + offset += this.packetInfo.packetLength; + totalLength = this.packetInfo.packetLength; + this.packetInfo = default; } } else { - packetLengths = new List(4); + packetInfos = new List<(int, byte)>(4); } bool nonSslRecord = false; @@ -216,7 +251,7 @@ protected override void Decode(IChannelHandlerContext context, IByteBuffer input break; } - int encryptedPacketLength = TlsUtils.GetEncryptedPacketLength(input, offset); + int encryptedPacketLength = TlsUtils.GetEncryptedPacketLength(input, offset, out byte contentType); if (encryptedPacketLength == -1) { nonSslRecord = true; @@ -228,7 +263,7 @@ protected override void Decode(IChannelHandlerContext context, IByteBuffer input if (encryptedPacketLength > readableBytes) { // wait until the whole packet can be read - this.packetLength = encryptedPacketLength; + this.packetInfo = (encryptedPacketLength, contentType); break; } @@ -244,7 +279,7 @@ protected override void Decode(IChannelHandlerContext context, IByteBuffer input // We have a whole packet. // Increment the offset to handle the next packet. - packetLengths.Add(encryptedPacketLength); + packetInfos.Add((encryptedPacketLength, contentType)); offset += encryptedPacketLength; totalLength = newTotalLength; } @@ -263,7 +298,7 @@ protected override void Decode(IChannelHandlerContext context, IByteBuffer input // See https://github.com/netty/netty/issues/1534 input.SkipBytes(totalLength); - this.Unwrap(context, input, startOffset, totalLength, packetLengths, output); + this.Unwrap(context, input, startOffset, totalLength, packetInfos, output); if (!this.firedChannelRead) { @@ -305,11 +340,18 @@ void ReadIfNeeded(IChannelHandlerContext ctx) ctx.Read(); } } + /// Unwraps inbound SSL records. - void Unwrap(IChannelHandlerContext ctx, IByteBuffer packet, int offset, int length, List packetLengths, List output) + void Unwrap( + IChannelHandlerContext ctx, + IByteBuffer packet, + int offset, + int length, + List<(int packetLength, byte packetContentType)> packetInfos, + List output) { - Contract.Requires(packetLengths.Count > 0); + Contract.Requires(packetInfos.Count > 0 || this.pendingDataPackets != null); //bool notifyClosure = false; // todo: netty/issues/137 bool pending = false; @@ -318,17 +360,30 @@ void Unwrap(IChannelHandlerContext ctx, IByteBuffer packet, int offset, int leng try { - ArraySegment inputIoBuffer = packet.GetIoBuffer(offset, length); - this.mediationStream.SetSource(inputIoBuffer.Array, inputIoBuffer.Offset); - int packetIndex = 0; - while (!this.EnsureAuthenticated()) + if (packetInfos.Count > 0) { - this.mediationStream.ExpandSource(packetLengths[packetIndex]); - if (++packetIndex == packetLengths.Count) + ArraySegment inputIoBuffer = packet.GetIoBuffer(offset, length); + this.mediationStream.SetSource(inputIoBuffer.Array, inputIoBuffer.Offset); + + while (!this.EnsureAuthenticated()) { - return; + (int packetLength, byte type) = packetInfos[packetIndex]; + this.mediationStream.ExpandSource(packetLength); + + if (type == TlsUtils.SSL_CONTENT_TYPE_APPLICATION_DATA) + { + // Due to SslStream's implementation, it's possible that we expand after handshake completed. Hence, we + // need to make sure we call ReadFromSslStreamAsync for these packets later + this.pendingDataPackets = this.pendingDataPackets ?? new List<(int packetLength, byte packetContentType)>(8); + this.pendingDataPackets.Add((packetLength, type)); + } + + if (++packetIndex == packetInfos.Count) + { + return; + } } } @@ -353,10 +408,33 @@ void Unwrap(IChannelHandlerContext ctx, IByteBuffer packet, int offset, int leng } // go through packets one by one (because SslStream does not consume more than 1 packet at a time) - for (; packetIndex < packetLengths.Count; packetIndex++) + // account pendingDataPackets + int skipExpandPacketCount = 0; + if (this.pendingDataPackets != null) { - int currentPacketLength = packetLengths[packetIndex]; - this.mediationStream.ExpandSource(currentPacketLength); + // We already expanded the source for all pendingDataPackets, so skip expand further below + skipExpandPacketCount = this.pendingDataPackets.Count; + + // add packetLengths to pending except already processed + for (int i = packetIndex; i < packetInfos.Count; i++) + { + this.pendingDataPackets.Add(packetInfos[i]); + } + + packetInfos = this.pendingDataPackets; + this.pendingDataPackets = null; + packetIndex = 0; + } + + for (; packetIndex < packetInfos.Count; packetIndex++) + { + int currentPacketLength = packetInfos[packetIndex].packetLength; + + if (--skipExpandPacketCount < 0) + { + // For pending packets we already expended, so skip expand + this.mediationStream.ExpandSource(currentPacketLength); + } if (currentReadFuture != null) { @@ -365,12 +443,10 @@ void Unwrap(IChannelHandlerContext ctx, IByteBuffer packet, int offset, int leng if (!currentReadFuture.IsCompleted) { // we did feed the whole current packet to SslStream yet it did not produce any result -> move to the next packet in input - continue; } int read = currentReadFuture.Result; - if (read == 0) { //Stream closed @@ -382,7 +458,7 @@ void Unwrap(IChannelHandlerContext ctx, IByteBuffer packet, int offset, int leng currentReadFuture = null; outputBuffer = null; - if (this.mediationStream.SourceReadableBytes == 0) + if (!this.mediationStream.SourceIsReadable) { // we just made a frame available for reading but there was already pending read so SslStream read it out to make further progress there @@ -428,9 +504,11 @@ void Unwrap(IChannelHandlerContext ctx, IByteBuffer packet, int offset, int leng { break; } + int read = currentReadFuture.Result; AddBufferToOutput(outputBuffer, read, output); } + outputBuffer = ctx.Allocator.Buffer(FallbackReadBufferSize); currentReadFuture = this.ReadFromSslStreamAsync(outputBuffer, FallbackReadBufferSize); } @@ -514,6 +592,7 @@ public override Task WriteAsync(IChannelHandlerContext context, object message) { return TaskEx.FromException(new UnsupportedMessageTypeException(message, typeof(IByteBuffer))); } + return this.pendingUnencryptedWrites.Add(message); } @@ -569,6 +648,7 @@ void Wrap(IChannelHandlerContext context) buffer.Release(); } } + buf.ReadBytes(this.sslStream, buf.ReadableBytes); // this leads to FinishWrap being called 0+ times buf.Release(); @@ -627,7 +707,6 @@ void HandleFailure(Exception cause) { // Release all resources such as internal buffers that SSLEngine // is managing. - this.mediationStream.Dispose(); try { @@ -664,323 +743,6 @@ void NotifyHandshakeFailure(Exception cause) this.CloseAsync(this.capturedContext); } } - - sealed class MediationStream : Stream - { - readonly TlsHandler owner; - byte[] input; - int inputStartOffset; - int inputOffset; - int inputLength; - TaskCompletionSource readCompletionSource; - ArraySegment sslOwnedBuffer; -#if NETSTANDARD2_0 - int readByteCount; -#else - SynchronousAsyncResult syncReadResult; - AsyncCallback readCallback; - TaskCompletionSource writeCompletion; - AsyncCallback writeCallback; -#endif - - public MediationStream(TlsHandler owner) - { - this.owner = owner; - } - - public int SourceReadableBytes => this.inputLength - this.inputOffset; - - public void SetSource(byte[] source, int offset) - { - this.input = source; - this.inputStartOffset = offset; - this.inputOffset = 0; - this.inputLength = 0; - } - - public void ResetSource() - { - this.input = null; - this.inputLength = 0; - } - - public void ExpandSource(int count) - { - Contract.Assert(this.input != null); - - this.inputLength += count; - - ArraySegment sslBuffer = this.sslOwnedBuffer; - if (sslBuffer.Array == null) - { - // there is no pending read operation - keep for future - return; - } - this.sslOwnedBuffer = default(ArraySegment); - -#if NETSTANDARD2_0 - this.readByteCount = this.ReadFromInput(sslBuffer.Array, sslBuffer.Offset, sslBuffer.Count); - // hack: this tricks SslStream's continuation to run synchronously instead of dispatching to TP. Remove once Begin/EndRead are available. - new Task( - ms => - { - var self = (MediationStream)ms; - TaskCompletionSource p = self.readCompletionSource; - self.readCompletionSource = null; - p.TrySetResult(self.readByteCount); - }, - this) - .RunSynchronously(TaskScheduler.Default); -#else - int read = this.ReadFromInput(sslBuffer.Array, sslBuffer.Offset, sslBuffer.Count); - - TaskCompletionSource promise = this.readCompletionSource; - this.readCompletionSource = null; - promise.TrySetResult(read); - - AsyncCallback callback = this.readCallback; - this.readCallback = null; - callback?.Invoke(promise.Task); -#endif - } - -#if NETSTANDARD2_0 - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - if (this.SourceReadableBytes > 0) - { - // we have the bytes available upfront - write out synchronously - int read = this.ReadFromInput(buffer, offset, count); - return Task.FromResult(read); - } - - Contract.Assert(this.sslOwnedBuffer.Array == null); - // take note of buffer - we will pass bytes there once available - this.sslOwnedBuffer = new ArraySegment(buffer, offset, count); - this.readCompletionSource = new TaskCompletionSource(); - return this.readCompletionSource.Task; - } -#else - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) - { - if (this.SourceReadableBytes > 0) - { - // we have the bytes available upfront - write out synchronously - int read = this.ReadFromInput(buffer, offset, count); - var res = this.PrepareSyncReadResult(read, state); - callback?.Invoke(res); - return res; - } - - Contract.Assert(this.sslOwnedBuffer.Array == null); - // take note of buffer - we will pass bytes there once available - this.sslOwnedBuffer = new ArraySegment(buffer, offset, count); - this.readCompletionSource = new TaskCompletionSource(state); - this.readCallback = callback; - return this.readCompletionSource.Task; - } - - public override int EndRead(IAsyncResult asyncResult) - { - SynchronousAsyncResult syncResult = this.syncReadResult; - if (ReferenceEquals(asyncResult, syncResult)) - { - return syncResult.Result; - } - - Debug.Assert(this.readCompletionSource == null || this.readCompletionSource.Task == asyncResult); - Contract.Assert(!((Task)asyncResult).IsCanceled); - - try - { - return ((Task)asyncResult).Result; - } - catch (AggregateException ex) - { - ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); - throw; // unreachable - } - } - - IAsyncResult PrepareSyncReadResult(int readBytes, object state) - { - // it is safe to reuse sync result object as it can't lead to leak (no way to attach to it via handle) - SynchronousAsyncResult result = this.syncReadResult ?? (this.syncReadResult = new SynchronousAsyncResult()); - result.Result = readBytes; - result.AsyncState = state; - return result; - } -#endif - - public override void Write(byte[] buffer, int offset, int count) => this.owner.FinishWrap(buffer, offset, count); - - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - => this.owner.FinishWrapNonAppDataAsync(buffer, offset, count); - -#if !NETSTANDARD2_0 - static readonly Action WriteCompleteCallback = HandleChannelWriteComplete; - - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) - { - Task task = this.WriteAsync(buffer, offset, count); - switch (task.Status) - { - case TaskStatus.RanToCompletion: - // write+flush completed synchronously (and successfully) - var result = new SynchronousAsyncResult(); - result.AsyncState = state; - callback?.Invoke(result); - return result; - default: - if (callback != null || state != task.AsyncState) - { - Contract.Assert(this.writeCompletion == null); - this.writeCallback = callback; - var tcs = new TaskCompletionSource(state); - this.writeCompletion = tcs; - task.ContinueWith(WriteCompleteCallback, this, TaskContinuationOptions.ExecuteSynchronously); - return tcs.Task; - } - else - { - return task; - } - } - } - - static void HandleChannelWriteComplete(Task writeTask, object state) - { - var self = (MediationStream)state; - - AsyncCallback callback = self.writeCallback; - self.writeCallback = null; - - var promise = self.writeCompletion; - self.writeCompletion = null; - - switch (writeTask.Status) - { - case TaskStatus.RanToCompletion: - promise.TryComplete(); - break; - case TaskStatus.Canceled: - promise.TrySetCanceled(); - break; - case TaskStatus.Faulted: - promise.TrySetException(writeTask.Exception); - break; - default: - throw new ArgumentOutOfRangeException("Unexpected task status: " + writeTask.Status); - } - - callback?.Invoke(promise.Task); - } - - public override void EndWrite(IAsyncResult asyncResult) - { - if (asyncResult is SynchronousAsyncResult) - { - return; - } - - try - { - ((Task)asyncResult).Wait(); - } - catch (AggregateException ex) - { - ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); - throw; - } - } -#endif - - int ReadFromInput(byte[] destination, int destinationOffset, int destinationCapacity) - { - Contract.Assert(destination != null); - - byte[] source = this.input; - int readableBytes = this.SourceReadableBytes; - int length = Math.Min(readableBytes, destinationCapacity); - Buffer.BlockCopy(source, this.inputStartOffset + this.inputOffset, destination, destinationOffset, length); - this.inputOffset += length; - return length; - } - - public override void Flush() - { - // NOOP: called on SslStream.Close - } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - if (disposing) - { - TaskCompletionSource p = this.readCompletionSource; - if (p != null) - { - this.readCompletionSource = null; - p.TrySetResult(0); - } - } - } - -#region plumbing - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException(); - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - public override int Read(byte[] buffer, int offset, int count) - { - throw new NotSupportedException(); - } - - public override bool CanRead => true; - - public override bool CanSeek => false; - - public override bool CanWrite => true; - - public override long Length - { - get { throw new NotSupportedException(); } - } - - public override long Position - { - get { throw new NotSupportedException(); } - set { throw new NotSupportedException(); } - } - -#endregion - -#region sync result - sealed class SynchronousAsyncResult : IAsyncResult - { - public T Result { get; set; } - - public bool IsCompleted => true; - - public WaitHandle AsyncWaitHandle - { - get { throw new InvalidOperationException("Cannot wait on a synchronous result."); } - } - - public object AsyncState { get; set; } - - public bool CompletedSynchronously => true; - } - -#endregion - } } [Flags] diff --git a/src/DotNetty.Handlers/Tls/TlsUtils.cs b/src/DotNetty.Handlers/Tls/TlsUtils.cs index c271c823e..bfc8d802b 100644 --- a/src/DotNetty.Handlers/Tls/TlsUtils.cs +++ b/src/DotNetty.Handlers/Tls/TlsUtils.cs @@ -53,12 +53,13 @@ static class TlsUtils /// The length of the encrypted packet that is included in the buffer. This will /// return -1 if the given is not encrypted at all. /// - public static int GetEncryptedPacketLength(IByteBuffer buffer, int offset) + public static int GetEncryptedPacketLength(IByteBuffer buffer, int offset, out byte contentType) { int packetLength = 0; // SSLv3 or TLS - Check ContentType - switch (buffer.GetByte(offset)) + contentType = buffer.GetByte(offset); + switch (contentType) { case SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC: case SSL_CONTENT_TYPE_ALERT: @@ -90,6 +91,11 @@ public static int GetEncryptedPacketLength(IByteBuffer buffer, int offset) return packetLength; } + public static int GetEncryptedPacketLength(IByteBuffer buffer, int offset) + { + return GetEncryptedPacketLength(buffer, offset, out _); + } + public static void NotifyHandshakeFailure(IChannelHandlerContext ctx, Exception cause) { // We have may haven written some parts of data before an exception was thrown so ensure we always flush. @@ -98,5 +104,23 @@ public static void NotifyHandshakeFailure(IChannelHandlerContext ctx, Exception ctx.FireUserEventTriggered(new TlsHandshakeCompletionEvent(cause)); ctx.CloseAsync(); } + + public static string FormatContentType(byte contentType) + { + switch (contentType) + { + case SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC: + return nameof(SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC); + case SSL_CONTENT_TYPE_ALERT: + return nameof(SSL_CONTENT_TYPE_ALERT); + case SSL_CONTENT_TYPE_HANDSHAKE: + return nameof(SSL_CONTENT_TYPE_HANDSHAKE); + case SSL_CONTENT_TYPE_APPLICATION_DATA: + return nameof(SSL_CONTENT_TYPE_APPLICATION_DATA); + default: + // SSLv2 or bad data + return "non-ssl"; + } + } } } \ No newline at end of file diff --git a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj index b9abbe773..50241fc5e 100644 --- a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj +++ b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 true DotNetty.Transport.Libuv Libuv transport model in DotNetty © Microsoft Corporation. All rights reserved. DotNetty: libuv transport model Experimental en-US - 0.7.2 + 0.7.3 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Transport.Libuv/LoopExecutor.cs b/src/DotNetty.Transport.Libuv/LoopExecutor.cs index 69ffa8f26..51585e41b 100644 --- a/src/DotNetty.Transport.Libuv/LoopExecutor.cs +++ b/src/DotNetty.Transport.Libuv/LoopExecutor.cs @@ -19,6 +19,7 @@ namespace DotNetty.Transport.Libuv using DotNetty.Common; using DotNetty.Transport.Libuv.Native; using Timer = Native.Timer; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; class LoopExecutor : AbstractScheduledEventExecutor { diff --git a/src/DotNetty.Transport.Libuv/Native/NativeMethods.cs b/src/DotNetty.Transport.Libuv/Native/NativeMethods.cs index 73d437b30..8ff9b1700 100644 --- a/src/DotNetty.Transport.Libuv/Native/NativeMethods.cs +++ b/src/DotNetty.Transport.Libuv/Native/NativeMethods.cs @@ -331,7 +331,7 @@ internal static IPEndPoint TcpGetSocketName(IntPtr handle) { Debug.Assert(handle != IntPtr.Zero); -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER int namelen = Marshal.SizeOf(); #else int namelen = Marshal.SizeOf(typeof(sockaddr)); @@ -344,7 +344,7 @@ internal static IPEndPoint TcpGetPeerName(IntPtr handle) { Debug.Assert(handle != IntPtr.Zero); -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER int namelen = Marshal.SizeOf(); #else int namelen = Marshal.SizeOf(typeof(sockaddr)); @@ -354,7 +354,7 @@ internal static IPEndPoint TcpGetPeerName(IntPtr handle) return sockaddr.GetIPEndPoint(); } -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER internal static IntPtr Allocate(int size) => Marshal.AllocCoTaskMem(size); internal static void FreeMemory(IntPtr ptr) => Marshal.FreeCoTaskMem(ptr); diff --git a/src/DotNetty.Transport.Libuv/Native/WindowsApi.cs b/src/DotNetty.Transport.Libuv/Native/WindowsApi.cs index 12b4307b9..0db29ea23 100644 --- a/src/DotNetty.Transport.Libuv/Native/WindowsApi.cs +++ b/src/DotNetty.Transport.Libuv/Native/WindowsApi.cs @@ -41,7 +41,7 @@ public void DetachFromIOCP(NativeHandle handle) IntPtr socket = IntPtr.Zero; NativeMethods.uv_fileno(handle.Handle, ref socket); -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER uint len = (uint)Marshal.SizeOf(); #else uint len = (uint)Marshal.SizeOf(typeof(FILE_COMPLETION_INFORMATION)); diff --git a/src/DotNetty.Transport.Libuv/Native/WriteRequest.cs b/src/DotNetty.Transport.Libuv/Native/WriteRequest.cs index 169e68d65..975b66532 100644 --- a/src/DotNetty.Transport.Libuv/Native/WriteRequest.cs +++ b/src/DotNetty.Transport.Libuv/Native/WriteRequest.cs @@ -26,7 +26,7 @@ sealed class WriteRequest : NativeRequest, ChannelOutboundBuffer.IMessageProcess static WriteRequest() { -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER BufferSize = Marshal.SizeOf(); #else BufferSize = Marshal.SizeOf(typeof(uv_buf_t)); diff --git a/src/DotNetty.Transport.Libuv/NativeChannel.cs b/src/DotNetty.Transport.Libuv/NativeChannel.cs index b77764a1a..a75ad7e9a 100644 --- a/src/DotNetty.Transport.Libuv/NativeChannel.cs +++ b/src/DotNetty.Transport.Libuv/NativeChannel.cs @@ -13,6 +13,7 @@ namespace DotNetty.Transport.Libuv using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; using DotNetty.Transport.Libuv.Native; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public abstract class NativeChannel : AbstractChannel { diff --git a/src/DotNetty.Transport.Libuv/WorkerEventLoop.cs b/src/DotNetty.Transport.Libuv/WorkerEventLoop.cs index 214818460..e891ba887 100644 --- a/src/DotNetty.Transport.Libuv/WorkerEventLoop.cs +++ b/src/DotNetty.Transport.Libuv/WorkerEventLoop.cs @@ -15,6 +15,7 @@ namespace DotNetty.Transport.Libuv using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; using DotNetty.Transport.Libuv.Native; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; sealed class WorkerEventLoop : LoopExecutor, IEventLoop { diff --git a/src/DotNetty.Transport/Bootstrapping/AbstractBootstrap.cs b/src/DotNetty.Transport/Bootstrapping/AbstractBootstrap.cs index 5dd26ddb1..7dad976a8 100644 --- a/src/DotNetty.Transport/Bootstrapping/AbstractBootstrap.cs +++ b/src/DotNetty.Transport/Bootstrapping/AbstractBootstrap.cs @@ -14,6 +14,7 @@ namespace DotNetty.Transport.Bootstrapping using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; /// /// This is a helper class that makes it easy to bootstrap an . It supports method- diff --git a/src/DotNetty.Transport/Bootstrapping/Bootstrap.cs b/src/DotNetty.Transport/Bootstrapping/Bootstrap.cs index 689afcbeb..f543a012f 100644 --- a/src/DotNetty.Transport/Bootstrapping/Bootstrap.cs +++ b/src/DotNetty.Transport/Bootstrapping/Bootstrap.cs @@ -13,6 +13,7 @@ namespace DotNetty.Transport.Bootstrapping using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; /// /// A that makes it easy to bootstrap an to use for clients. diff --git a/src/DotNetty.Transport/Channels/AbstractChannel.cs b/src/DotNetty.Transport/Channels/AbstractChannel.cs index 10f06f7a5..6e8f8aff0 100644 --- a/src/DotNetty.Transport/Channels/AbstractChannel.cs +++ b/src/DotNetty.Transport/Channels/AbstractChannel.cs @@ -13,6 +13,7 @@ namespace DotNetty.Transport.Channels using DotNetty.Common.Concurrency; using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public abstract class AbstractChannel : DefaultAttributeMap, IChannel { diff --git a/src/DotNetty.Transport/Channels/AbstractChannelHandlerContext.cs b/src/DotNetty.Transport/Channels/AbstractChannelHandlerContext.cs index 6401d5c1f..300875131 100644 --- a/src/DotNetty.Transport/Channels/AbstractChannelHandlerContext.cs +++ b/src/DotNetty.Transport/Channels/AbstractChannelHandlerContext.cs @@ -14,6 +14,7 @@ namespace DotNetty.Transport.Channels using DotNetty.Common.Concurrency; using DotNetty.Common.Internal; using DotNetty.Common.Utilities; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; abstract class AbstractChannelHandlerContext : IChannelHandlerContext, IResourceLeakHint { diff --git a/src/DotNetty.Transport/Channels/BatchingPendingWriteQueue.cs b/src/DotNetty.Transport/Channels/BatchingPendingWriteQueue.cs index 8d2fc2278..5896fbcf9 100644 --- a/src/DotNetty.Transport/Channels/BatchingPendingWriteQueue.cs +++ b/src/DotNetty.Transport/Channels/BatchingPendingWriteQueue.cs @@ -11,6 +11,7 @@ namespace DotNetty.Transport.Channels using DotNetty.Common.Concurrency; using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; /// /// A queue of write operations which are pending for later execution. It also updates the diff --git a/src/DotNetty.Transport/Channels/DefaultChannelPipeline.cs b/src/DotNetty.Transport/Channels/DefaultChannelPipeline.cs index 1390b7a01..1473e5cc0 100644 --- a/src/DotNetty.Transport/Channels/DefaultChannelPipeline.cs +++ b/src/DotNetty.Transport/Channels/DefaultChannelPipeline.cs @@ -16,6 +16,7 @@ namespace DotNetty.Transport.Channels using DotNetty.Common.Concurrency; using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; + using ReferenceEqualityComparer = DotNetty.Common.Utilities.ReferenceEqualityComparer; public class DefaultChannelPipeline : IChannelPipeline { diff --git a/src/DotNetty.Transport/Channels/Embedded/EmbeddedChannel.cs b/src/DotNetty.Transport/Channels/Embedded/EmbeddedChannel.cs index d3bd4ca07..543d0a6d9 100644 --- a/src/DotNetty.Transport/Channels/Embedded/EmbeddedChannel.cs +++ b/src/DotNetty.Transport/Channels/Embedded/EmbeddedChannel.cs @@ -14,7 +14,7 @@ namespace DotNetty.Transport.Channels.Embedded using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; - public class EmbeddedChannel : AbstractChannel + public class EmbeddedChannel : AbstractChannel, IEmbeddedChannel { static readonly EndPoint LOCAL_ADDRESS = new EmbeddedSocketAddress(); static readonly EndPoint REMOTE_ADDRESS = new EmbeddedSocketAddress(); diff --git a/src/DotNetty.Transport/Channels/Embedded/IEmbeddedChannel.cs b/src/DotNetty.Transport/Channels/Embedded/IEmbeddedChannel.cs new file mode 100644 index 000000000..5cd9917e4 --- /dev/null +++ b/src/DotNetty.Transport/Channels/Embedded/IEmbeddedChannel.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace DotNetty.Transport.Channels.Embedded +{ + public interface IEmbeddedChannel : IChannel + { + bool WriteInbound(params object[] msgs); + + bool WriteOutbound(params object[] msgs); + + T ReadInbound(); + + T ReadOutbound(); + + bool Finish(); + } +} \ No newline at end of file diff --git a/src/DotNetty.Transport/Channels/Embedded/SingleThreadedEmbeddedChannel.cs b/src/DotNetty.Transport/Channels/Embedded/SingleThreadedEmbeddedChannel.cs new file mode 100644 index 000000000..b3a51d642 --- /dev/null +++ b/src/DotNetty.Transport/Channels/Embedded/SingleThreadedEmbeddedChannel.cs @@ -0,0 +1,468 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace DotNetty.Transport.Channels.Embedded +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.Contracts; + using System.Net; + using System.Runtime.ExceptionServices; + using System.Threading.Tasks; + using DotNetty.Common; + using DotNetty.Common.Internal.Logging; + using DotNetty.Common.Utilities; + + public class SingleThreadedEmbeddedChannel : AbstractChannel, IEmbeddedChannel + { + static readonly EndPoint LOCAL_ADDRESS = new EmbeddedSocketAddress(); + static readonly EndPoint REMOTE_ADDRESS = new EmbeddedSocketAddress(); + + enum State + { + Open, + Active, + Closed + }; + + static readonly IChannelHandler[] EMPTY_HANDLERS = new IChannelHandler[0]; + + static readonly IInternalLogger logger = InternalLoggerFactory.GetInstance(); + + static readonly ChannelMetadata METADATA_NO_DISCONNECT = new ChannelMetadata(false); + static readonly ChannelMetadata METADATA_DISCONNECT = new ChannelMetadata(true); + + readonly IEventLoop loop = new SingleThreadEventLoop(); + + Queue inboundMessages; + Queue outboundMessages; + Exception lastException; + State state; + + /// + /// Create a new instance with an empty pipeline. + /// + public SingleThreadedEmbeddedChannel(IEventLoop eventLoop = null) + : this(EmbeddedChannelId.Instance, eventLoop, EMPTY_HANDLERS) + { + } + + /// + /// Create a new instance with an empty pipeline with the specified . + /// + /// The of this channel. + public SingleThreadedEmbeddedChannel(IChannelId channelId, IEventLoop eventLoop = null) + : this(channelId, eventLoop, EMPTY_HANDLERS) + { + } + + /// + /// Create a new instance with the pipeline initialized with the specified handlers. + /// + /// + /// The s that will be added to the + /// + public SingleThreadedEmbeddedChannel(IEventLoop eventLoop = null, params IChannelHandler[] handlers) + : this(EmbeddedChannelId.Instance, eventLoop, handlers) + { + } + + public SingleThreadedEmbeddedChannel(IChannelId id, IEventLoop eventLoop = null, params IChannelHandler[] handlers) + : this(id, false, eventLoop, handlers) + { + } + + /// Create a new instance with the pipeline initialized with the specified handlers. + /// The of this channel. + /// + /// false if this will delegate + /// to , true otherwise. + /// + /// + /// The s that will be added to the + /// + public SingleThreadedEmbeddedChannel(IChannelId id, bool hasDisconnect, IEventLoop eventLoop = null, params IChannelHandler[] handlers) + : this(id, hasDisconnect, true, eventLoop, handlers) + { } + + public SingleThreadedEmbeddedChannel(IChannelId id, bool hasDisconnect, bool register, IEventLoop eventLoop = null, params IChannelHandler[] handlers) + : base(null, id) + { + if (eventLoop != null) + { + this.loop = eventLoop; + } + + this.Metadata = GetMetadata(hasDisconnect); + this.Configuration = new DefaultChannelConfiguration(this); + this.Setup(register, handlers); + } + + public SingleThreadedEmbeddedChannel(IChannelId id, bool hasDisconnect, IChannelConfiguration config, IEventLoop eventLoop = null, + params IChannelHandler[] handlers) + : base(null, id) + { + Contract.Requires(config != null); + + if (eventLoop != null) + { + this.loop = eventLoop; + } + this.Metadata = GetMetadata(hasDisconnect); + this.Configuration = config; + this.Setup(true, handlers); + } + + static ChannelMetadata GetMetadata(bool hasDisconnect) => hasDisconnect ? METADATA_DISCONNECT : METADATA_NO_DISCONNECT; + + void Setup(bool register, params IChannelHandler[] handlers) + { + Contract.Requires(handlers != null); + + IChannelPipeline p = this.Pipeline; + p.AddLast(new ActionChannelInitializer(channel => + { + IChannelPipeline pipeline = channel.Pipeline; + foreach (IChannelHandler h in handlers) + { + if (h == null) + { + break; + + } + pipeline.AddLast(h); + } + })); + + if (register) + { + Task future = this.loop.RegisterAsync(this); + future.GetAwaiter().GetResult(); + Debug.Assert(future.IsCompleted); + } + } + + public void Register() + { + Task future = this.loop.RegisterAsync(this); + // Debug.Assert(future.IsCompleted); + this.Pipeline.AddLast(new LastInboundHandler(this.InboundMessages, this.RecordException)); + future.GetAwaiter().GetResult(); + } + + protected sealed override DefaultChannelPipeline NewChannelPipeline() => new SingleThreadedEmbeddedChannelPipeline(this); + + public override ChannelMetadata Metadata { get; } + + public override IChannelConfiguration Configuration { get; } + + /// + /// Returns the which holds all of the s that + /// were received by this . + /// + public Queue InboundMessages => this.inboundMessages ?? (this.inboundMessages = new Queue()); + + /// + /// Returns the which holds all of the s that + /// were written by this . + /// + public Queue OutboundMessages => this.outboundMessages ?? (this.outboundMessages = new Queue()); + + /// + /// Return received data from this . + /// + public T ReadInbound() => (T)Poll(this.inboundMessages); + + /// + /// Read data from the outbound. This may return null if nothing is readable. + /// + public T ReadOutbound() => (T)Poll(this.outboundMessages); + + protected override EndPoint LocalAddressInternal => this.Active ? LOCAL_ADDRESS : null; + + protected override EndPoint RemoteAddressInternal => this.Active ? REMOTE_ADDRESS : null; + + protected override IChannelUnsafe NewUnsafe() => new DefaultUnsafe(this); + + protected override bool IsCompatible(IEventLoop eventLoop) => true; + + protected override void DoBind(EndPoint localAddress) + { + //NOOP + } + + protected override void DoRegister() => this.state = State.Active; + + protected override void DoDisconnect() => this.DoClose(); + + protected override void DoClose() => this.state = State.Closed; + + protected override void DoBeginRead() + { + //NOOP + } + + protected override void DoWrite(ChannelOutboundBuffer input) + { + for (;;) + { + object msg = input.Current; + if (msg == null) + { + break; + } + + ReferenceCountUtil.Retain(msg); + this.OutboundMessages.Enqueue(msg); + input.Remove(); + } + } + + public override bool Open => this.state != State.Closed; + + public override bool Active => this.state == State.Active; + + /// + /// Write messages to the inbound of this + /// + /// The messages to be written. + /// true if the write operation did add something to the inbound buffer + public bool WriteInbound(params object[] msgs) + { + this.EnsureOpen(); + if (msgs.Length == 0) + { + return IsNotEmpty(this.inboundMessages); + } + + IChannelPipeline p = this.Pipeline; + foreach (object m in msgs) + { + p.FireChannelRead(m); + } + p.FireChannelReadComplete(); + this.CheckException(); + return IsNotEmpty(this.inboundMessages); + } + + /// + /// Write messages to the outbound of this . + /// + /// The messages to be written. + /// true if the write operation did add something to the inbound buffer + public bool WriteOutbound(params object[] msgs) + { + this.EnsureOpen(); + if (msgs.Length == 0) + { + return IsNotEmpty(this.outboundMessages); + } + + ThreadLocalObjectList futures = ThreadLocalObjectList.NewInstance(msgs.Length); + + foreach (object m in msgs) + { + if (m == null) + { + break; + } + futures.Add(this.WriteAsync(m)); + } + this.Flush(); + + int size = futures.Count; + for (int i = 0; i < size; i++) + { + var future = (Task)futures[i]; + if (future.IsCompleted) + { + this.RecordException(future); + } + else + { + // The write may be delayed to run later by runPendingTasks() + future.ContinueWith(t => this.RecordException(t)); + } + } + futures.Return(); + + this.CheckException(); + return IsNotEmpty(this.outboundMessages); + } + + void RecordException(Task future) + { + switch (future.Status) + { + case TaskStatus.Canceled: + case TaskStatus.Faulted: + this.RecordException(future.Exception); + break; + default: + break; + } + } + + void RecordException(Exception cause) + { + if (this.lastException == null) + { + this.lastException = cause; + } + else + { + logger.Warn("More than one exception was raised. " + "Will report only the first one and log others.", cause); + } + } + + /// + /// Mark this as finished. Any further try to write data to it will fail. + /// + /// bufferReadable returns true + public bool Finish() => this.Finish(false); + + /// + /// Marks this as finished and releases all pending message in the inbound and outbound + /// buffer. Any futher try to write data to it will fail. + /// + /// true if any of the used buffers has something left to read, otherwise false. + public bool FinishAndReleaseAll() => this.Finish(true); + + /// + /// Marks this as finished. Any futher attempt to write data to it will fail. + /// + /// If true, all pending messages in the inbound and outbound buffer are released. + /// true if any of the used buffers has something left to read, otherwise false. + bool Finish(bool releaseAll) + { + this.CloseSafe(); + try + { + this.CheckException(); + return IsNotEmpty(this.inboundMessages) || IsNotEmpty(this.outboundMessages); + } + finally + { + if (releaseAll) + { + ReleaseAll(this.inboundMessages); + ReleaseAll(this.outboundMessages); + } + } + } + + /// + /// Releases all buffered inbound messages. + /// + /// true if any were in the inbound buffer, otherwise false. + public bool ReleaseInbound() => ReleaseAll(this.inboundMessages); + + /// + /// Releases all buffered outbound messages. + /// + /// true if any were in the outbound buffer, otherwise false. + public bool ReleaseOutbound() => ReleaseAll(this.outboundMessages); + + static bool ReleaseAll(Queue queue) + { + if (queue != null && queue.Count > 0) + { + for (;;) + { + if (queue.Count == 0) + { + break; + } + object msg = queue.Dequeue(); + ReferenceCountUtil.Release(msg); + } + return true; + } + return false; + } + + public override Task CloseAsync() + { + // We need to call RunPendingTasks() before calling super.CloseAsync() as there may be something in the queue + // that needs to be run before the actual close takes place. + Task future = base.CloseAsync(); + return future; + } + + public override Task DisconnectAsync() + { + Task future = base.DisconnectAsync(); + return future; + } + + static bool IsNotEmpty(Queue queue) => queue != null && queue.Count > 0; + + /// + /// Check to see if there was any and rethrow if so. + /// + public void CheckException() + { + Exception e = this.lastException; + if (e == null) + { + return; + } + + this.lastException = null; + ExceptionDispatchInfo.Capture(e).Throw(); + } + + /// + /// Ensure the is open and if not throw an exception. + /// + protected void EnsureOpen() + { + if (!this.Open) + { + this.RecordException(new ClosedChannelException()); + this.CheckException(); + } + } + + static object Poll(Queue queue) => IsNotEmpty(queue) ? queue.Dequeue() : null; + + class DefaultUnsafe : AbstractUnsafe + { + public DefaultUnsafe(AbstractChannel channel) + : base(channel) + { + } + + public override Task ConnectAsync(EndPoint remoteAddress, EndPoint localAddress) => TaskEx.Completed; + } + + internal sealed class LastInboundHandler : ChannelHandlerAdapter + { + readonly Queue inboundMessages; + readonly Action recordException; + + public LastInboundHandler(Queue inboundMessages, Action recordException) + { + this.inboundMessages = inboundMessages; + this.recordException = recordException; + } + + public override void ChannelRead(IChannelHandlerContext context, object message) => this.inboundMessages.Enqueue(message); + + public override void ExceptionCaught(IChannelHandlerContext context, Exception exception) => this.recordException(exception); + } + + sealed class SingleThreadedEmbeddedChannelPipeline : DefaultChannelPipeline + { + public SingleThreadedEmbeddedChannelPipeline(SingleThreadedEmbeddedChannel channel) + : base(channel) + { + } + + protected override void OnUnhandledInboundException(Exception cause) => ((SingleThreadedEmbeddedChannel)this.Channel).RecordException(cause); + + protected override void OnUnhandledInboundMessage(object msg) => ((SingleThreadedEmbeddedChannel)this.Channel).InboundMessages.Enqueue(msg); + } + } +} \ No newline at end of file diff --git a/src/DotNetty.Transport/Channels/Local/LocalChannel.cs b/src/DotNetty.Transport/Channels/Local/LocalChannel.cs index ac466d56c..3c1decd26 100644 --- a/src/DotNetty.Transport/Channels/Local/LocalChannel.cs +++ b/src/DotNetty.Transport/Channels/Local/LocalChannel.cs @@ -13,6 +13,7 @@ namespace DotNetty.Transport.Channels.Local using DotNetty.Common.Internal; using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; /// /// A for the local transport. diff --git a/src/DotNetty.Transport/Channels/PendingWriteQueue.cs b/src/DotNetty.Transport/Channels/PendingWriteQueue.cs index 80441bb22..568fc0f54 100644 --- a/src/DotNetty.Transport/Channels/PendingWriteQueue.cs +++ b/src/DotNetty.Transport/Channels/PendingWriteQueue.cs @@ -11,6 +11,7 @@ namespace DotNetty.Transport.Channels using DotNetty.Common.Concurrency; using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; /// /// A queue of write operations which are pending for later execution. It also updates the writability of the diff --git a/src/DotNetty.Transport/Channels/Sockets/AbstractSocketByteChannel.cs b/src/DotNetty.Transport/Channels/Sockets/AbstractSocketByteChannel.cs index e297a8b08..e42c32018 100644 --- a/src/DotNetty.Transport/Channels/Sockets/AbstractSocketByteChannel.cs +++ b/src/DotNetty.Transport/Channels/Sockets/AbstractSocketByteChannel.cs @@ -154,7 +154,7 @@ protected override void ScheduleSocketRead() { SocketChannelAsyncOperation operation = this.ReadOperation; bool pending; -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER pending = this.Socket.ReceiveAsync(operation); #else if (ExecutionContext.IsFlowSuppressed()) @@ -308,7 +308,7 @@ protected bool IncompleteWrite(bool scheduleAsync, SocketChannelAsyncOperation o this.SetState(StateFlags.WriteScheduled); bool pending; -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER pending = this.Socket.SendAsync(operation); #else if (ExecutionContext.IsFlowSuppressed()) diff --git a/src/DotNetty.Transport/Channels/Sockets/AbstractSocketChannel.cs b/src/DotNetty.Transport/Channels/Sockets/AbstractSocketChannel.cs index c5da05692..dab11317a 100644 --- a/src/DotNetty.Transport/Channels/Sockets/AbstractSocketChannel.cs +++ b/src/DotNetty.Transport/Channels/Sockets/AbstractSocketChannel.cs @@ -12,6 +12,7 @@ namespace DotNetty.Transport.Channels.Sockets using DotNetty.Common.Concurrency; using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public abstract class AbstractSocketChannel : AbstractChannel { diff --git a/src/DotNetty.Transport/Channels/Sockets/IDatagramChannel.cs b/src/DotNetty.Transport/Channels/Sockets/IDatagramChannel.cs index a8046c52f..7e5e43ea5 100644 --- a/src/DotNetty.Transport/Channels/Sockets/IDatagramChannel.cs +++ b/src/DotNetty.Transport/Channels/Sockets/IDatagramChannel.cs @@ -7,6 +7,7 @@ namespace DotNetty.Transport.Channels.Sockets using System.Net.NetworkInformation; using System.Threading.Tasks; using DotNetty.Common.Concurrency; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public interface IDatagramChannel : IChannel { diff --git a/src/DotNetty.Transport/Channels/Sockets/SocketDatagramChannel.cs b/src/DotNetty.Transport/Channels/Sockets/SocketDatagramChannel.cs index 4696a4ab2..82a49dc6c 100644 --- a/src/DotNetty.Transport/Channels/Sockets/SocketDatagramChannel.cs +++ b/src/DotNetty.Transport/Channels/Sockets/SocketDatagramChannel.cs @@ -16,6 +16,7 @@ namespace DotNetty.Transport.Channels.Sockets using DotNetty.Common.Concurrency; using DotNetty.Common.Internal.Logging; using DotNetty.Common.Utilities; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public class SocketDatagramChannel : AbstractSocketMessageChannel, IDatagramChannel { @@ -115,7 +116,7 @@ protected override void ScheduleSocketRead() operation.SetBuffer(bytes.Array, bytes.Offset, bytes.Count); bool pending; -#if NETSTANDARD2_0 +#if NETSTANDARD2_0 || NETCOREAPP3_1_OR_GREATER || NET5_0_OR_GREATER pending = this.Socket.ReceiveFromAsync(operation); #else if (ExecutionContext.IsFlowSuppressed()) diff --git a/src/DotNetty.Transport/Channels/Sockets/TcpSocketChannel.cs b/src/DotNetty.Transport/Channels/Sockets/TcpSocketChannel.cs index 4e6b2fef1..8d7b843d5 100644 --- a/src/DotNetty.Transport/Channels/Sockets/TcpSocketChannel.cs +++ b/src/DotNetty.Transport/Channels/Sockets/TcpSocketChannel.cs @@ -10,6 +10,7 @@ namespace DotNetty.Transport.Channels.Sockets using System.Threading.Tasks; using DotNetty.Buffers; using DotNetty.Common.Concurrency; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; /// /// which uses Socket-based implementation. diff --git a/src/DotNetty.Transport/Channels/Util.cs b/src/DotNetty.Transport/Channels/Util.cs index 105860e87..0b7849c80 100644 --- a/src/DotNetty.Transport/Channels/Util.cs +++ b/src/DotNetty.Transport/Channels/Util.cs @@ -7,6 +7,7 @@ namespace DotNetty.Transport.Channels using System.Threading.Tasks; using DotNetty.Common.Concurrency; using DotNetty.Common.Internal.Logging; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; static class Util { diff --git a/src/DotNetty.Transport/DotNetty.Transport.csproj b/src/DotNetty.Transport/DotNetty.Transport.csproj index 6530c18db..e4488c989 100644 --- a/src/DotNetty.Transport/DotNetty.Transport.csproj +++ b/src/DotNetty.Transport/DotNetty.Transport.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472 + netstandard2.0;net472;net5;net6 true DotNetty.Transport Transport model in DotNetty © Microsoft Corporation. All rights reserved. DotNetty: transport model en-US - 0.7.2 + 0.7.3 Microsoft $(NoWarn);CS1591 false diff --git a/src/shared/SharedAssemblyInfo.cs b/src/shared/SharedAssemblyInfo.cs index ed949d621..7b2a9f3e0 100644 --- a/src/shared/SharedAssemblyInfo.cs +++ b/src/shared/SharedAssemblyInfo.cs @@ -7,7 +7,7 @@ [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("DotNetty")] -[assembly: AssemblyVersion("0.7.2")] -[assembly: AssemblyFileVersion("0.7.2")] +[assembly: AssemblyVersion("0.7.3")] +[assembly: AssemblyFileVersion("0.7.3")] [assembly: AssemblyCopyright("(c) Microsoft 2015 - 2021")] diff --git a/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj b/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj index 94e38d7a6..6c2b3d16a 100644 --- a/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj +++ b/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj @@ -1,10 +1,12 @@  true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj b/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj index 82dcbc4d9..a266a749c 100644 --- a/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj +++ b/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj @@ -1,10 +1,12 @@  true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Codecs.Http.Tests/HttpClientCodecTest.cs b/test/DotNetty.Codecs.Http.Tests/HttpClientCodecTest.cs index 09876ee6c..0ca42abc0 100644 --- a/test/DotNetty.Codecs.Http.Tests/HttpClientCodecTest.cs +++ b/test/DotNetty.Codecs.Http.Tests/HttpClientCodecTest.cs @@ -17,6 +17,7 @@ namespace DotNetty.Codecs.Http.Tests using Xunit; using HttpVersion = DotNetty.Codecs.Http.HttpVersion; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public sealed class HttpClientCodecTest { diff --git a/test/DotNetty.Codecs.Http.Tests/HttpServerUpgradeHandlerTest.cs b/test/DotNetty.Codecs.Http.Tests/HttpServerUpgradeHandlerTest.cs index cb8f3a6a2..9143b693f 100644 --- a/test/DotNetty.Codecs.Http.Tests/HttpServerUpgradeHandlerTest.cs +++ b/test/DotNetty.Codecs.Http.Tests/HttpServerUpgradeHandlerTest.cs @@ -13,6 +13,7 @@ namespace DotNetty.Codecs.Http.Tests using DotNetty.Transport.Channels; using DotNetty.Transport.Channels.Embedded; using Xunit; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public class HttpServerUpgradeHandlerTest { diff --git a/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketHandshakeHandOverTest.cs b/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketHandshakeHandOverTest.cs index cf527aad6..18a1f1731 100644 --- a/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketHandshakeHandOverTest.cs +++ b/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketHandshakeHandOverTest.cs @@ -12,6 +12,7 @@ namespace DotNetty.Codecs.Http.Tests.WebSockets using DotNetty.Transport.Channels; using DotNetty.Transport.Channels.Embedded; using Xunit; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public class WebSocketHandshakeHandOverTest { diff --git a/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj b/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj index f14e1e5e7..526674f1b 100644 --- a/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj +++ b/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj @@ -1,10 +1,12 @@  true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj b/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj index 4a32e857b..ab2b6e22a 100644 --- a/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj +++ b/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj @@ -1,10 +1,12 @@  true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj b/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj index 58d563787..bb4ab9a73 100644 --- a/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj +++ b/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj @@ -1,8 +1,10 @@  true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj b/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj index f42b68f15..b8d7a5709 100644 --- a/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj +++ b/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj @@ -1,10 +1,12 @@  true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj b/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj index ac979f577..311bf220c 100644 --- a/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj +++ b/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj @@ -1,10 +1,12 @@  true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Common.Tests/Concurrency/SingleThreadEventExecutorTests.cs b/test/DotNetty.Common.Tests/Concurrency/SingleThreadEventExecutorTests.cs index ae45ce3ec..e3f6812a7 100644 --- a/test/DotNetty.Common.Tests/Concurrency/SingleThreadEventExecutorTests.cs +++ b/test/DotNetty.Common.Tests/Concurrency/SingleThreadEventExecutorTests.cs @@ -13,6 +13,7 @@ namespace DotNetty.Common.Tests.Concurrency using DotNetty.Tests.Common; using Xunit; using Xunit.Abstractions; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public class SingleThreadEventExecutorTests : TestBase { diff --git a/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj b/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj index b6cef6261..401e20866 100644 --- a/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj +++ b/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj @@ -1,10 +1,12 @@  true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Handlers.Tests/AsIsWriteStrategy.cs b/test/DotNetty.Handlers.Tests/AsIsWriteStrategy.cs index a2fd4cf66..a0477edd6 100644 --- a/test/DotNetty.Handlers.Tests/AsIsWriteStrategy.cs +++ b/test/DotNetty.Handlers.Tests/AsIsWriteStrategy.cs @@ -11,7 +11,7 @@ namespace DotNetty.Handlers.Tests class AsIsWriteStrategy : IWriteStrategy { - public Task WriteToChannelAsync(EmbeddedChannel channel, ArraySegment input) + public Task WriteToChannelAsync(IEmbeddedChannel channel, ArraySegment input) { channel.WriteInbound(Unpooled.WrappedBuffer(input.Array, input.Offset, input.Count)); return TaskEx.Completed; diff --git a/test/DotNetty.Handlers.Tests/BatchingWriteStrategy.cs b/test/DotNetty.Handlers.Tests/BatchingWriteStrategy.cs index 85211b392..fd7ebfc15 100644 --- a/test/DotNetty.Handlers.Tests/BatchingWriteStrategy.cs +++ b/test/DotNetty.Handlers.Tests/BatchingWriteStrategy.cs @@ -14,7 +14,7 @@ class BatchingWriteStrategy : IWriteStrategy readonly TimeSpan timeWindow; readonly bool forceSizing; IByteBuffer pendingBuffer; - EmbeddedChannel channel; + IEmbeddedChannel channel; public BatchingWriteStrategy(int maxBatchSize, TimeSpan timeWindow, bool forceSizing) { @@ -23,7 +23,7 @@ public BatchingWriteStrategy(int maxBatchSize, TimeSpan timeWindow, bool forceSi this.forceSizing = forceSizing; } - public async Task WriteToChannelAsync(EmbeddedChannel ch, ArraySegment input) + public async Task WriteToChannelAsync(IEmbeddedChannel ch, ArraySegment input) { this.channel = ch; diff --git a/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj b/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj index 0a67729c2..d8c3a3d17 100644 --- a/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj +++ b/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj @@ -1,10 +1,12 @@  true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Handlers.Tests/IWriteStrategy.cs b/test/DotNetty.Handlers.Tests/IWriteStrategy.cs index a6f183994..125062871 100644 --- a/test/DotNetty.Handlers.Tests/IWriteStrategy.cs +++ b/test/DotNetty.Handlers.Tests/IWriteStrategy.cs @@ -9,6 +9,6 @@ namespace DotNetty.Handlers.Tests public interface IWriteStrategy { - Task WriteToChannelAsync(EmbeddedChannel channel, ArraySegment input); + Task WriteToChannelAsync(IEmbeddedChannel channel, ArraySegment input); } } \ No newline at end of file diff --git a/test/DotNetty.Handlers.Tests/SniHandlerTest.cs b/test/DotNetty.Handlers.Tests/SniHandlerTest.cs index 0f4d09328..7bb1a03f4 100644 --- a/test/DotNetty.Handlers.Tests/SniHandlerTest.cs +++ b/test/DotNetty.Handlers.Tests/SniHandlerTest.cs @@ -72,13 +72,13 @@ public async Task TlsRead(int[] frameLengths, bool isClient, IWriteStrategy writ this.Output.WriteLine($"protocol: {protocol}"); this.Output.WriteLine($"targetHost: {targetHost}"); - var executor = new SingleThreadEventExecutor("test executor", TimeSpan.FromMilliseconds(10)); + var executor = new SingleThreadEventLoop("test executor", TimeSpan.FromMilliseconds(10)); try { var writeTasks = new List(); var pair = await SetupStreamAndChannelAsync(isClient, executor, writeStrategy, protocol, writeTasks, targetHost).WithTimeout(TimeSpan.FromSeconds(10)); - EmbeddedChannel ch = pair.Item1; + IEmbeddedChannel ch = pair.Item1; SslStream driverStream = pair.Item2; int randomSeed = Environment.TickCount; @@ -139,13 +139,13 @@ public async Task TlsWrite(int[] frameLengths, bool isClient, SslProtocols proto this.Output.WriteLine($"targetHost: {targetHost}"); var writeStrategy = new AsIsWriteStrategy(); - var executor = new SingleThreadEventExecutor("test executor", TimeSpan.FromMilliseconds(10)); + var executor = new SingleThreadEventLoop("test executor", TimeSpan.FromMilliseconds(10)); try { var writeTasks = new List(); var pair = await SetupStreamAndChannelAsync(isClient, executor, writeStrategy, protocol, writeTasks, targetHost); - EmbeddedChannel ch = pair.Item1; + IEmbeddedChannel ch = pair.Item1; SslStream driverStream = pair.Item2; int randomSeed = Environment.TickCount; @@ -189,7 +189,7 @@ await ReadOutboundAsync( } } - static async Task> SetupStreamAndChannelAsync(bool isClient, IEventExecutor executor, IWriteStrategy writeStrategy, SslProtocols protocol, List writeTasks, string targetHost) + static async Task> SetupStreamAndChannelAsync(bool isClient, IEventLoop executor, IWriteStrategy writeStrategy, SslProtocols protocol, List writeTasks, string targetHost) { IChannelHandler tlsHandler = isClient ? (IChannelHandler)new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => @@ -199,13 +199,19 @@ static async Task> SetupStreamAndChannelAsync( }), new ClientTlsSettings(protocol, false, new List(), targetHost)) : new SniHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ServerTlsSniSettings(CertificateSelector)); //var ch = new EmbeddedChannel(new LoggingHandler("BEFORE"), tlsHandler, new LoggingHandler("AFTER")); - var ch = new EmbeddedChannel(tlsHandler); - +#if NET5_0_OR_GREATER + IEmbeddedChannel ch = new SingleThreadedEmbeddedChannel(executor, tlsHandler); +#else + IEmbeddedChannel ch = new EmbeddedChannel(tlsHandler); +#endif if (!isClient) { // check if in the beginning snihandler exists in the pipeline, but not tls handler - Assert.NotNull(ch.Pipeline.Get()); - Assert.Null(ch.Pipeline.Get()); + await AssertEx.EventuallyAsync( + () => ch.Pipeline.Get() != null && ch.Pipeline.Get() == null, + TimeSpan.FromMilliseconds(10), + TimeSpan.FromSeconds(5) + ); } IByteBuffer readResultBuffer = Unpooled.Buffer(4 * 1024); diff --git a/test/DotNetty.Handlers.Tests/TlsHandlerTest.cs b/test/DotNetty.Handlers.Tests/TlsHandlerTest.cs index ba7748c59..34677e5ca 100644 --- a/test/DotNetty.Handlers.Tests/TlsHandlerTest.cs +++ b/test/DotNetty.Handlers.Tests/TlsHandlerTest.cs @@ -69,7 +69,6 @@ from protocol in protocols select new object[] { frameLengths, isClient, writeStrategyFactory(), protocol.Item1, protocol.Item2 }; } - [Theory] [MemberData(nameof(GetTlsReadTestData))] public async Task TlsRead(int[] frameLengths, bool isClient, IWriteStrategy writeStrategy, SslProtocols serverProtocol, SslProtocols clientProtocol) @@ -80,15 +79,15 @@ public async Task TlsRead(int[] frameLengths, bool isClient, IWriteStrategy writ this.Output.WriteLine($"serverProtocol: {serverProtocol}"); this.Output.WriteLine($"clientProtocol: {clientProtocol}"); - var executor = new SingleThreadEventExecutor("test executor", TimeSpan.FromMilliseconds(10)); + var executor = new SingleThreadEventLoop("test executor", TimeSpan.FromMilliseconds(10)); try { var writeTasks = new List(); var pair = await SetupStreamAndChannelAsync(isClient, executor, writeStrategy, serverProtocol, clientProtocol, writeTasks).WithTimeout(TimeSpan.FromSeconds(10)); - EmbeddedChannel ch = pair.Item1; + IEmbeddedChannel ch = pair.Item1; SslStream driverStream = pair.Item2; - + int randomSeed = Environment.TickCount; var random = new Random(randomSeed); IByteBuffer expectedBuffer = Unpooled.Buffer(16 * 1024); @@ -101,6 +100,7 @@ public async Task TlsRead(int[] frameLengths, bool isClient, IWriteStrategy writ } await Task.WhenAll(writeTasks).WithTimeout(TimeSpan.FromSeconds(5)); IByteBuffer finalReadBuffer = Unpooled.Buffer(16 * 1024); + await ReadOutboundAsync(async () => ch.ReadInbound(), expectedBuffer.ReadableBytes, finalReadBuffer, TestTimeout); bool isEqual = ByteBufferUtil.Equals(expectedBuffer, finalReadBuffer); if (!isEqual) @@ -160,15 +160,15 @@ public async Task TlsWrite(int[] frameLengths, bool isClient, SslProtocols serve var writeStrategy = new AsIsWriteStrategy(); this.Output.WriteLine($"writeStrategy: {writeStrategy}"); - var executor = new SingleThreadEventExecutor("test executor", TimeSpan.FromMilliseconds(10)); + var executor = new SingleThreadEventLoop("test executor", TimeSpan.FromMilliseconds(10)); try { var writeTasks = new List(); var pair = await SetupStreamAndChannelAsync(isClient, executor, writeStrategy, serverProtocol, clientProtocol, writeTasks); - EmbeddedChannel ch = pair.Item1; + IEmbeddedChannel ch = pair.Item1; SslStream driverStream = pair.Item2; - + int randomSeed = Environment.TickCount; var random = new Random(randomSeed); IByteBuffer expectedBuffer = Unpooled.Buffer(16 * 1024); @@ -182,7 +182,7 @@ public async Task TlsWrite(int[] frameLengths, bool isClient, SslProtocols serve return (object)Unpooled.WrappedBuffer(data); }).ToArray()); } - + IByteBuffer finalReadBuffer = Unpooled.Buffer(16 * 1024); var readBuffer = new byte[16 * 1024 * 10]; await ReadOutboundAsync( @@ -206,7 +206,7 @@ await ReadOutboundAsync( } } - static async Task> SetupStreamAndChannelAsync(bool isClient, IEventExecutor executor, IWriteStrategy writeStrategy, SslProtocols serverProtocol, SslProtocols clientProtocol, List writeTasks) + static async Task> SetupStreamAndChannelAsync(bool isClient, IEventLoop executor, IWriteStrategy writeStrategy, SslProtocols serverProtocol, SslProtocols clientProtocol, List writeTasks) { X509Certificate2 tlsCertificate = TestResourceHelper.GetTestCertificate(); string targetHost = tlsCertificate.GetNameInfo(X509NameType.DnsName, false); @@ -214,7 +214,12 @@ static async Task> SetupStreamAndChannelAsync( new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(clientProtocol, false, new List(), targetHost)) : new TlsHandler(new ServerTlsSettings(tlsCertificate, false, false, serverProtocol)); //var ch = new EmbeddedChannel(new LoggingHandler("BEFORE"), tlsHandler, new LoggingHandler("AFTER")); - var ch = new EmbeddedChannel(tlsHandler); + +#if NET5_0_OR_GREATER + IEmbeddedChannel ch = new SingleThreadedEmbeddedChannel(executor, tlsHandler); +#else + IEmbeddedChannel ch = new EmbeddedChannel(tlsHandler); +#endif IByteBuffer readResultBuffer = Unpooled.Buffer(4 * 1024); Func, Task> readDataFunc = async output => @@ -228,21 +233,40 @@ static async Task> SetupStreamAndChannelAsync( if (readResultBuffer.ReadableBytes < output.Count) { if (ch.Active) - await ReadOutboundAsync(async () => ch.ReadOutbound(), output.Count - readResultBuffer.ReadableBytes, readResultBuffer, TestTimeout, readResultBuffer.ReadableBytes != 0 ? 0 : 1); + { + await ReadOutboundAsync( + async () => ch.ReadOutbound(), + output.Count - readResultBuffer.ReadableBytes, + readResultBuffer, + TestTimeout, + readResultBuffer.ReadableBytes != 0 ? 0 : 1 + ); + } } int read = Math.Min(output.Count, readResultBuffer.ReadableBytes); readResultBuffer.ReadBytes(output.Array, output.Offset, read); return read; }; - var mediationStream = new MediationStream(readDataFunc, input => - { - Task task = executor.SubmitAsync(() => writeStrategy.WriteToChannelAsync(ch, input)).Unwrap(); - writeTasks.Add(task); - return task; - }, () => - { - ch.CloseAsync(); - }); + var mediationStream = new MediationStream( + output => + { + Task task = executor.SubmitAsync( + () => readDataFunc(output) + ).Unwrap(); + return task; + }, + input => + { + Task task = executor.SubmitAsync( + () => writeStrategy.WriteToChannelAsync(ch, input) + ).Unwrap(); + writeTasks.Add(task); + return task; + }, + () => + { + ch.CloseAsync(); + }); var driverStream = new SslStream(mediationStream, true, (_1, _2, _3, _4) => true); if (isClient) diff --git a/test/DotNetty.Microbench/DotNetty.Microbench.csproj b/test/DotNetty.Microbench/DotNetty.Microbench.csproj index 8be7693c2..f02dd3298 100644 --- a/test/DotNetty.Microbench/DotNetty.Microbench.csproj +++ b/test/DotNetty.Microbench/DotNetty.Microbench.csproj @@ -2,10 +2,12 @@ Exe true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU win-x64 diff --git a/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj b/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj index 946f21561..226225f1e 100644 --- a/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj +++ b/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj @@ -2,9 +2,11 @@ true false - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 ../../DotNetty.snk true + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj b/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj index c1a9f7130..cb732f973 100644 --- a/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj +++ b/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj @@ -1,10 +1,12 @@  true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Tests.End2End/End2EndTests.cs b/test/DotNetty.Tests.End2End/End2EndTests.cs index 39473d46b..cffc672a7 100644 --- a/test/DotNetty.Tests.End2End/End2EndTests.cs +++ b/test/DotNetty.Tests.End2End/End2EndTests.cs @@ -23,6 +23,7 @@ namespace DotNetty.Tests.End2End using DotNetty.Transport.Channels.Sockets; using Xunit; using Xunit.Abstractions; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public class End2EndTests : TestBase { diff --git a/test/DotNetty.Transport.Libuv.Tests/BufReleaseTests.cs b/test/DotNetty.Transport.Libuv.Tests/BufReleaseTests.cs index e104f9f27..f9a05817b 100644 --- a/test/DotNetty.Transport.Libuv.Tests/BufReleaseTests.cs +++ b/test/DotNetty.Transport.Libuv.Tests/BufReleaseTests.cs @@ -13,6 +13,7 @@ namespace DotNetty.Transport.Libuv.Tests using Xunit; using static TestUtil; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; [Collection(LibuvTransport)] public sealed class BufReleaseTests : IDisposable diff --git a/test/DotNetty.Transport.Libuv.Tests/CompositeBufferGatheringWriteTests.cs b/test/DotNetty.Transport.Libuv.Tests/CompositeBufferGatheringWriteTests.cs index ab276ce4a..5bc8cd0af 100644 --- a/test/DotNetty.Transport.Libuv.Tests/CompositeBufferGatheringWriteTests.cs +++ b/test/DotNetty.Transport.Libuv.Tests/CompositeBufferGatheringWriteTests.cs @@ -14,6 +14,7 @@ namespace DotNetty.Transport.Libuv.Tests using Xunit; using static TestUtil; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; [Collection(LibuvTransport)] public sealed class CompositeBufferGatheringWriteTests : IDisposable diff --git a/test/DotNetty.Transport.Libuv.Tests/DetectPeerCloseWithoutReadTests.cs b/test/DotNetty.Transport.Libuv.Tests/DetectPeerCloseWithoutReadTests.cs index 3355c12b1..e24a985ec 100644 --- a/test/DotNetty.Transport.Libuv.Tests/DetectPeerCloseWithoutReadTests.cs +++ b/test/DotNetty.Transport.Libuv.Tests/DetectPeerCloseWithoutReadTests.cs @@ -14,6 +14,7 @@ namespace DotNetty.Transport.Libuv.Tests using Xunit; using static TestUtil; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; [Collection(LibuvTransport)] public sealed class DetectPeerCloseWithoutReadTests : IDisposable diff --git a/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj b/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj index 1bad6c058..df04277ab 100644 --- a/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj +++ b/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj @@ -1,10 +1,12 @@ true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU win-x64 diff --git a/test/DotNetty.Transport.Libuv.Tests/EchoTests.cs b/test/DotNetty.Transport.Libuv.Tests/EchoTests.cs index 77613e87e..eca92688b 100644 --- a/test/DotNetty.Transport.Libuv.Tests/EchoTests.cs +++ b/test/DotNetty.Transport.Libuv.Tests/EchoTests.cs @@ -14,6 +14,7 @@ namespace DotNetty.Transport.Libuv.Tests using Xunit.Abstractions; using static TestUtil; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; [Collection(LibuvTransport)] public sealed class EchoTests : IDisposable diff --git a/test/DotNetty.Transport.Libuv.Tests/EventLoopTests.cs b/test/DotNetty.Transport.Libuv.Tests/EventLoopTests.cs index 8302671f9..efd8d75e0 100644 --- a/test/DotNetty.Transport.Libuv.Tests/EventLoopTests.cs +++ b/test/DotNetty.Transport.Libuv.Tests/EventLoopTests.cs @@ -11,6 +11,7 @@ namespace DotNetty.Transport.Libuv.Tests using Xunit; using Xunit.Abstractions; using static TestUtil; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public sealed class EventLoopTests : TestBase, IDisposable { diff --git a/test/DotNetty.Transport.Libuv.Tests/ExceptionHandlingTests.cs b/test/DotNetty.Transport.Libuv.Tests/ExceptionHandlingTests.cs index 2ac71cf76..5b755130f 100644 --- a/test/DotNetty.Transport.Libuv.Tests/ExceptionHandlingTests.cs +++ b/test/DotNetty.Transport.Libuv.Tests/ExceptionHandlingTests.cs @@ -15,6 +15,7 @@ namespace DotNetty.Transport.Libuv.Tests using Xunit; using static TestUtil; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; [Collection(LibuvTransport)] public sealed class ExceptionHandlingTests : IDisposable diff --git a/test/DotNetty.Transport.Libuv.Tests/ReadPendingTests.cs b/test/DotNetty.Transport.Libuv.Tests/ReadPendingTests.cs index 0696eda56..f0f3ee186 100644 --- a/test/DotNetty.Transport.Libuv.Tests/ReadPendingTests.cs +++ b/test/DotNetty.Transport.Libuv.Tests/ReadPendingTests.cs @@ -15,6 +15,7 @@ namespace DotNetty.Transport.Libuv.Tests using Xunit; using static TestUtil; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; [Collection(LibuvTransport)] public sealed class ReadPendingTests : IDisposable diff --git a/test/DotNetty.Transport.Libuv.Tests/ResetTests.cs b/test/DotNetty.Transport.Libuv.Tests/ResetTests.cs index 301e7159b..ac94944e6 100644 --- a/test/DotNetty.Transport.Libuv.Tests/ResetTests.cs +++ b/test/DotNetty.Transport.Libuv.Tests/ResetTests.cs @@ -13,6 +13,7 @@ namespace DotNetty.Transport.Libuv.Tests using Xunit; using static TestUtil; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; [Collection(LibuvTransport)] public sealed class ResetTests : IDisposable diff --git a/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj b/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj index 72cb185f7..49ad8cbb6 100644 --- a/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj +++ b/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj @@ -4,11 +4,13 @@ true - net472 + netcoreapp3.1;net472;net5;net6 false library + Debug;Release;Package + AnyCPU diff --git a/test/DotNetty.Transport.Tests.Performance/Transport/AbstractPingPongPerfSpecs.cs b/test/DotNetty.Transport.Tests.Performance/Transport/AbstractPingPongPerfSpecs.cs index 92f050f48..a2e7d0ab5 100644 --- a/test/DotNetty.Transport.Tests.Performance/Transport/AbstractPingPongPerfSpecs.cs +++ b/test/DotNetty.Transport.Tests.Performance/Transport/AbstractPingPongPerfSpecs.cs @@ -13,6 +13,7 @@ namespace DotNetty.Transport.Tests.Performance.Transport using DotNetty.Transport.Bootstrapping; using DotNetty.Transport.Channels; using NBench; + using TaskCompletionSource = DotNetty.Common.Concurrency.TaskCompletionSource; public abstract class AbstractPingPongPerfSpecs where TServer : IServerChannel, new() diff --git a/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj b/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj index b1909e485..bdfb33232 100644 --- a/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj +++ b/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj @@ -1,10 +1,12 @@  true - netcoreapp3.1;net472 + netcoreapp3.1;net472;net5;net6 false ../../DotNetty.snk true + Debug;Release;Package + AnyCPU From 77ad4154060dbfa28089f2793073473a72a2e1b7 Mon Sep 17 00:00:00 2001 From: "microsoft-github-policy-service[bot]" <77245923+microsoft-github-policy-service[bot]@users.noreply.github.com> Date: Thu, 4 Aug 2022 11:59:50 -0700 Subject: [PATCH 22/33] Microsoft mandatory file (#590) Co-authored-by: microsoft-github-policy-service[bot] <77245923+microsoft-github-policy-service[bot]@users.noreply.github.com> --- SECURITY.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..869fdfe2b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + From 18deefb5e935f2220bd38f188440a5a92b819843 Mon Sep 17 00:00:00 2001 From: paul cheung Date: Fri, 5 Aug 2022 03:02:35 +0800 Subject: [PATCH 23/33] minor improvements (#582) --- src/DotNetty.Buffers/IByteBuffer.cs | 2 +- src/DotNetty.Buffers/IPoolChunkListMetric.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DotNetty.Buffers/IByteBuffer.cs b/src/DotNetty.Buffers/IByteBuffer.cs index 88bf34455..498630b0e 100644 --- a/src/DotNetty.Buffers/IByteBuffer.cs +++ b/src/DotNetty.Buffers/IByteBuffer.cs @@ -959,7 +959,7 @@ public interface IByteBuffer : IReferenceCounted, IComparable, IEqu /// /// Transfers bytes from this buffer's data into the specified destination buffer - /// starting at the curent until the destination becomes + /// starting at the current until the destination becomes /// non-writable and increases the by the number of transferred bytes. /// /// diff --git a/src/DotNetty.Buffers/IPoolChunkListMetric.cs b/src/DotNetty.Buffers/IPoolChunkListMetric.cs index fe5596f8e..163d190bb 100644 --- a/src/DotNetty.Buffers/IPoolChunkListMetric.cs +++ b/src/DotNetty.Buffers/IPoolChunkListMetric.cs @@ -7,10 +7,10 @@ namespace DotNetty.Buffers public interface IPoolChunkListMetric : IEnumerable { - /// Return the minum usage of the chunk list before which chunks are promoted to the previous list. + /// Return the minimum usage of the chunk list before which chunks are promoted to the previous list. int MinUsage { get; } - /// Return the minum usage of the chunk list after which chunks are promoted to the next list. + /// Return the maximum usage of the chunk list after which chunks are promoted to the next list. int MaxUsage { get; } } } \ No newline at end of file From 18fbb0839e95417970e6633bfa92d5d589df9cb3 Mon Sep 17 00:00:00 2001 From: Andrey Ilnitsky Date: Thu, 4 Aug 2022 14:53:30 -0700 Subject: [PATCH 24/33] Target fix: net5 -> net5.0, net6 -> net6.0 (#592) --- RELEASE_NOTES.md | 3 +++ build.cake | 5 ++++- examples/Discard.Client/Discard.Client.csproj | 2 +- examples/Discard.Server/Discard.Server.csproj | 2 +- examples/Echo.Client/Echo.Client.csproj | 2 +- examples/Echo.Server/Echo.Server.csproj | 2 +- examples/Examples.Common/Examples.Common.csproj | 2 +- examples/Factorial.Client/Factorial.Client.csproj | 2 +- examples/Factorial.Server/Factorial.Server.csproj | 2 +- examples/Factorial/Factorial.csproj | 2 +- examples/HttpServer/HttpServer.csproj | 2 +- .../QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj | 2 +- .../QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj | 2 +- examples/SecureChat.Client/SecureChat.Client.csproj | 2 +- examples/SecureChat.Server/SecureChat.Server.csproj | 2 +- examples/Telnet.Client/Telnet.Client.csproj | 2 +- examples/Telnet.Server/Telnet.Server.csproj | 2 +- examples/WebSockets.Client/WebSockets.Client.csproj | 2 +- examples/WebSockets.Server/WebSockets.Server.csproj | 2 +- src/Directory.Build.props | 2 +- src/DotNetty.Buffers/DotNetty.Buffers.csproj | 6 +++--- src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj | 6 +++--- src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj | 6 +++--- .../DotNetty.Codecs.Protobuf.csproj | 6 +++--- .../DotNetty.Codecs.ProtocolBuffers.csproj | 6 +++--- src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj | 6 +++--- src/DotNetty.Codecs/DotNetty.Codecs.csproj | 6 +++--- src/DotNetty.Common/DotNetty.Common.csproj | 6 +++--- src/DotNetty.Handlers/DotNetty.Handlers.csproj | 6 +++--- .../DotNetty.Transport.Libuv.csproj | 6 +++--- src/DotNetty.Transport/DotNetty.Transport.csproj | 6 +++--- src/shared/SharedAssemblyInfo.cs | 4 ++-- test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj | 2 +- .../DotNetty.Codecs.Http.Tests.csproj | 2 +- .../DotNetty.Codecs.Mqtt.Tests.csproj | 2 +- .../DotNetty.Codecs.Protobuf.Tests.csproj | 2 +- .../DotNetty.Codecs.ProtocolBuffers.Tests.csproj | 2 +- .../DotNetty.Codecs.Redis.Tests.csproj | 2 +- test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj | 2 +- test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj | 2 +- test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj | 2 +- test/DotNetty.Microbench/DotNetty.Microbench.csproj | 2 +- test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj | 2 +- test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj | 2 +- .../DotNetty.Transport.Libuv.Tests.csproj | 2 +- .../DotNetty.Transport.Tests.Performance.csproj | 2 +- .../DotNetty.Transport.Tests.csproj | 2 +- 47 files changed, 75 insertions(+), 69 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f46e23530..8dae6ef1b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,6 @@ +#### 0.7.4 August 04, 2022 +- target fix: net5 -> net5.0, net6 -> net6.0 + #### 0.7.3 July 28, 2022 - target net5 and net6 - Adopted TlsHandler for the case when Handshake completion callback is dispatched asynchronously to thread pool diff --git a/build.cake b/build.cake index 92448f42b..b6b829de6 100644 --- a/build.cake +++ b/build.cake @@ -25,6 +25,8 @@ var output = Directory("build"); var outputBinaries = output + Directory("binaries"); var outputBinariesNet = outputBinaries + Directory("net472"); var outputBinariesNetStandard = outputBinaries + Directory("netstandard2.0"); +var outputBinariesNet5 = outputBinaries + Directory("net5.0"); +var outputBinariesNet6 = outputBinaries + Directory("net6.0"); var outputPackages = output + Directory("packages"); var outputNuGet = output + Directory("nuget"); var outputPerfResults = Directory("perfResults"); @@ -37,7 +39,8 @@ Task("Clean") // Clean artifact directories. CleanDirectories(new DirectoryPath[] { output, outputBinaries, outputPackages, outputNuGet, - outputBinariesNet, outputBinariesNetStandard + outputBinariesNet, outputBinariesNetStandard, + outputBinariesNet5, outputBinariesNet6 }); if(!skipClean) { diff --git a/examples/Discard.Client/Discard.Client.csproj b/examples/Discard.Client/Discard.Client.csproj index fc5f66ab8..63cb815ba 100644 --- a/examples/Discard.Client/Discard.Client.csproj +++ b/examples/Discard.Client/Discard.Client.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/Discard.Server/Discard.Server.csproj b/examples/Discard.Server/Discard.Server.csproj index fc5f66ab8..63cb815ba 100644 --- a/examples/Discard.Server/Discard.Server.csproj +++ b/examples/Discard.Server/Discard.Server.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/Echo.Client/Echo.Client.csproj b/examples/Echo.Client/Echo.Client.csproj index fc5f66ab8..63cb815ba 100644 --- a/examples/Echo.Client/Echo.Client.csproj +++ b/examples/Echo.Client/Echo.Client.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/Echo.Server/Echo.Server.csproj b/examples/Echo.Server/Echo.Server.csproj index 0d2902c22..dfe7ea312 100644 --- a/examples/Echo.Server/Echo.Server.csproj +++ b/examples/Echo.Server/Echo.Server.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/Examples.Common/Examples.Common.csproj b/examples/Examples.Common/Examples.Common.csproj index 3ffab8ae0..06abb948a 100644 --- a/examples/Examples.Common/Examples.Common.csproj +++ b/examples/Examples.Common/Examples.Common.csproj @@ -1,6 +1,6 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/Factorial.Client/Factorial.Client.csproj b/examples/Factorial.Client/Factorial.Client.csproj index e359418af..493334d23 100644 --- a/examples/Factorial.Client/Factorial.Client.csproj +++ b/examples/Factorial.Client/Factorial.Client.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/Factorial.Server/Factorial.Server.csproj b/examples/Factorial.Server/Factorial.Server.csproj index e359418af..493334d23 100644 --- a/examples/Factorial.Server/Factorial.Server.csproj +++ b/examples/Factorial.Server/Factorial.Server.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/Factorial/Factorial.csproj b/examples/Factorial/Factorial.csproj index 157b1f550..dd5d00f26 100644 --- a/examples/Factorial/Factorial.csproj +++ b/examples/Factorial/Factorial.csproj @@ -1,6 +1,6 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/HttpServer/HttpServer.csproj b/examples/HttpServer/HttpServer.csproj index 3337a67d1..ecf15b92a 100644 --- a/examples/HttpServer/HttpServer.csproj +++ b/examples/HttpServer/HttpServer.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false true diff --git a/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj b/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj index fc5f66ab8..63cb815ba 100644 --- a/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj +++ b/examples/QuoteOfTheMoment.Client/QuoteOfTheMoment.Client.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj b/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj index fc5f66ab8..63cb815ba 100644 --- a/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj +++ b/examples/QuoteOfTheMoment.Server/QuoteOfTheMoment.Server.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/SecureChat.Client/SecureChat.Client.csproj b/examples/SecureChat.Client/SecureChat.Client.csproj index fc5f66ab8..63cb815ba 100644 --- a/examples/SecureChat.Client/SecureChat.Client.csproj +++ b/examples/SecureChat.Client/SecureChat.Client.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/SecureChat.Server/SecureChat.Server.csproj b/examples/SecureChat.Server/SecureChat.Server.csproj index fc5f66ab8..63cb815ba 100644 --- a/examples/SecureChat.Server/SecureChat.Server.csproj +++ b/examples/SecureChat.Server/SecureChat.Server.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/Telnet.Client/Telnet.Client.csproj b/examples/Telnet.Client/Telnet.Client.csproj index fc5f66ab8..63cb815ba 100644 --- a/examples/Telnet.Client/Telnet.Client.csproj +++ b/examples/Telnet.Client/Telnet.Client.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/Telnet.Server/Telnet.Server.csproj b/examples/Telnet.Server/Telnet.Server.csproj index fc5f66ab8..63cb815ba 100644 --- a/examples/Telnet.Server/Telnet.Server.csproj +++ b/examples/Telnet.Server/Telnet.Server.csproj @@ -1,7 +1,7 @@  Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/WebSockets.Client/WebSockets.Client.csproj b/examples/WebSockets.Client/WebSockets.Client.csproj index cd4b150b3..b9a7c762a 100644 --- a/examples/WebSockets.Client/WebSockets.Client.csproj +++ b/examples/WebSockets.Client/WebSockets.Client.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false Debug;Release;Package diff --git a/examples/WebSockets.Server/WebSockets.Server.csproj b/examples/WebSockets.Server/WebSockets.Server.csproj index 597c37354..55ab19721 100644 --- a/examples/WebSockets.Server/WebSockets.Server.csproj +++ b/examples/WebSockets.Server/WebSockets.Server.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 2.0.3 false true diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 679f1b4a0..824112e62 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -16,7 +16,7 @@ True true - 0.7.3 + 0.7.4 $(PackageVersion) diff --git a/src/DotNetty.Buffers/DotNetty.Buffers.csproj b/src/DotNetty.Buffers/DotNetty.Buffers.csproj index c6d10c9b9..61163daa5 100644 --- a/src/DotNetty.Buffers/DotNetty.Buffers.csproj +++ b/src/DotNetty.Buffers/DotNetty.Buffers.csproj @@ -1,12 +1,12 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 true Buffer management in DotNetty © Microsoft Corporation. All rights reserved. DotNetty: buffer management en-US - 0.7.3 + 0.7.4 Microsoft $(NoWarn);CS1591 True @@ -19,7 +19,7 @@ DotNetty.Buffers socket;tcp;protocol;netty;dotnetty;network https://github.com/Azure/DotNetty/ - https://github.com/Azure/DotNetty/blob/master/LICENSE.txt + MIT true https://github.com/Azure/DotNetty/ 2.0.3 diff --git a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj index b6a4062f4..3a1b48142 100644 --- a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj +++ b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 true DotNetty.Codecs.Http Http codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: Http codec en-US - 0.7.3 + 0.7.4 Microsoft $(NoWarn);CS1591 true @@ -20,7 +20,7 @@ true socket;tcp;protocol;netty;dotnetty;network;http https://github.com/Azure/DotNetty/ - https://github.com/Azure/DotNetty/blob/master/LICENSE.txt + MIT true git https://github.com/Azure/DotNetty/ diff --git a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj index fb8cdfecc..17c984693 100644 --- a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj +++ b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj @@ -1,13 +1,13 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 true DotNetty.Codecs.Mqtt MQTT codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: MQTT codec en-US - 0.7.3 + 0.7.4 Microsoft $(NoWarn);CS1591 false @@ -18,7 +18,7 @@ true socket;tcp;protocol;netty;dotnetty;network;mqtt https://github.com/Azure/DotNetty/ - https://github.com/Azure/DotNetty/blob/master/LICENSE.txt + MIT true git https://github.com/Azure/DotNetty/ diff --git a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj index 096eee805..222e419c9 100644 --- a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj +++ b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj @@ -1,13 +1,13 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 true DotNetty.Codecs.Protobuf Protobuf Proto3 codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: Protobuf Proto3 codec en-US - 0.7.3 + 0.7.4 Microsoft $(NoWarn);CS1591 false @@ -18,7 +18,7 @@ true socket;tcp;protocol;netty;dotnetty;network;Protobuf https://github.com/Azure/DotNetty/ - https://github.com/Azure/DotNetty/blob/master/LICENSE.txt + MIT true git https://github.com/Azure/DotNetty/ diff --git a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj index 8a00e147a..82e50e2de 100644 --- a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj +++ b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 true DotNetty.Codecs.ProtocolBuffers ProtocolBuffers Proto2 codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: ProtocolBuffers Proto2 codec en-US - 0.7.3 + 0.7.4 Microsoft $(NoWarn);CS1591 false @@ -19,7 +19,7 @@ true socket;tcp;protocol;netty;dotnetty;network;ProtocolBuffers https://github.com/Azure/DotNetty/ - https://github.com/Azure/DotNetty/blob/master/LICENSE.txt + MIT true git https://github.com/Azure/DotNetty/ diff --git a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj index ed156c65e..58f245364 100644 --- a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj +++ b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj @@ -1,13 +1,13 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 true DotNetty.Codecs.Redis Redis codec for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: Redis codec en-US - 0.7.3 + 0.7.4 Microsoft $(NoWarn);CS1591 false @@ -18,7 +18,7 @@ true socket;tcp;protocol;netty;dotnetty;network;redis https://github.com/Azure/DotNetty/ - https://github.com/Azure/DotNetty/blob/master/LICENSE.txt + MIT true git https://github.com/Azure/DotNetty/ diff --git a/src/DotNetty.Codecs/DotNetty.Codecs.csproj b/src/DotNetty.Codecs/DotNetty.Codecs.csproj index ff6f47b93..7b9618759 100644 --- a/src/DotNetty.Codecs/DotNetty.Codecs.csproj +++ b/src/DotNetty.Codecs/DotNetty.Codecs.csproj @@ -1,13 +1,13 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 true DotNetty.Codecs General purpose codecs for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: codecs en-US - 0.7.3 + 0.7.4 Microsoft $(NoWarn);CS1591 true @@ -20,7 +20,7 @@ DotNetty.Codecs socket;tcp;protocol;netty;dotnetty;network;codec https://github.com/Azure/DotNetty/ - https://github.com/Azure/DotNetty/blob/master/LICENSE.txt + MIT true git https://github.com/Azure/DotNetty/ diff --git a/src/DotNetty.Common/DotNetty.Common.csproj b/src/DotNetty.Common/DotNetty.Common.csproj index 8d06f5b8a..5ccbbd5e2 100644 --- a/src/DotNetty.Common/DotNetty.Common.csproj +++ b/src/DotNetty.Common/DotNetty.Common.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 true DotNetty.Common DotNetty common routines © Microsoft Corporation. All rights reserved. DotNetty: common routines en-US - 0.7.3 + 0.7.4 Microsoft $(NoWarn);CS1591 True @@ -20,7 +20,7 @@ true socket;tcp;protocol;netty;dotnetty;network https://github.com/Azure/DotNetty/ - https://github.com/Azure/DotNetty/blob/master/LICENSE.txt + MIT true git https://github.com/Azure/DotNetty/ diff --git a/src/DotNetty.Handlers/DotNetty.Handlers.csproj b/src/DotNetty.Handlers/DotNetty.Handlers.csproj index fe1ce05ec..c3df4b048 100644 --- a/src/DotNetty.Handlers/DotNetty.Handlers.csproj +++ b/src/DotNetty.Handlers/DotNetty.Handlers.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 true DotNetty.Handlers Application handlers for DotNetty © Microsoft Corporation. All rights reserved. DotNetty: handlers en-US - 0.7.3 + 0.7.4 Microsoft $(NoWarn);CS1591 false @@ -19,7 +19,7 @@ true socket;tcp;protocol;netty;dotnetty;network;tls;ssl https://github.com/Azure/DotNetty/ - https://github.com/Azure/DotNetty/blob/master/LICENSE.txt + MIT true git https://github.com/Azure/DotNetty/ diff --git a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj index 50241fc5e..2ff090cc5 100644 --- a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj +++ b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 true DotNetty.Transport.Libuv Libuv transport model in DotNetty © Microsoft Corporation. All rights reserved. DotNetty: libuv transport model Experimental en-US - 0.7.3 + 0.7.4 Microsoft $(NoWarn);CS1591 True @@ -20,7 +20,7 @@ true socket;tcp;udp;protocol;netty;dotnetty;network https://github.com/Azure/DotNetty/ - https://github.com/Azure/DotNetty/blob/master/LICENSE.txt + MIT true git https://github.com/Azure/DotNetty/ diff --git a/src/DotNetty.Transport/DotNetty.Transport.csproj b/src/DotNetty.Transport/DotNetty.Transport.csproj index e4488c989..da026db8f 100644 --- a/src/DotNetty.Transport/DotNetty.Transport.csproj +++ b/src/DotNetty.Transport/DotNetty.Transport.csproj @@ -1,14 +1,14 @@  - netstandard2.0;net472;net5;net6 + netstandard2.0;net472;net5.0;net6.0 true DotNetty.Transport Transport model in DotNetty © Microsoft Corporation. All rights reserved. DotNetty: transport model en-US - 0.7.3 + 0.7.4 Microsoft $(NoWarn);CS1591 false @@ -19,7 +19,7 @@ true socket;tcp;udp;protocol;netty;dotnetty;network https://github.com/Azure/DotNetty/ - https://github.com/Azure/DotNetty/blob/master/LICENSE.txt + MIT true git https://github.com/Azure/DotNetty/ diff --git a/src/shared/SharedAssemblyInfo.cs b/src/shared/SharedAssemblyInfo.cs index 7b2a9f3e0..4a68dfc50 100644 --- a/src/shared/SharedAssemblyInfo.cs +++ b/src/shared/SharedAssemblyInfo.cs @@ -7,7 +7,7 @@ [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("DotNetty")] -[assembly: AssemblyVersion("0.7.3")] -[assembly: AssemblyFileVersion("0.7.3")] +[assembly: AssemblyVersion("0.7.4")] +[assembly: AssemblyFileVersion("0.7.4")] [assembly: AssemblyCopyright("(c) Microsoft 2015 - 2021")] diff --git a/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj b/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj index 6c2b3d16a..23bf7ad9c 100644 --- a/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj +++ b/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj b/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj index a266a749c..09e3e7bd0 100644 --- a/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj +++ b/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj b/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj index 526674f1b..cb1dadae6 100644 --- a/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj +++ b/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj b/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj index ab2b6e22a..599180c0f 100644 --- a/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj +++ b/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj b/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj index bb4ab9a73..a60ee8be7 100644 --- a/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj +++ b/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false Debug;Release;Package AnyCPU diff --git a/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj b/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj index b8d7a5709..bab73a44b 100644 --- a/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj +++ b/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj b/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj index 311bf220c..3e8b2cf69 100644 --- a/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj +++ b/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj b/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj index 401e20866..e6de15885 100644 --- a/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj +++ b/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj b/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj index d8c3a3d17..c394fdc74 100644 --- a/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj +++ b/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Microbench/DotNetty.Microbench.csproj b/test/DotNetty.Microbench/DotNetty.Microbench.csproj index f02dd3298..7f804cd78 100644 --- a/test/DotNetty.Microbench/DotNetty.Microbench.csproj +++ b/test/DotNetty.Microbench/DotNetty.Microbench.csproj @@ -2,7 +2,7 @@ Exe true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj b/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj index 226225f1e..8a28698f1 100644 --- a/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj +++ b/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj @@ -2,7 +2,7 @@ true false - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 ../../DotNetty.snk true Debug;Release;Package diff --git a/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj b/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj index cb732f973..17b5107c8 100644 --- a/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj +++ b/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj b/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj index df04277ab..1a3681396 100644 --- a/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj +++ b/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj @@ -1,7 +1,7 @@ true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj b/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj index 49ad8cbb6..92c6f96e5 100644 --- a/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj +++ b/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj @@ -4,7 +4,7 @@ true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false library diff --git a/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj b/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj index bdfb33232..530e594c5 100644 --- a/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj +++ b/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5;net6 + netcoreapp3.1;net472;net5.0;net6.0 false ../../DotNetty.snk true From 4a5b84605414521d45f100986253682efde1604d Mon Sep 17 00:00:00 2001 From: kenlon <366899789@qq.com> Date: Thu, 1 Sep 2022 00:23:17 +0800 Subject: [PATCH 25/33] Fix infinite loop during TLS handshake(Only .NET6) (#583) Fix infinite loop caused by disconnection during TLS handshake, and the memory exploded instantly. --- src/DotNetty.Handlers/Tls/TlsHandler.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/DotNetty.Handlers/Tls/TlsHandler.cs b/src/DotNetty.Handlers/Tls/TlsHandler.cs index 8e4749f44..082fa0c0b 100644 --- a/src/DotNetty.Handlers/Tls/TlsHandler.cs +++ b/src/DotNetty.Handlers/Tls/TlsHandler.cs @@ -506,6 +506,13 @@ void Unwrap( } int read = currentReadFuture.Result; + + if (read == 0) + { + //Stream closed + return; + } + AddBufferToOutput(outputBuffer, read, output); } @@ -763,4 +770,4 @@ static class TlsHandlerStateExtensions public static bool HasAny(this TlsHandlerState value, TlsHandlerState testValue) => (value & testValue) != 0; } -} \ No newline at end of file +} From cde1bc36d0f522d8589e1208d36b40af966f9546 Mon Sep 17 00:00:00 2001 From: Andrey Ilnitsky Date: Wed, 31 Aug 2022 14:01:55 -0700 Subject: [PATCH 26/33] Version bump up to generate release build (#595) + Fix infinite loop caused by TlsHandler --- RELEASE_NOTES.md | 3 +++ src/Directory.Build.props | 2 +- src/DotNetty.Buffers/DotNetty.Buffers.csproj | 2 +- src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj | 2 +- src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj | 2 +- src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj | 2 +- .../DotNetty.Codecs.ProtocolBuffers.csproj | 2 +- src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj | 2 +- src/DotNetty.Codecs/DotNetty.Codecs.csproj | 2 +- src/DotNetty.Common/DotNetty.Common.csproj | 2 +- src/DotNetty.Handlers/DotNetty.Handlers.csproj | 2 +- src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj | 2 +- src/DotNetty.Transport/DotNetty.Transport.csproj | 2 +- src/shared/SharedAssemblyInfo.cs | 4 ++-- 14 files changed, 17 insertions(+), 14 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 8dae6ef1b..70ced068f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,6 @@ +#### 0.7.5 August 31, 2022 +- Fix infinite loop caused by TlsHandler + #### 0.7.4 August 04, 2022 - target fix: net5 -> net5.0, net6 -> net6.0 diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 824112e62..d7ac80510 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -16,7 +16,7 @@ True true - 0.7.4 + 0.7.5 $(PackageVersion) diff --git a/src/DotNetty.Buffers/DotNetty.Buffers.csproj b/src/DotNetty.Buffers/DotNetty.Buffers.csproj index 61163daa5..46bdfdecb 100644 --- a/src/DotNetty.Buffers/DotNetty.Buffers.csproj +++ b/src/DotNetty.Buffers/DotNetty.Buffers.csproj @@ -6,7 +6,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: buffer management en-US - 0.7.4 + 0.7.5 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj index 3a1b48142..ab1396594 100644 --- a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj +++ b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Http codec en-US - 0.7.4 + 0.7.5 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj index 17c984693..a6cd947ed 100644 --- a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj +++ b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: MQTT codec en-US - 0.7.4 + 0.7.5 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj index 222e419c9..1f54e068e 100644 --- a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj +++ b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Protobuf Proto3 codec en-US - 0.7.4 + 0.7.5 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj index 82e50e2de..56ec11f30 100644 --- a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj +++ b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: ProtocolBuffers Proto2 codec en-US - 0.7.4 + 0.7.5 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj index 58f245364..ad07b19bd 100644 --- a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj +++ b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Redis codec en-US - 0.7.4 + 0.7.5 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs/DotNetty.Codecs.csproj b/src/DotNetty.Codecs/DotNetty.Codecs.csproj index 7b9618759..abf2ee2f0 100644 --- a/src/DotNetty.Codecs/DotNetty.Codecs.csproj +++ b/src/DotNetty.Codecs/DotNetty.Codecs.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: codecs en-US - 0.7.4 + 0.7.5 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Common/DotNetty.Common.csproj b/src/DotNetty.Common/DotNetty.Common.csproj index 5ccbbd5e2..be454f874 100644 --- a/src/DotNetty.Common/DotNetty.Common.csproj +++ b/src/DotNetty.Common/DotNetty.Common.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: common routines en-US - 0.7.4 + 0.7.5 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Handlers/DotNetty.Handlers.csproj b/src/DotNetty.Handlers/DotNetty.Handlers.csproj index c3df4b048..45b22e991 100644 --- a/src/DotNetty.Handlers/DotNetty.Handlers.csproj +++ b/src/DotNetty.Handlers/DotNetty.Handlers.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: handlers en-US - 0.7.4 + 0.7.5 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj index 2ff090cc5..298de42e3 100644 --- a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj +++ b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: libuv transport model Experimental en-US - 0.7.4 + 0.7.5 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Transport/DotNetty.Transport.csproj b/src/DotNetty.Transport/DotNetty.Transport.csproj index da026db8f..5a05de57e 100644 --- a/src/DotNetty.Transport/DotNetty.Transport.csproj +++ b/src/DotNetty.Transport/DotNetty.Transport.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: transport model en-US - 0.7.4 + 0.7.5 Microsoft $(NoWarn);CS1591 false diff --git a/src/shared/SharedAssemblyInfo.cs b/src/shared/SharedAssemblyInfo.cs index 4a68dfc50..9d7d6556f 100644 --- a/src/shared/SharedAssemblyInfo.cs +++ b/src/shared/SharedAssemblyInfo.cs @@ -7,7 +7,7 @@ [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("DotNetty")] -[assembly: AssemblyVersion("0.7.4")] -[assembly: AssemblyFileVersion("0.7.4")] +[assembly: AssemblyVersion("0.7.5")] +[assembly: AssemblyFileVersion("0.7.5")] [assembly: AssemblyCopyright("(c) Microsoft 2015 - 2021")] From 296166bae9980cf35acb12d9f4bb1d229be9c5da Mon Sep 17 00:00:00 2001 From: pea-sys <49807271+pea-sys@users.noreply.github.com> Date: Wed, 7 Sep 2022 03:57:21 +0900 Subject: [PATCH 27/33] Update README.md fixed Deadlink (#594) fixed Contribution Guide link. Same link as the next page. https://github.com/Azure/azure-powershell/blob/main/README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 728f69116..defa18602 100644 --- a/README.md +++ b/README.md @@ -17,5 +17,5 @@ We gladly accept community contributions. * Issues: Please report bugs using the Issues section of GitHub * Source Code Contributions: - * Please follow the [Contribution Guidelines for Microsoft Azure](http://azure.github.io/guidelines.html) open source that details information on onboarding as a contributor + * Please follow the [Microsoft Azure Projects Contribution Guidelines](https://opensource.microsoft.com/collaborate) open source that details information on onboarding as a contributor * See [C# Coding Style](https://github.com/Azure/DotNetty/wiki/C%23-Coding-Style) for reference on coding style. From 977fd6ac09cf0490e50b8c4f456de1e89d76b5d8 Mon Sep 17 00:00:00 2001 From: nivalxer Date: Sat, 2 Dec 2023 03:47:53 +0800 Subject: [PATCH 28/33] Fix the issue of TLS handshake failure in .NET 8 environment. Signed-off-by: nivalxer --- .../Tls/TlsHandler.MediationStream.Net.cs | 11 +++++++++++ .../DotNetty.Buffers.Tests.csproj | 2 +- .../DotNetty.Codecs.Http.Tests.csproj | 2 +- .../DotNetty.Codecs.Mqtt.Tests.csproj | 2 +- .../DotNetty.Codecs.Protobuf.Tests.csproj | 2 +- .../DotNetty.Codecs.ProtocolBuffers.Tests.csproj | 2 +- .../DotNetty.Codecs.Redis.Tests.csproj | 2 +- .../DotNetty.Codecs.Tests.csproj | 2 +- .../DotNetty.Common.Tests.csproj | 2 +- .../Utilities/HashedWheelTimerTest.cs | 1 + .../DotNetty.Handlers.Tests.csproj | 2 +- test/DotNetty.Microbench/DotNetty.Microbench.csproj | 2 +- .../DotNetty.Tests.Common.csproj | 2 +- .../DotNetty.Tests.End2End.csproj | 2 +- .../DotNetty.Transport.Libuv.Tests.csproj | 2 +- .../DotNetty.Transport.Tests.Performance.csproj | 2 +- .../DotNetty.Transport.Tests.csproj | 2 +- 17 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.Net.cs b/src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.Net.cs index b8e48babd..95323eab4 100644 --- a/src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.Net.cs +++ b/src/DotNetty.Handlers/Tls/TlsHandler.MediationStream.Net.cs @@ -69,6 +69,11 @@ ValueTask InLoopReadAsync(Memory buffer, CancellationToken cancellati int read = this.ReadFromInput(buffer); return new ValueTask(read); } + //.NET8 sslStream will return 0 sometimes.like:https://github.com/dotnet/wcf/issues/5205 + if (buffer.IsEmpty) + { + return new ValueTask(0); + } Contract.Assert(this.sslOwnedMemory.IsEmpty); // take note of buffer - we will pass bytes there once available @@ -89,6 +94,12 @@ Task OutOfLoopReadAsync(Memory buffer, CancellationToken cancellation return Task.FromResult(read); } + //.NET8 sslStream will return 0 sometimes.like:https://github.com/dotnet/wcf/issues/5205 + if (buffer.IsEmpty) + { + return Task.FromResult(0); + } + Contract.Assert(this.sslOwnedMemory.IsEmpty); // take note of buffer - we will pass bytes there once available this.sslOwnedMemory = buffer; diff --git a/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj b/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj index 23bf7ad9c..1b8a6435c 100644 --- a/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj +++ b/test/DotNetty.Buffers.Tests/DotNetty.Buffers.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj b/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj index 09e3e7bd0..ad22753e1 100644 --- a/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj +++ b/test/DotNetty.Codecs.Http.Tests/DotNetty.Codecs.Http.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj b/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj index cb1dadae6..7d2fef89f 100644 --- a/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj +++ b/test/DotNetty.Codecs.Mqtt.Tests/DotNetty.Codecs.Mqtt.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj b/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj index 599180c0f..996840e19 100644 --- a/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj +++ b/test/DotNetty.Codecs.Protobuf.Tests/DotNetty.Codecs.Protobuf.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj b/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj index a60ee8be7..b460bf476 100644 --- a/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj +++ b/test/DotNetty.Codecs.ProtocolBuffers.Tests/DotNetty.Codecs.ProtocolBuffers.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false Debug;Release;Package AnyCPU diff --git a/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj b/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj index bab73a44b..e04d372c8 100644 --- a/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj +++ b/test/DotNetty.Codecs.Redis.Tests/DotNetty.Codecs.Redis.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj b/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj index 3e8b2cf69..8a148c3b1 100644 --- a/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj +++ b/test/DotNetty.Codecs.Tests/DotNetty.Codecs.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj b/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj index e6de15885..f59db99bd 100644 --- a/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj +++ b/test/DotNetty.Common.Tests/DotNetty.Common.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Common.Tests/Utilities/HashedWheelTimerTest.cs b/test/DotNetty.Common.Tests/Utilities/HashedWheelTimerTest.cs index 22c52fefd..e2c9a9605 100644 --- a/test/DotNetty.Common.Tests/Utilities/HashedWheelTimerTest.cs +++ b/test/DotNetty.Common.Tests/Utilities/HashedWheelTimerTest.cs @@ -11,6 +11,7 @@ namespace DotNetty.Common.Tests.Utilities using DotNetty.Tests.Common; using Xunit; using Xunit.Abstractions; + using ITimer = DotNetty.Common.Utilities.ITimer; public class HashedWheelTimerTest : TestBase { diff --git a/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj b/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj index c394fdc74..e2078c6be 100644 --- a/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj +++ b/test/DotNetty.Handlers.Tests/DotNetty.Handlers.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Microbench/DotNetty.Microbench.csproj b/test/DotNetty.Microbench/DotNetty.Microbench.csproj index 7f804cd78..6dccc389e 100644 --- a/test/DotNetty.Microbench/DotNetty.Microbench.csproj +++ b/test/DotNetty.Microbench/DotNetty.Microbench.csproj @@ -2,7 +2,7 @@ Exe true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj b/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj index 8a28698f1..395751329 100644 --- a/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj +++ b/test/DotNetty.Tests.Common/DotNetty.Tests.Common.csproj @@ -2,7 +2,7 @@ true false - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 ../../DotNetty.snk true Debug;Release;Package diff --git a/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj b/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj index 17b5107c8..adfdfd1b8 100644 --- a/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj +++ b/test/DotNetty.Tests.End2End/DotNetty.Tests.End2End.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj b/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj index 1a3681396..c18b3419e 100644 --- a/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj +++ b/test/DotNetty.Transport.Libuv.Tests/DotNetty.Transport.Libuv.Tests.csproj @@ -1,7 +1,7 @@ true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true diff --git a/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj b/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj index 92c6f96e5..4356c4dc7 100644 --- a/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj +++ b/test/DotNetty.Transport.Tests.Performance/DotNetty.Transport.Tests.Performance.csproj @@ -4,7 +4,7 @@ true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false library diff --git a/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj b/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj index 530e594c5..490b45714 100644 --- a/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj +++ b/test/DotNetty.Transport.Tests/DotNetty.Transport.Tests.csproj @@ -1,7 +1,7 @@  true - netcoreapp3.1;net472;net5.0;net6.0 + netcoreapp3.1;net472;net5.0;net6.0;net8.0 false ../../DotNetty.snk true From 392137ecb38d7403620054163b15102bea840a6c Mon Sep 17 00:00:00 2001 From: nivalxer Date: Fri, 29 Dec 2023 22:48:27 +0800 Subject: [PATCH 29/33] change appveyor to support .net8 Signed-off-by: nivalxer --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index b3954a098..049b2dedc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ version: 0.7.0.{build} pull_requests: do_not_increment_build_number: true -image: Visual Studio 2019 +image: Visual Studio 2022 build_script: - cmd: powershell .\build.ps1 -target PR test: off From 1ed22ceeba83f50b2d282f8b45a4eb8770821e28 Mon Sep 17 00:00:00 2001 From: Filip Stankovski Date: Fri, 9 Feb 2024 11:56:52 -0800 Subject: [PATCH 30/33] Updating package version to 0.7.7 --- RELEASE_NOTES.md | 5 ++++- src/Directory.Build.props | 2 +- src/DotNetty.Buffers/DotNetty.Buffers.csproj | 2 +- src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj | 2 +- src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj | 2 +- src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj | 2 +- .../DotNetty.Codecs.ProtocolBuffers.csproj | 2 +- src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj | 2 +- src/DotNetty.Codecs/DotNetty.Codecs.csproj | 2 +- src/DotNetty.Common/DotNetty.Common.csproj | 2 +- src/DotNetty.Handlers/DotNetty.Handlers.csproj | 2 +- src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj | 2 +- src/DotNetty.Transport/DotNetty.Transport.csproj | 2 +- src/shared/SharedAssemblyInfo.cs | 4 ++-- 14 files changed, 18 insertions(+), 15 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 70ced068f..83c98b064 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,4 +1,7 @@ -#### 0.7.5 August 31, 2022 +#### 0.7.7 February 9, 2024 +- Fix TLS handshake for net8 + +#### 0.7.7 August 31, 2022 - Fix infinite loop caused by TlsHandler #### 0.7.4 August 04, 2022 diff --git a/src/Directory.Build.props b/src/Directory.Build.props index d7ac80510..b4918a8cd 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -16,7 +16,7 @@ True true - 0.7.5 + 0.7.7 $(PackageVersion) diff --git a/src/DotNetty.Buffers/DotNetty.Buffers.csproj b/src/DotNetty.Buffers/DotNetty.Buffers.csproj index 46bdfdecb..24acac435 100644 --- a/src/DotNetty.Buffers/DotNetty.Buffers.csproj +++ b/src/DotNetty.Buffers/DotNetty.Buffers.csproj @@ -6,7 +6,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: buffer management en-US - 0.7.5 + 0.7.7 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj index ab1396594..e662df2fe 100644 --- a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj +++ b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Http codec en-US - 0.7.5 + 0.7.7 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj index a6cd947ed..e891dd3ef 100644 --- a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj +++ b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: MQTT codec en-US - 0.7.5 + 0.7.7 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj index 1f54e068e..0cc65190f 100644 --- a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj +++ b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Protobuf Proto3 codec en-US - 0.7.5 + 0.7.7 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj index 56ec11f30..efcf95b2c 100644 --- a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj +++ b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: ProtocolBuffers Proto2 codec en-US - 0.7.5 + 0.7.7 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj index ad07b19bd..4e35fc17b 100644 --- a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj +++ b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Redis codec en-US - 0.7.5 + 0.7.7 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs/DotNetty.Codecs.csproj b/src/DotNetty.Codecs/DotNetty.Codecs.csproj index abf2ee2f0..566d79b14 100644 --- a/src/DotNetty.Codecs/DotNetty.Codecs.csproj +++ b/src/DotNetty.Codecs/DotNetty.Codecs.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: codecs en-US - 0.7.5 + 0.7.7 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Common/DotNetty.Common.csproj b/src/DotNetty.Common/DotNetty.Common.csproj index be454f874..86b23f5c9 100644 --- a/src/DotNetty.Common/DotNetty.Common.csproj +++ b/src/DotNetty.Common/DotNetty.Common.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: common routines en-US - 0.7.5 + 0.7.7 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Handlers/DotNetty.Handlers.csproj b/src/DotNetty.Handlers/DotNetty.Handlers.csproj index 45b22e991..7c871ae80 100644 --- a/src/DotNetty.Handlers/DotNetty.Handlers.csproj +++ b/src/DotNetty.Handlers/DotNetty.Handlers.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: handlers en-US - 0.7.5 + 0.7.7 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj index 298de42e3..b22f89d3c 100644 --- a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj +++ b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: libuv transport model Experimental en-US - 0.7.5 + 0.7.7 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Transport/DotNetty.Transport.csproj b/src/DotNetty.Transport/DotNetty.Transport.csproj index 5a05de57e..d6bbc5b1f 100644 --- a/src/DotNetty.Transport/DotNetty.Transport.csproj +++ b/src/DotNetty.Transport/DotNetty.Transport.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: transport model en-US - 0.7.5 + 0.7.7 Microsoft $(NoWarn);CS1591 false diff --git a/src/shared/SharedAssemblyInfo.cs b/src/shared/SharedAssemblyInfo.cs index 9d7d6556f..f145c3aae 100644 --- a/src/shared/SharedAssemblyInfo.cs +++ b/src/shared/SharedAssemblyInfo.cs @@ -7,7 +7,7 @@ [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("DotNetty")] -[assembly: AssemblyVersion("0.7.5")] -[assembly: AssemblyFileVersion("0.7.5")] +[assembly: AssemblyVersion("0.7.7")] +[assembly: AssemblyFileVersion("0.7.7")] [assembly: AssemblyCopyright("(c) Microsoft 2015 - 2021")] From e504c148b3e1ec647e9ec3b544327d00ee5204a0 Mon Sep 17 00:00:00 2001 From: Filip Stankovski Date: Fri, 9 Feb 2024 12:57:35 -0800 Subject: [PATCH 31/33] 0.7.6 --- RELEASE_NOTES.md | 4 ++-- src/Directory.Build.props | 2 +- src/DotNetty.Buffers/DotNetty.Buffers.csproj | 2 +- src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj | 2 +- src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj | 2 +- src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj | 2 +- .../DotNetty.Codecs.ProtocolBuffers.csproj | 2 +- src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj | 2 +- src/DotNetty.Codecs/DotNetty.Codecs.csproj | 2 +- src/DotNetty.Common/DotNetty.Common.csproj | 2 +- src/DotNetty.Handlers/DotNetty.Handlers.csproj | 2 +- src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj | 2 +- src/DotNetty.Transport/DotNetty.Transport.csproj | 2 +- src/shared/SharedAssemblyInfo.cs | 4 ++-- 14 files changed, 16 insertions(+), 16 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 83c98b064..2f4fabbf6 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,7 +1,7 @@ -#### 0.7.7 February 9, 2024 +#### 0.7.6 February 9, 2024 - Fix TLS handshake for net8 -#### 0.7.7 August 31, 2022 +#### 0.7.5 August 31, 2022 - Fix infinite loop caused by TlsHandler #### 0.7.4 August 04, 2022 diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b4918a8cd..abe924170 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -16,7 +16,7 @@ True true - 0.7.7 + 0.7.6 $(PackageVersion) diff --git a/src/DotNetty.Buffers/DotNetty.Buffers.csproj b/src/DotNetty.Buffers/DotNetty.Buffers.csproj index 24acac435..7aa36135b 100644 --- a/src/DotNetty.Buffers/DotNetty.Buffers.csproj +++ b/src/DotNetty.Buffers/DotNetty.Buffers.csproj @@ -6,7 +6,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: buffer management en-US - 0.7.7 + 0.7.6 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj index e662df2fe..d6c931439 100644 --- a/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj +++ b/src/DotNetty.Codecs.Http/DotNetty.Codecs.Http.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Http codec en-US - 0.7.7 + 0.7.6 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj index e891dd3ef..be4c6e2ca 100644 --- a/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj +++ b/src/DotNetty.Codecs.Mqtt/DotNetty.Codecs.Mqtt.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: MQTT codec en-US - 0.7.7 + 0.7.6 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj index 0cc65190f..6d72011ee 100644 --- a/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj +++ b/src/DotNetty.Codecs.Protobuf/DotNetty.Codecs.Protobuf.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Protobuf Proto3 codec en-US - 0.7.7 + 0.7.6 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj index efcf95b2c..0402068a6 100644 --- a/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj +++ b/src/DotNetty.Codecs.ProtocolBuffers/DotNetty.Codecs.ProtocolBuffers.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: ProtocolBuffers Proto2 codec en-US - 0.7.7 + 0.7.6 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj index 4e35fc17b..dc1590a7b 100644 --- a/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj +++ b/src/DotNetty.Codecs.Redis/DotNetty.Codecs.Redis.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: Redis codec en-US - 0.7.7 + 0.7.6 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Codecs/DotNetty.Codecs.csproj b/src/DotNetty.Codecs/DotNetty.Codecs.csproj index 566d79b14..e978583f4 100644 --- a/src/DotNetty.Codecs/DotNetty.Codecs.csproj +++ b/src/DotNetty.Codecs/DotNetty.Codecs.csproj @@ -7,7 +7,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: codecs en-US - 0.7.7 + 0.7.6 Microsoft $(NoWarn);CS1591 true diff --git a/src/DotNetty.Common/DotNetty.Common.csproj b/src/DotNetty.Common/DotNetty.Common.csproj index 86b23f5c9..8358ec1a3 100644 --- a/src/DotNetty.Common/DotNetty.Common.csproj +++ b/src/DotNetty.Common/DotNetty.Common.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: common routines en-US - 0.7.7 + 0.7.6 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Handlers/DotNetty.Handlers.csproj b/src/DotNetty.Handlers/DotNetty.Handlers.csproj index 7c871ae80..1009c1818 100644 --- a/src/DotNetty.Handlers/DotNetty.Handlers.csproj +++ b/src/DotNetty.Handlers/DotNetty.Handlers.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: handlers en-US - 0.7.7 + 0.7.6 Microsoft $(NoWarn);CS1591 false diff --git a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj index b22f89d3c..a03e4703e 100644 --- a/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj +++ b/src/DotNetty.Transport.Libuv/DotNetty.Transport.Libuv.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: libuv transport model Experimental en-US - 0.7.7 + 0.7.6 Microsoft $(NoWarn);CS1591 True diff --git a/src/DotNetty.Transport/DotNetty.Transport.csproj b/src/DotNetty.Transport/DotNetty.Transport.csproj index d6bbc5b1f..738edc94f 100644 --- a/src/DotNetty.Transport/DotNetty.Transport.csproj +++ b/src/DotNetty.Transport/DotNetty.Transport.csproj @@ -8,7 +8,7 @@ © Microsoft Corporation. All rights reserved. DotNetty: transport model en-US - 0.7.7 + 0.7.6 Microsoft $(NoWarn);CS1591 false diff --git a/src/shared/SharedAssemblyInfo.cs b/src/shared/SharedAssemblyInfo.cs index f145c3aae..dd8345785 100644 --- a/src/shared/SharedAssemblyInfo.cs +++ b/src/shared/SharedAssemblyInfo.cs @@ -7,7 +7,7 @@ [assembly: AssemblyCompany("Microsoft")] [assembly: AssemblyProduct("DotNetty")] -[assembly: AssemblyVersion("0.7.7")] -[assembly: AssemblyFileVersion("0.7.7")] +[assembly: AssemblyVersion("0.7.6")] +[assembly: AssemblyFileVersion("0.7.6")] [assembly: AssemblyCopyright("(c) Microsoft 2015 - 2021")] From 6a8b6298a6fd44ccb2c70b37532e797e78ee37a4 Mon Sep 17 00:00:00 2001 From: Filip Stankovski Date: Fri, 9 Feb 2024 14:38:34 -0800 Subject: [PATCH 32/33] Updating test timeout to 5s --- .../WebSockets/WebSocketHandshakeHandOverTest.cs | 2 +- .../WebSockets/WebSocketServerHandshaker00Test.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketHandshakeHandOverTest.cs b/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketHandshakeHandOverTest.cs index 18a1f1731..d1741e820 100644 --- a/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketHandshakeHandOverTest.cs +++ b/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketHandshakeHandOverTest.cs @@ -38,7 +38,7 @@ public void Handover() // Transfer the handshake from the client to the server TransferAllDataWithMerge(clientChannel, serverChannel); - Assert.True(serverHandler.Completion.Wait(TimeSpan.FromSeconds(1))); + Assert.True(serverHandler.Completion.Wait(TimeSpan.FromSeconds(5))); Assert.True(this.serverReceivedHandshake); Assert.NotNull(this.serverHandshakeComplete); diff --git a/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketServerHandshaker00Test.cs b/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketServerHandshaker00Test.cs index 9778bd0cd..9a2271b2b 100644 --- a/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketServerHandshaker00Test.cs +++ b/test/DotNetty.Codecs.Http.Tests/WebSockets/WebSocketServerHandshaker00Test.cs @@ -46,7 +46,7 @@ static void PerformOpeningHandshake0(bool subProtocol) { handshaker = new WebSocketServerHandshaker00("ws://example.com/chat", null, int.MaxValue); } - Assert.True(handshaker.HandshakeAsync(ch, req).Wait(TimeSpan.FromSeconds(2))); + Assert.True(handshaker.HandshakeAsync(ch, req).Wait(TimeSpan.FromSeconds(5))); var ch2 = new EmbeddedChannel(new HttpResponseDecoder()); ch2.WriteInbound(ch.ReadOutbound()); From 1cc162838a51d86b671e1171a01382c03c6a2eea Mon Sep 17 00:00:00 2001 From: Filip Stankovski Date: Fri, 9 Feb 2024 16:27:39 -0800 Subject: [PATCH 33/33] More timeouts --- .../Channel/Sockets/SocketDatagramChannelUnicastTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/DotNetty.Transport.Tests/Channel/Sockets/SocketDatagramChannelUnicastTest.cs b/test/DotNetty.Transport.Tests/Channel/Sockets/SocketDatagramChannelUnicastTest.cs index 908a03c15..f76fa24c2 100644 --- a/test/DotNetty.Transport.Tests/Channel/Sockets/SocketDatagramChannelUnicastTest.cs +++ b/test/DotNetty.Transport.Tests/Channel/Sockets/SocketDatagramChannelUnicastTest.cs @@ -20,7 +20,7 @@ namespace DotNetty.Transport.Tests.Channel.Sockets [Collection("UDP Transport Tests")] public class SocketDatagramChannelUnicastTest : TestBase { - const int DefaultTimeOutInMilliseconds = 800; + const int DefaultTimeOutInMilliseconds = 5000; public SocketDatagramChannelUnicastTest(ITestOutputHelper output) : base(output)