Unverified Commit b3bbac37 authored by honfika's avatar honfika Committed by GitHub

Merge pull request #698 from justcoding121/master

beta
parents 727e7505 1fe10a92
......@@ -5,7 +5,7 @@
"name": "NetCore|Debug|Basic Example",
"type": "coreclr",
"request": "launch",
"program": "${workspaceRoot}/examples/Titanium.Web.Proxy.Examples.Basic/bin/Debug/netcoreapp2.0/Titanium.Web.Proxy.Examples.Basic.NetCore.dll",
"program": "${workspaceRoot}/examples/Titanium.Web.Proxy.Examples.Basic/bin/Debug/netcoreapp3.1/Titanium.Web.Proxy.Examples.Basic.NetCore.dll",
"args": [],
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
......@@ -16,7 +16,7 @@
"name": "NetCore|Release|Basic Example",
"type": "coreclr",
"request": "launch",
"program": "${workspaceRoot}/examples/Titanium.Web.Proxy.Examples.Basic/bin/Release/netcoreapp2.0/Titanium.Web.Proxy.Examples.Basic.NetCore.dll",
"program": "${workspaceRoot}/examples/Titanium.Web.Proxy.Examples.Basic/bin/Release/netcoreapp3.1/Titanium.Web.Proxy.Examples.Basic.NetCore.dll",
"args": [],
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
......
......@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
......
......@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net461;netcoreapp3.0</TargetFrameworks>
<TargetFrameworks>net461;netcoreapp3.1</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<LangVersion>7.1</LangVersion>
</PropertyGroup>
......
......@@ -103,16 +103,16 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry">
<Version>4.6.0</Version>
<Version>4.7.0</Version>
</PackageReference>
<PackageReference Include="System.Numerics.Vectors">
<Version>4.5.0</Version>
</PackageReference>
<PackageReference Include="System.Runtime.CompilerServices.Unsafe">
<Version>4.6.0</Version>
<Version>4.7.0</Version>
</PackageReference>
<PackageReference Include="System.ServiceProcess.ServiceController">
<Version>4.6.0</Version>
<Version>4.7.0</Version>
</PackageReference>
<PackageReference Include="System.Threading.Tasks.Extensions">
<Version>4.5.3</Version>
......
......@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp3.0</TargetFrameworks>
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<UseWPF>true</UseWPF>
</PropertyGroup>
......
......@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFrameworks>net461;netcoreapp3.0</TargetFrameworks>
<TargetFrameworks>net461;netcoreapp3.1</TargetFrameworks>
<UseWPF>true</UseWPF>
</PropertyGroup>
......
using System;
using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy.EventArguments
{
public class EmptyProxyEventArgs : ProxyEventArgsBase
{
internal EmptyProxyEventArgs(TcpClientConnection clientConnection) : base(clientConnection)
{
}
}
}
......@@ -190,7 +190,7 @@ namespace Titanium.Web.Proxy.EventArguments
private async Task<byte[]> readBodyAsync(bool isRequest, CancellationToken cancellationToken)
{
using var bodyStream = new MemoryStream();
using var writer = new HttpStream(bodyStream, BufferPool);
using var writer = new HttpStream(bodyStream, BufferPool, cancellationToken);
if (isRequest)
{
......
......@@ -33,14 +33,12 @@ namespace Titanium.Web.Proxy
var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool);
var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken);
Task<TcpServerConnection>? prefetchConnectionTask = null;
bool closeServerConnection = false;
bool calledRequestHandler = false;
SslStream? sslStream = null;
try
{
TunnelConnectSessionEventArgs? connectArgs = null;
......@@ -191,6 +189,7 @@ namespace Titanium.Web.Proxy
}
X509Certificate2? certificate = null;
SslStream? sslStream = null;
try
{
sslStream = new SslStream(clientStream, false);
......@@ -221,7 +220,7 @@ namespace Titanium.Web.Proxy
#endif
// HTTPS server created - we can now decrypt the client's traffic
clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool);
clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool, cancellationToken);
sslStream = null; // clientStream was created, no need to keep SSL stream reference
clientStream.DataRead += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count);
......@@ -229,6 +228,8 @@ namespace Titanium.Web.Proxy
}
catch (Exception e)
{
sslStream?.Dispose();
var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
throw new ProxyConnectException(
$"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs);
......@@ -401,12 +402,16 @@ namespace Titanium.Web.Proxy
}
finally
{
if (!cancellationTokenSource.IsCancellationRequested)
{
cancellationTokenSource.Cancel();
}
if (!calledRequestHandler)
{
await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection);
}
sslStream?.Dispose();
clientStream.Dispose();
}
}
......
......@@ -42,8 +42,8 @@ namespace Titanium.Web.Proxy.Extensions
{
// cancellation is not working on Socket ReadAsync
// https://github.com/dotnet/corefx/issues/15033
int num = await input.ReadAsync(buffer, 0, buffer.Length, CancellationToken.None)
.withCancellation(cancellationToken);
int num = await input.ReadAsync(buffer, 0, buffer.Length, cancellationToken)
.WithCancellation(cancellationToken);
int bytesRead;
if ((bytesRead = num) != 0 && !cancellationToken.IsCancellationRequested)
{
......@@ -62,7 +62,7 @@ namespace Titanium.Web.Proxy.Extensions
}
}
private static async Task<T> withCancellation<T>(this Task<T> task, CancellationToken cancellationToken) where T : struct
internal static async Task<T> WithCancellation<T>(this Task<T> task, CancellationToken cancellationToken) where T : struct
{
var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
......
......@@ -12,8 +12,8 @@ namespace Titanium.Web.Proxy.Helpers
{
public TcpClientConnection Connection { get; }
internal HttpClientStream(TcpClientConnection connection, Stream stream, IBufferPool bufferPool)
: base(stream, bufferPool)
internal HttpClientStream(TcpClientConnection connection, Stream stream, IBufferPool bufferPool, CancellationToken cancellationToken)
: base(stream, bufferPool, cancellationToken)
{
Connection = connection;
}
......
......@@ -10,8 +10,8 @@ namespace Titanium.Web.Proxy.Helpers
{
internal sealed class HttpServerStream : HttpStream
{
internal HttpServerStream(Stream stream, IBufferPool bufferPool)
: base(stream, bufferPool)
internal HttpServerStream(Stream stream, IBufferPool bufferPool, CancellationToken cancellationToken)
: base(stream, bufferPool, cancellationToken)
{
}
......
......@@ -9,6 +9,7 @@ using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Compression;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Shared;
......@@ -19,7 +20,7 @@ namespace Titanium.Web.Proxy.Helpers
{
internal class HttpStream : Stream, IHttpStreamWriter, IHttpStreamReader, IPeekStream
{
private readonly bool swallowException;
private readonly bool isNetworkStream;
private readonly bool leaveOpen;
private readonly byte[] streamBuffer;
......@@ -37,6 +38,7 @@ namespace Titanium.Web.Proxy.Helpers
private bool closedRead;
private readonly IBufferPool bufferPool;
private readonly CancellationToken cancellationToken;
public event EventHandler<DataEventArgs>? DataRead;
......@@ -71,18 +73,20 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
/// <param name="baseStream">The base stream.</param>
/// <param name="bufferPool">Bufferpool.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="leaveOpen"><see langword="true" /> to leave the stream open after disposing the <see cref="T:CustomBufferedStream" /> object; otherwise, <see langword="false" />.</param>
internal HttpStream(Stream baseStream, IBufferPool bufferPool, bool leaveOpen = false)
internal HttpStream(Stream baseStream, IBufferPool bufferPool, CancellationToken cancellationToken, bool leaveOpen = false)
{
if (baseStream is NetworkStream)
{
swallowException = true;
isNetworkStream = true;
}
this.baseStream = baseStream;
this.leaveOpen = leaveOpen;
streamBuffer = bufferPool.GetBuffer();
this.bufferPool = bufferPool;
this.cancellationToken = cancellationToken;
}
/// <summary>
......@@ -102,7 +106,7 @@ namespace Titanium.Web.Proxy.Helpers
catch
{
closedWrite = true;
if (!swallowException)
if (!isNetworkStream)
throw;
}
}
......@@ -181,7 +185,7 @@ namespace Titanium.Web.Proxy.Helpers
catch
{
closedWrite = true;
if (!swallowException)
if (!isNetworkStream)
throw;
}
}
......@@ -228,7 +232,7 @@ namespace Titanium.Web.Proxy.Helpers
catch
{
closedWrite = true;
if (!swallowException)
if (!isNetworkStream)
throw;
}
}
......@@ -450,7 +454,7 @@ namespace Titanium.Web.Proxy.Helpers
catch
{
closedWrite = true;
if (!swallowException)
if (!isNetworkStream)
throw;
}
}
......@@ -476,7 +480,7 @@ namespace Titanium.Web.Proxy.Helpers
catch
{
closedWrite = true;
if (!swallowException)
if (!isNetworkStream)
throw;
}
finally
......@@ -609,7 +613,7 @@ namespace Titanium.Web.Proxy.Helpers
}
catch
{
if (!swallowException)
if (!isNetworkStream)
throw;
}
finally
......@@ -655,7 +659,13 @@ namespace Titanium.Web.Proxy.Helpers
bool result = false;
try
{
int readBytes = await baseStream.ReadAsync(streamBuffer, bufferLength, bytesToRead, cancellationToken);
var readTask = baseStream.ReadAsync(streamBuffer, bufferLength, bytesToRead, cancellationToken);
if (isNetworkStream)
{
readTask = readTask.WithCancellation(cancellationToken);
}
int readBytes = await readTask;
result = readBytes > 0;
if (result)
{
......@@ -665,7 +675,7 @@ namespace Titanium.Web.Proxy.Helpers
}
catch
{
if (!swallowException)
if (!isNetworkStream)
throw;
}
finally
......@@ -771,14 +781,18 @@ namespace Titanium.Web.Proxy.Helpers
return base.BeginRead(buffer, offset, count, callback, state);
}
var vAsyncResult = this.ReadAsync(buffer, offset, count);
var vAsyncResult = this.ReadAsync(buffer, offset, count, cancellationToken);
if (isNetworkStream)
{
vAsyncResult = vAsyncResult.WithCancellation(cancellationToken);
}
vAsyncResult.ContinueWith(pAsyncResult =>
{
// use TaskExtended to pass State as AsyncObject
// callback will call EndRead (otherwise, it will block)
callback?.Invoke(new TaskResult<int>(pAsyncResult, state));
});
}, cancellationToken);
return vAsyncResult;
}
......@@ -811,12 +825,12 @@ namespace Titanium.Web.Proxy.Helpers
return base.BeginWrite(buffer, offset, count, callback, state);
}
var vAsyncResult = this.WriteAsync(buffer, offset, count);
var vAsyncResult = this.WriteAsync(buffer, offset, count, cancellationToken);
vAsyncResult.ContinueWith(pAsyncResult =>
{
callback?.Invoke(new TaskResult(pAsyncResult, state));
});
}, cancellationToken);
return vAsyncResult;
}
......@@ -868,7 +882,7 @@ namespace Titanium.Web.Proxy.Helpers
catch
{
closedWrite = true;
if (!swallowException)
if (!isNetworkStream)
throw;
}
finally
......@@ -893,7 +907,7 @@ namespace Titanium.Web.Proxy.Helpers
catch
{
closedWrite = true;
if (!swallowException)
if (!isNetworkStream)
throw;
}
}
......@@ -940,7 +954,7 @@ namespace Titanium.Web.Proxy.Helpers
catch
{
closedWrite = true;
if (!swallowException)
if (!isNetworkStream)
throw;
}
}
......@@ -964,7 +978,7 @@ namespace Titanium.Web.Proxy.Helpers
catch
{
closedWrite = true;
if (!swallowException)
if (!isNetworkStream)
throw;
}
}
......@@ -1011,7 +1025,7 @@ namespace Titanium.Web.Proxy.Helpers
try
{
var http = new HttpStream(s, bufferPool, true);
var http = new HttpStream(s, bufferPool, cancellationToken, true);
await http.CopyBodyAsync(writer, false, -1, onCopy, cancellationToken);
}
finally
......@@ -1196,7 +1210,7 @@ namespace Titanium.Web.Proxy.Helpers
catch
{
closedWrite = true;
if (!swallowException)
if (!isNetworkStream)
throw;
}
}
......@@ -1217,7 +1231,7 @@ namespace Titanium.Web.Proxy.Helpers
}
catch
{
if (!swallowException)
if (!isNetworkStream)
throw;
}
}
......
......@@ -445,7 +445,7 @@ retry:
await proxyServer.InvokeServerConnectionCreateEvent(tcpClient);
stream = new HttpServerStream(tcpClient.GetStream(), proxyServer.BufferPool);
stream = new HttpServerStream(tcpClient.GetStream(), proxyServer.BufferPool, cancellationToken);
if (externalProxy != null && (isConnect || isHttps))
{
......@@ -487,7 +487,7 @@ retry:
(sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) =>
proxyServer.SelectClientCertificate(sender, sessionArgs, targetHost, localCertificates,
remoteCertificate, acceptableIssuers));
stream = new HttpServerStream(sslStream, proxyServer.BufferPool);
stream = new HttpServerStream(sslStream, proxyServer.BufferPool, cancellationToken);
var options = new SslClientAuthenticationOptions
{
......
......@@ -272,7 +272,7 @@ namespace Titanium.Web.Proxy
cancellationToken);
// for connection pool, retry fails until cache is exhausted.
return await retryPolicy<ServerConnectionException>().ExecuteAsync(async (connection) =>
return await retryPolicy<ServerConnectionException>().ExecuteAsync(async connection =>
{
// set the connection and send request headers
args.HttpClient.SetConnection(connection);
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp2.1</TargetFrameworks>
<TargetFrameworks>netstandard2.1</TargetFrameworks>
<RootNamespace>Titanium.Web.Proxy</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5.2" />
<PackageReference Include="System.Buffers" Version="4.5.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<ItemGroup Condition="'$(TargetFramework)' != 'net45'">
<PackageReference Include="Microsoft.Win32.Registry">
<Version>4.6.0</Version>
<Version>4.7.0</Version>
</PackageReference>
<PackageReference Include="System.Security.Principal.Windows">
<Version>4.6.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
<PackageReference Include="Microsoft.Win32.Registry">
<Version>4.6.0</Version>
</PackageReference>
<PackageReference Include="System.Security.Principal.Windows">
<Version>4.6.0</Version>
<Version>4.7.0</Version>
</PackageReference>
</ItemGroup>
......
......@@ -25,10 +25,10 @@
<ItemGroup Condition="'$(TargetFramework)' != 'net45'">
<PackageReference Include="Microsoft.Win32.Registry">
<Version>4.6.0</Version>
<Version>4.7.0</Version>
</PackageReference>
<PackageReference Include="System.Security.Principal.Windows">
<Version>4.6.0</Version>
<Version>4.7.0</Version>
</PackageReference>
</ItemGroup>
......
......@@ -24,26 +24,26 @@
<group targetFramework="net461">
<dependency id="BrotliSharpLib" version="0.3.3" />
<dependency id="Portable.BouncyCastle" version="1.8.5.2" />
<dependency id="Microsoft.Win32.Registry" version="4.6.0" />
<dependency id="Microsoft.Win32.Registry" version="4.7.0" />
<dependency id="System.Buffers" version="4.5.0" />
<dependency id="System.Memory" version="4.5.3" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3" />
<dependency id="System.Security.Principal.Windows" version="4.6.0" />
<dependency id="System.Security.Principal.Windows" version="4.7.0" />
</group>
<group targetFramework="netstandard2.0">
<dependency id="BrotliSharpLib" version="0.3.3" />
<dependency id="Portable.BouncyCastle" version="1.8.5.2" />
<dependency id="Microsoft.Win32.Registry" version="4.6.0" />
<dependency id="Microsoft.Win32.Registry" version="4.7.0" />
<dependency id="System.Buffers" version="4.5.0" />
<dependency id="System.Memory" version="4.5.3" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3" />
<dependency id="System.Security.Principal.Windows" version="4.6.0" />
<dependency id="System.Security.Principal.Windows" version="4.7.0" />
</group>
<group targetFramework="netstandard2.1">
<dependency id="BrotliSharpLib" version="0.3.3" />
<dependency id="Portable.BouncyCastle" version="1.8.5.2" />
<dependency id="Microsoft.Win32.Registry" version="4.6.0" />
<dependency id="System.Security.Principal.Windows" version="4.6.0" />
<dependency id="Microsoft.Win32.Registry" version="4.7.0" />
<dependency id="System.Security.Principal.Windows" version="4.7.0" />
</group>
</dependencies>
</metadata>
......
......@@ -30,9 +30,7 @@ namespace Titanium.Web.Proxy
var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool);
SslStream? sslStream = null;
var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken);
try
{
......@@ -57,6 +55,7 @@ namespace Titanium.Web.Proxy
// do client authentication using certificate
X509Certificate2? certificate = null;
SslStream? sslStream = null;
try
{
sslStream = new SslStream(clientStream, false);
......@@ -69,17 +68,18 @@ namespace Titanium.Web.Proxy
await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false);
// HTTPS server created - we can now decrypt the client's traffic
clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool);
clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool, cancellationToken);
sslStream = null; // clientStream was created, no need to keep SSL stream reference
}
catch (Exception e)
{
sslStream?.Dispose();
var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
var session = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource);
throw new ProxyConnectException(
$"Couldn't authenticate host '{httpsHostName}' with certificate '{certName}'.", e, session);
}
}
else
{
......@@ -146,7 +146,6 @@ namespace Titanium.Web.Proxy
}
finally
{
sslStream?.Dispose();
clientStream.Dispose();
}
}
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
......@@ -14,9 +14,7 @@
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment