Unverified Commit 17abd9b8 authored by honfika's avatar honfika Committed by GitHub

Merge pull request #711 from justcoding121/master

stable
parents 30b18236 d21ea354
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
"name": "NetCore|Debug|Basic Example", "name": "NetCore|Debug|Basic Example",
"type": "coreclr", "type": "coreclr",
"request": "launch", "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": [], "args": [],
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"stopAtEntry": false, "stopAtEntry": false,
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
"name": "NetCore|Release|Basic Example", "name": "NetCore|Release|Basic Example",
"type": "coreclr", "type": "coreclr",
"request": "launch", "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": [], "args": [],
"cwd": "${workspaceRoot}", "cwd": "${workspaceRoot}",
"stopAtEntry": false, "stopAtEntry": false,
......
...@@ -207,6 +207,17 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -207,6 +207,17 @@ namespace Titanium.Web.Proxy.Examples.Basic
{ {
e.GetState().PipelineInfo.AppendLine(nameof(onRequest) + ":" + e.HttpClient.Request.RequestUri); e.GetState().PipelineInfo.AppendLine(nameof(onRequest) + ":" + e.HttpClient.Request.RequestUri);
var clientLocalIp = e.ClientLocalEndPoint.Address;
if (!clientLocalIp.Equals(IPAddress.Loopback) && !clientLocalIp.Equals(IPAddress.IPv6Loopback))
{
e.HttpClient.UpStreamEndPoint = new IPEndPoint(clientLocalIp, 0);
}
if (e.HttpClient.Request.Url.Contains("yahoo.com"))
{
e.CustomUpStreamProxy = new ExternalProxy("localhost", 8888);
}
await writeToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount); await writeToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
await writeToConsole(e.HttpClient.Request.Url); await writeToConsole(e.HttpClient.Request.Url);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp2.1</TargetFrameworks> <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<LangVersion>7.1</LangVersion> <LangVersion>7.1</LangVersion>
</PropertyGroup> </PropertyGroup>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFrameworks>net461;netcoreapp3.0</TargetFrameworks> <TargetFrameworks>net461;netcoreapp3.1</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<LangVersion>7.1</LangVersion> <LangVersion>7.1</LangVersion>
</PropertyGroup> </PropertyGroup>
......
...@@ -103,16 +103,16 @@ ...@@ -103,16 +103,16 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry"> <PackageReference Include="Microsoft.Win32.Registry">
<Version>4.6.0</Version> <Version>4.7.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.Numerics.Vectors"> <PackageReference Include="System.Numerics.Vectors">
<Version>4.5.0</Version> <Version>4.5.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.Runtime.CompilerServices.Unsafe"> <PackageReference Include="System.Runtime.CompilerServices.Unsafe">
<Version>4.6.0</Version> <Version>4.7.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.ServiceProcess.ServiceController"> <PackageReference Include="System.ServiceProcess.ServiceController">
<Version>4.6.0</Version> <Version>4.7.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.Threading.Tasks.Extensions"> <PackageReference Include="System.Threading.Tasks.Extensions">
<Version>4.5.3</Version> <Version>4.5.3</Version>
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
<GridViewColumn Header="Process" DisplayMemberBinding="{Binding Process}" /> <GridViewColumn Header="Process" DisplayMemberBinding="{Binding Process}" />
<GridViewColumn Header="SentBytes" DisplayMemberBinding="{Binding SentDataCount}" /> <GridViewColumn Header="SentBytes" DisplayMemberBinding="{Binding SentDataCount}" />
<GridViewColumn Header="ReceivedBytes" DisplayMemberBinding="{Binding ReceivedDataCount}" /> <GridViewColumn Header="ReceivedBytes" DisplayMemberBinding="{Binding ReceivedDataCount}" />
<GridViewColumn Header="ClientEndPoint" DisplayMemberBinding="{Binding ClientEndPoint}" /> <GridViewColumn Header="ClientRemoteEndPoint" DisplayMemberBinding="{Binding ClientRemoteEndPoint}" />
<GridViewColumn Header="ClientConnectionId" DisplayMemberBinding="{Binding ClientConnectionId}" /> <GridViewColumn Header="ClientConnectionId" DisplayMemberBinding="{Binding ClientConnectionId}" />
<GridViewColumn Header="ServerConnectionId" DisplayMemberBinding="{Binding ServerConnectionId}" /> <GridViewColumn Header="ServerConnectionId" DisplayMemberBinding="{Binding ServerConnectionId}" />
</GridView> </GridView>
......
...@@ -229,7 +229,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -229,7 +229,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf
ClientConnectionId = e.ClientConnectionId, ClientConnectionId = e.ClientConnectionId,
ServerConnectionId = e.ServerConnectionId, ServerConnectionId = e.ServerConnectionId,
HttpClient = e.HttpClient, HttpClient = e.HttpClient,
ClientEndPoint = e.ClientEndPoint, ClientRemoteEndPoint = e.ClientRemoteEndPoint,
ClientLocalEndPoint = e.ClientLocalEndPoint,
IsTunnelConnect = isTunnelConnect IsTunnelConnect = isTunnelConnect
}; };
......
...@@ -38,7 +38,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -38,7 +38,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf
public HttpWebClient HttpClient { get; set; } public HttpWebClient HttpClient { get; set; }
public IPEndPoint ClientEndPoint { get; set; } public IPEndPoint ClientLocalEndPoint { get; set; }
public IPEndPoint ClientRemoteEndPoint { get; set; }
public bool IsTunnelConnect { get; set; } public bool IsTunnelConnect { get; set; }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>netcoreapp3.0</TargetFrameworks> <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
</PropertyGroup> </PropertyGroup>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFrameworks>net461;netcoreapp3.0</TargetFrameworks> <TargetFrameworks>net461;netcoreapp3.1</TargetFrameworks>
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
</PropertyGroup> </PropertyGroup>
......
using System;
using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy.EventArguments
{
public class EmptyProxyEventArgs : ProxyEventArgsBase
{
internal EmptyProxyEventArgs(TcpClientConnection clientConnection) : base(clientConnection)
{
}
}
}
...@@ -25,7 +25,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -25,7 +25,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
private bool reRequest; private bool reRequest;
private WebSocketDecoder webSocketDecoder; private WebSocketDecoder? webSocketDecoder;
/// <summary> /// <summary>
/// Is this session a HTTP/2 promise? /// Is this session a HTTP/2 promise?
...@@ -190,7 +190,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -190,7 +190,7 @@ namespace Titanium.Web.Proxy.EventArguments
private async Task<byte[]> readBodyAsync(bool isRequest, CancellationToken cancellationToken) private async Task<byte[]> readBodyAsync(bool isRequest, CancellationToken cancellationToken)
{ {
using var bodyStream = new MemoryStream(); using var bodyStream = new MemoryStream();
using var writer = new HttpStream(bodyStream, BufferPool); using var writer = new HttpStream(bodyStream, BufferPool, cancellationToken);
if (isRequest) if (isRequest)
{ {
...@@ -221,7 +221,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -221,7 +221,7 @@ namespace Titanium.Web.Proxy.EventArguments
var reader = isRequest ? (HttpStream)ClientStream : HttpClient.Connection.Stream; var reader = isRequest ? (HttpStream)ClientStream : HttpClient.Connection.Stream;
await reader.CopyBodyAsync(requestResponse, true, new NullWriter(), TransformationMode.None, null, cancellationToken); await reader.CopyBodyAsync(requestResponse, true, NullWriter.Instance, TransformationMode.None, null, cancellationToken);
} }
/// <summary> /// <summary>
......
...@@ -59,7 +59,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -59,7 +59,7 @@ namespace Titanium.Web.Proxy.EventArguments
ClientStream = clientStream; ClientStream = clientStream;
HttpClient = new HttpWebClient(connectRequest, request, new Lazy<int>(() => clientStream.Connection.GetProcessId(endPoint))); HttpClient = new HttpWebClient(connectRequest, request, new Lazy<int>(() => clientStream.Connection.GetProcessId(endPoint)));
LocalEndPoint = endPoint; ProxyEndPoint = endPoint;
EnableWinAuth = server.EnableWinAuth && isWindowsAuthenticationSupported; EnableWinAuth = server.EnableWinAuth && isWindowsAuthenticationSupported;
} }
...@@ -94,9 +94,17 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -94,9 +94,17 @@ namespace Titanium.Web.Proxy.EventArguments
public bool IsHttps => HttpClient.Request.IsHttps; public bool IsHttps => HttpClient.Request.IsHttps;
/// <summary> /// <summary>
/// Client End Point. /// Client Local End Point.
/// </summary> /// </summary>
public IPEndPoint ClientEndPoint => (IPEndPoint)ClientConnection.RemoteEndPoint; public IPEndPoint ClientLocalEndPoint => (IPEndPoint)ClientConnection.LocalEndPoint;
/// <summary>
/// Client Remote End Point.
/// </summary>
public IPEndPoint ClientRemoteEndPoint => (IPEndPoint)ClientConnection.RemoteEndPoint;
[Obsolete("Use ClientRemoteEndPoint instead.")]
public IPEndPoint ClientEndPoint => ClientRemoteEndPoint;
/// <summary> /// <summary>
/// The web client used to communicate with server for this session. /// The web client used to communicate with server for this session.
...@@ -106,6 +114,14 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -106,6 +114,14 @@ namespace Titanium.Web.Proxy.EventArguments
[Obsolete("Use HttpClient instead.")] [Obsolete("Use HttpClient instead.")]
public HttpWebClient WebSession => HttpClient; public HttpWebClient WebSession => HttpClient;
/// <summary>
/// Gets or sets the custom up stream proxy.
/// </summary>
/// <value>
/// The custom up stream proxy.
/// </value>
public IExternalProxy? CustomUpStreamProxy { get; set; }
/// <summary> /// <summary>
/// Are we using a custom upstream HTTP(S) proxy? /// Are we using a custom upstream HTTP(S) proxy?
/// </summary> /// </summary>
...@@ -114,12 +130,15 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -114,12 +130,15 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Local endpoint via which we make the request. /// Local endpoint via which we make the request.
/// </summary> /// </summary>
public ProxyEndPoint LocalEndPoint { get; } public ProxyEndPoint ProxyEndPoint { get; }
[Obsolete("Use ProxyEndPoint instead.")]
public ProxyEndPoint LocalEndPoint => ProxyEndPoint;
/// <summary> /// <summary>
/// Is this a transparent endpoint? /// Is this a transparent endpoint?
/// </summary> /// </summary>
public bool IsTransparent => LocalEndPoint is TransparentProxyEndPoint; public bool IsTransparent => ProxyEndPoint is TransparentProxyEndPoint;
/// <summary> /// <summary>
/// The last exception that happened. /// The last exception that happened.
......
...@@ -33,13 +33,10 @@ namespace Titanium.Web.Proxy ...@@ -33,13 +33,10 @@ namespace Titanium.Web.Proxy
var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token; 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; Task<TcpServerConnection>? prefetchConnectionTask = null;
bool closeServerConnection = false; bool closeServerConnection = false;
bool calledRequestHandler = false;
SslStream? sslStream = null;
try try
{ {
...@@ -191,6 +188,7 @@ namespace Titanium.Web.Proxy ...@@ -191,6 +188,7 @@ namespace Titanium.Web.Proxy
} }
X509Certificate2? certificate = null; X509Certificate2? certificate = null;
SslStream? sslStream = null;
try try
{ {
sslStream = new SslStream(clientStream, false); sslStream = new SslStream(clientStream, false);
...@@ -221,7 +219,7 @@ namespace Titanium.Web.Proxy ...@@ -221,7 +219,7 @@ namespace Titanium.Web.Proxy
#endif #endif
// HTTPS server created - we can now decrypt the client's traffic // 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 sslStream = null; // clientStream was created, no need to keep SSL stream reference
clientStream.DataRead += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count); clientStream.DataRead += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count);
...@@ -229,6 +227,8 @@ namespace Titanium.Web.Proxy ...@@ -229,6 +227,8 @@ namespace Titanium.Web.Proxy
} }
catch (Exception e) catch (Exception e)
{ {
sslStream?.Dispose();
var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false); var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
throw new ProxyConnectException( throw new ProxyConnectException(
$"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs); $"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs);
...@@ -374,10 +374,11 @@ namespace Titanium.Web.Proxy ...@@ -374,10 +374,11 @@ namespace Titanium.Web.Proxy
} }
} }
calledRequestHandler = true; var prefetchTask = prefetchConnectionTask;
prefetchConnectionTask = null;
// Now create the request // Now create the request
await handleHttpSessionRequest(endPoint, clientStream, cancellationTokenSource, connectArgs, prefetchConnectionTask); await handleHttpSessionRequest(endPoint, clientStream, cancellationTokenSource, connectArgs, prefetchTask);
} }
catch (ProxyException e) catch (ProxyException e)
{ {
...@@ -401,12 +402,13 @@ namespace Titanium.Web.Proxy ...@@ -401,12 +402,13 @@ namespace Titanium.Web.Proxy
} }
finally finally
{ {
if (!calledRequestHandler) if (!cancellationTokenSource.IsCancellationRequested)
{ {
await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection); cancellationTokenSource.Cancel();
} }
sslStream?.Dispose(); await tcpConnectionFactory.Release(prefetchConnectionTask, closeServerConnection);
clientStream.Dispose(); clientStream.Dispose();
} }
} }
......
...@@ -42,8 +42,8 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -42,8 +42,8 @@ namespace Titanium.Web.Proxy.Extensions
{ {
// cancellation is not working on Socket ReadAsync // cancellation is not working on Socket ReadAsync
// https://github.com/dotnet/corefx/issues/15033 // https://github.com/dotnet/corefx/issues/15033
int num = await input.ReadAsync(buffer, 0, buffer.Length, CancellationToken.None) int num = await input.ReadAsync(buffer, 0, buffer.Length, cancellationToken)
.withCancellation(cancellationToken); .WithCancellation(cancellationToken);
int bytesRead; int bytesRead;
if ((bytesRead = num) != 0 && !cancellationToken.IsCancellationRequested) if ((bytesRead = num) != 0 && !cancellationToken.IsCancellationRequested)
{ {
...@@ -62,7 +62,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -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>(); var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs)) using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
......
...@@ -12,8 +12,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -12,8 +12,8 @@ namespace Titanium.Web.Proxy.Helpers
{ {
public TcpClientConnection Connection { get; } public TcpClientConnection Connection { get; }
internal HttpClientStream(TcpClientConnection connection, Stream stream, IBufferPool bufferPool) internal HttpClientStream(TcpClientConnection connection, Stream stream, IBufferPool bufferPool, CancellationToken cancellationToken)
: base(stream, bufferPool) : base(stream, bufferPool, cancellationToken)
{ {
Connection = connection; Connection = connection;
} }
......
...@@ -10,8 +10,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -10,8 +10,8 @@ namespace Titanium.Web.Proxy.Helpers
{ {
internal sealed class HttpServerStream : HttpStream internal sealed class HttpServerStream : HttpStream
{ {
internal HttpServerStream(Stream stream, IBufferPool bufferPool) internal HttpServerStream(Stream stream, IBufferPool bufferPool, CancellationToken cancellationToken)
: base(stream, bufferPool) : base(stream, bufferPool, cancellationToken)
{ {
} }
......
...@@ -9,6 +9,7 @@ using System.Threading; ...@@ -9,6 +9,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Compression; using Titanium.Web.Proxy.Compression;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
...@@ -19,7 +20,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -19,7 +20,7 @@ namespace Titanium.Web.Proxy.Helpers
{ {
internal class HttpStream : Stream, IHttpStreamWriter, IHttpStreamReader, IPeekStream internal class HttpStream : Stream, IHttpStreamWriter, IHttpStreamReader, IPeekStream
{ {
private readonly bool swallowException; private readonly bool isNetworkStream;
private readonly bool leaveOpen; private readonly bool leaveOpen;
private readonly byte[] streamBuffer; private readonly byte[] streamBuffer;
...@@ -37,6 +38,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -37,6 +38,7 @@ namespace Titanium.Web.Proxy.Helpers
private bool closedRead; private bool closedRead;
private readonly IBufferPool bufferPool; private readonly IBufferPool bufferPool;
private readonly CancellationToken cancellationToken;
public event EventHandler<DataEventArgs>? DataRead; public event EventHandler<DataEventArgs>? DataRead;
...@@ -71,18 +73,20 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -71,18 +73,20 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
/// <param name="baseStream">The base stream.</param> /// <param name="baseStream">The base stream.</param>
/// <param name="bufferPool">Bufferpool.</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> /// <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) if (baseStream is NetworkStream)
{ {
swallowException = true; isNetworkStream = true;
} }
this.baseStream = baseStream; this.baseStream = baseStream;
this.leaveOpen = leaveOpen; this.leaveOpen = leaveOpen;
streamBuffer = bufferPool.GetBuffer(); streamBuffer = bufferPool.GetBuffer();
this.bufferPool = bufferPool; this.bufferPool = bufferPool;
this.cancellationToken = cancellationToken;
} }
/// <summary> /// <summary>
...@@ -102,7 +106,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -102,7 +106,7 @@ namespace Titanium.Web.Proxy.Helpers
catch catch
{ {
closedWrite = true; closedWrite = true;
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
} }
...@@ -181,7 +185,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -181,7 +185,7 @@ namespace Titanium.Web.Proxy.Helpers
catch catch
{ {
closedWrite = true; closedWrite = true;
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
} }
...@@ -228,7 +232,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -228,7 +232,7 @@ namespace Titanium.Web.Proxy.Helpers
catch catch
{ {
closedWrite = true; closedWrite = true;
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
} }
...@@ -450,7 +454,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -450,7 +454,7 @@ namespace Titanium.Web.Proxy.Helpers
catch catch
{ {
closedWrite = true; closedWrite = true;
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
} }
...@@ -476,7 +480,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -476,7 +480,7 @@ namespace Titanium.Web.Proxy.Helpers
catch catch
{ {
closedWrite = true; closedWrite = true;
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
finally finally
...@@ -609,7 +613,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -609,7 +613,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
catch catch
{ {
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
finally finally
...@@ -655,7 +659,13 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -655,7 +659,13 @@ namespace Titanium.Web.Proxy.Helpers
bool result = false; bool result = false;
try 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; result = readBytes > 0;
if (result) if (result)
{ {
...@@ -665,7 +675,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -665,7 +675,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
catch catch
{ {
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
finally finally
...@@ -771,14 +781,18 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -771,14 +781,18 @@ namespace Titanium.Web.Proxy.Helpers
return base.BeginRead(buffer, offset, count, callback, state); 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 => vAsyncResult.ContinueWith(pAsyncResult =>
{ {
// use TaskExtended to pass State as AsyncObject // use TaskExtended to pass State as AsyncObject
// callback will call EndRead (otherwise, it will block) // callback will call EndRead (otherwise, it will block)
callback?.Invoke(new TaskResult<int>(pAsyncResult, state)); callback?.Invoke(new TaskResult<int>(pAsyncResult, state));
}); }, cancellationToken);
return vAsyncResult; return vAsyncResult;
} }
...@@ -811,12 +825,12 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -811,12 +825,12 @@ namespace Titanium.Web.Proxy.Helpers
return base.BeginWrite(buffer, offset, count, callback, state); 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 => vAsyncResult.ContinueWith(pAsyncResult =>
{ {
callback?.Invoke(new TaskResult(pAsyncResult, state)); callback?.Invoke(new TaskResult(pAsyncResult, state));
}); }, cancellationToken);
return vAsyncResult; return vAsyncResult;
} }
...@@ -868,7 +882,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -868,7 +882,7 @@ namespace Titanium.Web.Proxy.Helpers
catch catch
{ {
closedWrite = true; closedWrite = true;
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
finally finally
...@@ -893,7 +907,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -893,7 +907,7 @@ namespace Titanium.Web.Proxy.Helpers
catch catch
{ {
closedWrite = true; closedWrite = true;
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
} }
...@@ -940,7 +954,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -940,7 +954,7 @@ namespace Titanium.Web.Proxy.Helpers
catch catch
{ {
closedWrite = true; closedWrite = true;
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
} }
...@@ -964,7 +978,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -964,7 +978,7 @@ namespace Titanium.Web.Proxy.Helpers
catch catch
{ {
closedWrite = true; closedWrite = true;
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
} }
...@@ -1011,7 +1025,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -1011,7 +1025,7 @@ namespace Titanium.Web.Proxy.Helpers
try try
{ {
var http = new HttpStream(s, bufferPool, true); var http = new HttpStream(s, bufferPool, cancellationToken, true);
await http.CopyBodyAsync(writer, false, -1, onCopy, cancellationToken); await http.CopyBodyAsync(writer, false, -1, onCopy, cancellationToken);
} }
finally finally
...@@ -1196,7 +1210,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -1196,7 +1210,7 @@ namespace Titanium.Web.Proxy.Helpers
catch catch
{ {
closedWrite = true; closedWrite = true;
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
} }
...@@ -1217,7 +1231,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -1217,7 +1231,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
catch catch
{ {
if (!swallowException) if (!isNetworkStream)
throw; throw;
} }
} }
......
...@@ -8,6 +8,10 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -8,6 +8,10 @@ namespace Titanium.Web.Proxy.Helpers
{ {
public static NullWriter Instance { get; } = new NullWriter(); public static NullWriter Instance { get; } = new NullWriter();
private NullWriter()
{
}
public void Write(byte[] buffer, int offset, int count) public void Write(byte[] buffer, int offset, int count)
{ {
} }
......
...@@ -114,11 +114,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -114,11 +114,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
} }
// TODO: Apply authorization // TODO: Apply authorization
var systemProxy = new ExternalProxy var systemProxy = new ExternalProxy(proxyStr, port);
{
HostName = proxyStr,
Port = port
};
return systemProxy; return systemProxy;
} }
...@@ -134,12 +130,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -134,12 +130,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
HttpSystemProxyValue? value = null; HttpSystemProxyValue? value = null;
if (ProxyInfo?.Proxies?.TryGetValue(protocolType.Value, out value) == true) if (ProxyInfo?.Proxies?.TryGetValue(protocolType.Value, out value) == true)
{ {
var systemProxy = new ExternalProxy var systemProxy = new ExternalProxy(value!.HostName, value.Port);
{
HostName = value!.HostName,
Port = value.Port
};
return systemProxy; return systemProxy;
} }
} }
......
...@@ -166,6 +166,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -166,6 +166,8 @@ namespace Titanium.Web.Proxy.Http
return; return;
} }
Response.RequestMethod = Request.Method;
var httpStatus = await Connection.Stream.ReadResponseStatus(cancellationToken); var httpStatus = await Connection.Stream.ReadResponseStatus(cancellationToken);
Response.HttpVersion = httpStatus.Version; Response.HttpVersion = httpStatus.Version;
Response.StatusCode = httpStatus.StatusCode; Response.StatusCode = httpStatus.StatusCode;
......
...@@ -36,6 +36,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -36,6 +36,8 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public string StatusDescription { get; set; } = string.Empty; public string StatusDescription { get; set; } = string.Empty;
internal string RequestMethod { get; set; }
/// <summary> /// <summary>
/// Has response body? /// Has response body?
/// </summary> /// </summary>
...@@ -43,6 +45,11 @@ namespace Titanium.Web.Proxy.Http ...@@ -43,6 +45,11 @@ namespace Titanium.Web.Proxy.Http
{ {
get get
{ {
if (RequestMethod == "HEAD")
{
return false;
}
long contentLength = ContentLength; long contentLength = ContentLength;
// If content length is set to 0 the response has no body // If content length is set to 0 the response has no body
......
...@@ -69,6 +69,39 @@ namespace Titanium.Web.Proxy.Models ...@@ -69,6 +69,39 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public int Port { get; set; } public int Port { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ExternalProxy"/> class.
/// </summary>
public ExternalProxy()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ExternalProxy"/> class.
/// </summary>
/// <param name="hostName">Name of the host.</param>
/// <param name="port">The port.</param>
public ExternalProxy(string hostName, int port)
{
HostName = hostName;
Port = port;
}
/// <summary>
/// Initializes a new instance of the <see cref="ExternalProxy"/> class.
/// </summary>
/// <param name="hostName">Name of the host.</param>
/// <param name="port">The port.</param>
/// <param name="userName">Name of the user.</param>
/// <param name="password">The password.</param>
public ExternalProxy(string hostName, int port, string userName, string password)
{
HostName = hostName;
Port = port;
UserName = userName;
Password = password;
}
/// <summary> /// <summary>
/// returns data in Hostname:port format. /// returns data in Hostname:port format.
/// </summary> /// </summary>
...@@ -77,6 +110,5 @@ namespace Titanium.Web.Proxy.Models ...@@ -77,6 +110,5 @@ namespace Titanium.Web.Proxy.Models
{ {
return $"{HostName}:{Port}"; return $"{HostName}:{Port}";
} }
} }
} }
...@@ -114,10 +114,10 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -114,10 +114,10 @@ namespace Titanium.Web.Proxy.Network.Tcp
applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol }; applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol };
} }
IExternalProxy? customUpStreamProxy = null; IExternalProxy? customUpStreamProxy = session.CustomUpStreamProxy;
bool isHttps = session.IsHttps; bool isHttps = session.IsHttps;
if (server.GetCustomUpStreamProxyFunc != null) if (customUpStreamProxy == null && server.GetCustomUpStreamProxyFunc != null)
{ {
customUpStreamProxy = await server.GetCustomUpStreamProxyFunc(session); customUpStreamProxy = await server.GetCustomUpStreamProxyFunc(session);
} }
...@@ -169,10 +169,10 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -169,10 +169,10 @@ namespace Titanium.Web.Proxy.Network.Tcp
internal async Task<TcpServerConnection> GetServerConnection(ProxyServer proxyServer, SessionEventArgsBase session, bool isConnect, internal async Task<TcpServerConnection> GetServerConnection(ProxyServer proxyServer, SessionEventArgsBase session, bool isConnect,
List<SslApplicationProtocol>? applicationProtocols, bool noCache, CancellationToken cancellationToken) List<SslApplicationProtocol>? applicationProtocols, bool noCache, CancellationToken cancellationToken)
{ {
IExternalProxy? customUpStreamProxy = null; IExternalProxy? customUpStreamProxy = session.CustomUpStreamProxy;
bool isHttps = session.IsHttps; bool isHttps = session.IsHttps;
if (proxyServer.GetCustomUpStreamProxyFunc != null) if (customUpStreamProxy == null && proxyServer.GetCustomUpStreamProxyFunc != null)
{ {
customUpStreamProxy = await proxyServer.GetCustomUpStreamProxyFunc(session); customUpStreamProxy = await proxyServer.GetCustomUpStreamProxyFunc(session);
} }
...@@ -445,7 +445,7 @@ retry: ...@@ -445,7 +445,7 @@ retry:
await proxyServer.InvokeServerConnectionCreateEvent(tcpClient); await proxyServer.InvokeServerConnectionCreateEvent(tcpClient);
stream = new HttpServerStream(tcpClient.GetStream(), proxyServer.BufferPool); stream = new HttpServerStream(tcpClient.GetStream(), proxyServer.BufferPool, cancellationToken);
if (externalProxy != null && (isConnect || isHttps)) if (externalProxy != null && (isConnect || isHttps))
{ {
...@@ -487,7 +487,7 @@ retry: ...@@ -487,7 +487,7 @@ retry:
(sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) => (sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) =>
proxyServer.SelectClientCertificate(sender, sessionArgs, targetHost, localCertificates, proxyServer.SelectClientCertificate(sender, sessionArgs, targetHost, localCertificates,
remoteCertificate, acceptableIssuers)); remoteCertificate, acceptableIssuers));
stream = new HttpServerStream(sslStream, proxyServer.BufferPool); stream = new HttpServerStream(sslStream, proxyServer.BufferPool, cancellationToken);
var options = new SslClientAuthenticationOptions var options = new SslClientAuthenticationOptions
{ {
...@@ -580,20 +580,22 @@ retry: ...@@ -580,20 +580,22 @@ retry:
internal async Task Release(Task<TcpServerConnection>? connectionCreateTask, bool closeServerConnection) internal async Task Release(Task<TcpServerConnection>? connectionCreateTask, bool closeServerConnection)
{ {
if (connectionCreateTask != null) if (connectionCreateTask == null)
{ {
TcpServerConnection? connection = null; return;
try }
{
connection = await connectionCreateTask; TcpServerConnection? connection = null;
} try
catch { } {
finally connection = await connectionCreateTask;
}
catch { }
finally
{
if (connection != null)
{ {
if (connection != null) await Release(connection, closeServerConnection);
{
await Release(connection, closeServerConnection);
}
} }
} }
} }
......
...@@ -272,7 +272,7 @@ namespace Titanium.Web.Proxy ...@@ -272,7 +272,7 @@ namespace Titanium.Web.Proxy
cancellationToken); cancellationToken);
// for connection pool, retry fails until cache is exhausted. // 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 // set the connection and send request headers
args.HttpClient.SetConnection(connection); args.HttpClient.SetConnection(connection);
......
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp2.1</TargetFrameworks> <TargetFrameworks>netstandard2.1</TargetFrameworks>
<RootNamespace>Titanium.Web.Proxy</RootNamespace> <RootNamespace>Titanium.Web.Proxy</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<SignAssembly>True</SignAssembly> <SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign> <DelaySign>False</DelaySign>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
<LangVersion>8.0</LangVersion> <LangVersion>8.0</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.3" /> <PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5.2" /> <PackageReference Include="Portable.BouncyCastle" Version="1.8.5.2" />
<PackageReference Include="System.Buffers" Version="4.5.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' != 'net45'">
<PackageReference Include="Microsoft.Win32.Registry"> <PackageReference Include="Microsoft.Win32.Registry">
<Version>4.6.0</Version> <Version>4.7.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.Security.Principal.Windows"> <PackageReference Include="System.Security.Principal.Windows">
<Version>4.6.0</Version> <Version>4.7.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>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
......
...@@ -25,10 +25,10 @@ ...@@ -25,10 +25,10 @@
<ItemGroup Condition="'$(TargetFramework)' != 'net45'"> <ItemGroup Condition="'$(TargetFramework)' != 'net45'">
<PackageReference Include="Microsoft.Win32.Registry"> <PackageReference Include="Microsoft.Win32.Registry">
<Version>4.6.0</Version> <Version>4.7.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.Security.Principal.Windows"> <PackageReference Include="System.Security.Principal.Windows">
<Version>4.6.0</Version> <Version>4.7.0</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
......
...@@ -24,26 +24,26 @@ ...@@ -24,26 +24,26 @@
<group targetFramework="net461"> <group targetFramework="net461">
<dependency id="BrotliSharpLib" version="0.3.3" /> <dependency id="BrotliSharpLib" version="0.3.3" />
<dependency id="Portable.BouncyCastle" version="1.8.5.2" /> <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.Buffers" version="4.5.0" />
<dependency id="System.Memory" version="4.5.3" /> <dependency id="System.Memory" version="4.5.3" />
<dependency id="System.Threading.Tasks.Extensions" 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>
<group targetFramework="netstandard2.0"> <group targetFramework="netstandard2.0">
<dependency id="BrotliSharpLib" version="0.3.3" /> <dependency id="BrotliSharpLib" version="0.3.3" />
<dependency id="Portable.BouncyCastle" version="1.8.5.2" /> <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.Buffers" version="4.5.0" />
<dependency id="System.Memory" version="4.5.3" /> <dependency id="System.Memory" version="4.5.3" />
<dependency id="System.Threading.Tasks.Extensions" 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>
<group targetFramework="netstandard2.1"> <group targetFramework="netstandard2.1">
<dependency id="BrotliSharpLib" version="0.3.3" /> <dependency id="BrotliSharpLib" version="0.3.3" />
<dependency id="Portable.BouncyCastle" version="1.8.5.2" /> <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.Security.Principal.Windows" version="4.6.0" /> <dependency id="System.Security.Principal.Windows" version="4.7.0" />
</group> </group>
</dependencies> </dependencies>
</metadata> </metadata>
......
...@@ -30,9 +30,7 @@ namespace Titanium.Web.Proxy ...@@ -30,9 +30,7 @@ namespace Titanium.Web.Proxy
var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool); var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken);
SslStream? sslStream = null;
try try
{ {
...@@ -57,6 +55,7 @@ namespace Titanium.Web.Proxy ...@@ -57,6 +55,7 @@ namespace Titanium.Web.Proxy
// do client authentication using certificate // do client authentication using certificate
X509Certificate2? certificate = null; X509Certificate2? certificate = null;
SslStream? sslStream = null;
try try
{ {
sslStream = new SslStream(clientStream, false); sslStream = new SslStream(clientStream, false);
...@@ -69,17 +68,18 @@ namespace Titanium.Web.Proxy ...@@ -69,17 +68,18 @@ namespace Titanium.Web.Proxy
await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false); await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false);
// HTTPS server created - we can now decrypt the client's traffic // 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 sslStream = null; // clientStream was created, no need to keep SSL stream reference
} }
catch (Exception e) catch (Exception e)
{ {
sslStream?.Dispose();
var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false); var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
var session = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource); var session = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource);
throw new ProxyConnectException( throw new ProxyConnectException(
$"Couldn't authenticate host '{httpsHostName}' with certificate '{certName}'.", e, session); $"Couldn't authenticate host '{httpsHostName}' with certificate '{certName}'.", e, session);
} }
} }
else else
{ {
...@@ -146,7 +146,6 @@ namespace Titanium.Web.Proxy ...@@ -146,7 +146,6 @@ namespace Titanium.Web.Proxy
} }
finally finally
{ {
sslStream?.Dispose();
clientStream.Dispose(); clientStream.Dispose();
} }
} }
......
...@@ -175,7 +175,7 @@ namespace Titanium.Web.Proxy ...@@ -175,7 +175,7 @@ namespace Titanium.Web.Proxy
// Add custom div to body to clarify that the proxy (not the client browser) failed authentication // Add custom div to body to clarify that the proxy (not the client browser) failed authentication
string authErrorMessage = string authErrorMessage =
"<div class=\"inserted-by-proxy\"><h2>NTLM authentication through Titanium.Web.Proxy (" + "<div class=\"inserted-by-proxy\"><h2>NTLM authentication through Titanium.Web.Proxy (" +
args.ClientConnection.LocalEndPoint + args.ClientLocalEndPoint +
") failed. Please check credentials.</h2></div>"; ") failed. Please check credentials.</h2></div>";
string originalErrorMessage = string originalErrorMessage =
"<div class=\"inserted-by-proxy\"><h3>Response from remote web server below.</h3></div><br/>"; "<div class=\"inserted-by-proxy\"><h3>Response from remote web server below.</h3></div><br/>";
......
...@@ -59,11 +59,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -59,11 +59,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
{ {
Assert.AreEqual("Test", session.UserData); Assert.AreEqual("Test", session.UserData);
return await Task.FromResult(new Models.ExternalProxy return await Task.FromResult(new Models.ExternalProxy("localhost", proxy2.ProxyEndPoints[0].Port));
{
HostName = "localhost",
Port = proxy2.ProxyEndPoints[0].Port
});
}; };
var client = testSuite.GetClient(proxy1, true); var client = testSuite.GetClient(proxy1, true);
......
...@@ -22,17 +22,8 @@ namespace Titanium.Web.Proxy.IntegrationTests.Setup ...@@ -22,17 +22,8 @@ namespace Titanium.Web.Proxy.IntegrationTests.Setup
if (upStreamProxy != null) if (upStreamProxy != null)
{ {
ProxyServer.UpStreamHttpProxy = new ExternalProxy ProxyServer.UpStreamHttpProxy = new ExternalProxy("localhost", upStreamProxy.ProxyEndPoints[0].Port);
{ ProxyServer.UpStreamHttpsProxy = new ExternalProxy("localhost", upStreamProxy.ProxyEndPoints[0].Port);
HostName = "localhost",
Port = upStreamProxy.ProxyEndPoints[0].Port
};
ProxyServer.UpStreamHttpsProxy = new ExternalProxy
{
HostName = "localhost",
Port = upStreamProxy.ProxyEndPoints[0].Port
};
} }
ProxyServer.Start(); ProxyServer.Start();
......
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
</PropertyGroup> </PropertyGroup>
...@@ -14,9 +14,7 @@ ...@@ -14,9 +14,7 @@
<ItemGroup> <ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" /> <FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.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.NET.Test.Sdk" Version="16.4.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.0.0" /> <PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" 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