diff --git a/.build/setup.ps1 b/.build/setup.ps1 index a0ccb55..1020fa9 100644 --- a/.build/setup.ps1 +++ b/.build/setup.ps1 @@ -36,7 +36,7 @@ function Install-DocFx() { if(!(Test-Path $env:ChocolateyInstall\lib\docfx\tools*)) { - choco install docfx + choco install docfx --version 2.40.1 } $env:Path += ";$env:ChocolateyInstall\lib\docfx\tools" } diff --git a/docs/api/StreamExtended.ClientHelloInfo.html b/docs/api/StreamExtended.ClientHelloInfo.html index ad76912..519af10 100644 --- a/docs/api/StreamExtended.ClientHelloInfo.html +++ b/docs/api/StreamExtended.ClientHelloInfo.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.DefaultBufferPool.html b/docs/api/StreamExtended.DefaultBufferPool.html index 2077b87..dde00d9 100644 --- a/docs/api/StreamExtended.DefaultBufferPool.html +++ b/docs/api/StreamExtended.DefaultBufferPool.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.IBufferPool.html b/docs/api/StreamExtended.IBufferPool.html index 0afcbc0..eba2678 100644 --- a/docs/api/StreamExtended.IBufferPool.html +++ b/docs/api/StreamExtended.IBufferPool.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.Models.SslExtension.html b/docs/api/StreamExtended.Models.SslExtension.html index 49a0efa..1132160 100644 --- a/docs/api/StreamExtended.Models.SslExtension.html +++ b/docs/api/StreamExtended.Models.SslExtension.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.Models.html b/docs/api/StreamExtended.Models.html index fa3034a..5a85d98 100644 --- a/docs/api/StreamExtended.Models.html +++ b/docs/api/StreamExtended.Models.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.Network.CopyStream.html b/docs/api/StreamExtended.Network.CopyStream.html index 9176b65..aaae0de 100644 --- a/docs/api/StreamExtended.Network.CopyStream.html +++ b/docs/api/StreamExtended.Network.CopyStream.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.Network.CustomBufferedStream.html b/docs/api/StreamExtended.Network.CustomBufferedStream.html index dc13dfc..d553aaf 100644 --- a/docs/api/StreamExtended.Network.CustomBufferedStream.html +++ b/docs/api/StreamExtended.Network.CustomBufferedStream.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.Network.DataEventArgs.html b/docs/api/StreamExtended.Network.DataEventArgs.html index 4740baf..b906256 100644 --- a/docs/api/StreamExtended.Network.DataEventArgs.html +++ b/docs/api/StreamExtended.Network.DataEventArgs.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.Network.ICustomStreamReader.html b/docs/api/StreamExtended.Network.ICustomStreamReader.html index 3713eb4..7668831 100644 --- a/docs/api/StreamExtended.Network.ICustomStreamReader.html +++ b/docs/api/StreamExtended.Network.ICustomStreamReader.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.Network.ICustomStreamWriter.html b/docs/api/StreamExtended.Network.ICustomStreamWriter.html index 642665c..581b196 100644 --- a/docs/api/StreamExtended.Network.ICustomStreamWriter.html +++ b/docs/api/StreamExtended.Network.ICustomStreamWriter.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.Network.html b/docs/api/StreamExtended.Network.html index 4261558..6fbc426 100644 --- a/docs/api/StreamExtended.Network.html +++ b/docs/api/StreamExtended.Network.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.ServerHelloInfo.html b/docs/api/StreamExtended.ServerHelloInfo.html index e6dfdea..c550559 100644 --- a/docs/api/StreamExtended.ServerHelloInfo.html +++ b/docs/api/StreamExtended.ServerHelloInfo.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.SslTools.html b/docs/api/StreamExtended.SslTools.html index 3def93a..3b9ded5 100644 --- a/docs/api/StreamExtended.SslTools.html +++ b/docs/api/StreamExtended.SslTools.html @@ -10,7 +10,7 @@ - + diff --git a/docs/api/StreamExtended.html b/docs/api/StreamExtended.html index 1e146e3..099a207 100644 --- a/docs/api/StreamExtended.html +++ b/docs/api/StreamExtended.html @@ -10,7 +10,7 @@ - + diff --git a/src/StreamExtended/Network/CustomBufferedStream.cs b/src/StreamExtended/Network/CustomBufferedStream.cs index 2f937bc..c81659c 100644 --- a/src/StreamExtended/Network/CustomBufferedStream.cs +++ b/src/StreamExtended/Network/CustomBufferedStream.cs @@ -139,14 +139,8 @@ public override void Write(byte[] buffer, int offset, int count) { if (bufferLength > 0) { - -//WriteAsync has a bug in Net45 -//See https://github.com/justcoding121/Titanium-Web-Proxy/issues/495 -#if NET45 - destination.Write(streamBuffer, bufferPos, bufferLength); -#else await destination.WriteAsync(streamBuffer, bufferPos, bufferLength, cancellationToken); -#endif + bufferLength = 0; } @@ -293,14 +287,7 @@ public byte ReadByteFromBuffer() { OnDataWrite(buffer, offset, count); -//WriteAsync has a bug in Net45 -//See https://github.com/justcoding121/Titanium-Web-Proxy/issues/495 -#if NET45 - baseStream.Write(buffer, offset, count); - await Task.FromResult(true); -#else await baseStream.WriteAsync(buffer, offset, count, cancellationToken); -#endif } /// @@ -592,5 +579,55 @@ private static void ResizeBuffer(ref byte[] buffer, long size) Buffer.BlockCopy(buffer, 0, newBuffer, 0, buffer.Length); buffer = newBuffer; } + +#if NET45 + + /// + /// Base Stream.BeginRead will call this.Read and block thread (we don't want this, Network stream handles async) + /// In order to really async Reading Launch this.ReadAsync as Task will fire NetworkStream.ReadAsync + /// See Threads here : + /// https://github.com/justcoding121/Stream-Extended/pull/43 + /// https://github.com/justcoding121/Titanium-Web-Proxy/issues/575 + /// + /// + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + var vAsyncResult = this.ReadAsync(buffer, offset, count); + + vAsyncResult.ContinueWith(pAsyncResult => + { + //use TaskExtended to pass State as AsyncObject + //callback will call EndRead (otherwise, it will block) + callback(new TaskResult(pAsyncResult, state)); + }); + + return vAsyncResult; + } + + /// + /// override EndRead to handle async Reading (see BeginRead comment) + /// + /// + public override int EndRead(IAsyncResult asyncResult) + { + return ((TaskResult)asyncResult).Result; + } + + /// + /// Fix the .net bug with SslStream slow WriteAsync + /// https://github.com/justcoding121/Titanium-Web-Proxy/issues/495 + /// Stream.BeginWrite + Stream.BeginRead uses the same SemaphoreSlim(1) + /// That's why we need to call NetworkStream.BeginWrite only (while read is waiting SemaphoreSlim) + /// + /// + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) + { + return baseStream.BeginWrite(buffer, offset, count, callback, state); + } + public override void EndWrite(IAsyncResult asyncResult) + { + baseStream.EndWrite(asyncResult); + } +#endif } } diff --git a/src/StreamExtended/TaskExtended.cs b/src/StreamExtended/TaskExtended.cs new file mode 100644 index 0000000..a8d4c74 --- /dev/null +++ b/src/StreamExtended/TaskExtended.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace StreamExtended +{ + /// + /// Mimic a Task but you can set AsyncState + /// + /// + public class TaskResult : IAsyncResult + { + Task Task; + object mAsyncState; + + public TaskResult(Task pTask, object state) + { + Task = pTask; + mAsyncState = state; + } + + public object AsyncState => mAsyncState; + public WaitHandle AsyncWaitHandle => ((IAsyncResult)Task).AsyncWaitHandle; + public bool CompletedSynchronously => ((IAsyncResult)Task).CompletedSynchronously; + public bool IsCompleted => Task.IsCompleted; + public T Result => Task.Result; + } +}