Unverified Commit 3d443dd7 authored by justcoding121's avatar justcoding121 Committed by GitHub

Merge pull request #435 from justcoding121/master

Connection pool 
parents d3ad2f8b 4485303b
...@@ -23,7 +23,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -23,7 +23,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
public ProxyTestController() public ProxyTestController()
{ {
proxyServer = new ProxyServer(); proxyServer = new ProxyServer();
proxyServer.EnableConnectionPool = true;
// generate root certificate without storing it in file system // generate root certificate without storing it in file system
//proxyServer.CertificateManager.CreateRootCertificate(false); //proxyServer.CertificateManager.CreateRootCertificate(false);
......
...@@ -51,8 +51,8 @@ ...@@ -51,8 +51,8 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="StreamExtended, Version=1.0.164.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL"> <Reference Include="StreamExtended, Version=1.0.175.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL">
<HintPath>..\..\packages\StreamExtended.1.0.164\lib\net45\StreamExtended.dll</HintPath> <HintPath>..\..\packages\StreamExtended.1.0.175-beta\lib\net45\StreamExtended.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="StreamExtended" version="1.0.164" targetFramework="net45" /> <package id="StreamExtended" version="1.0.175-beta" targetFramework="net45" />
</packages> </packages>
\ No newline at end of file
...@@ -2,23 +2,25 @@ ...@@ -2,23 +2,25 @@
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Helpers; using StreamExtended;
using StreamExtended.Network; using StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
internal class LimitedStream : Stream internal class LimitedStream : Stream
{ {
private readonly IBufferPool bufferPool;
private readonly ICustomStreamReader baseStream; private readonly ICustomStreamReader baseStream;
private readonly bool isChunked; private readonly bool isChunked;
private long bytesRemaining; private long bytesRemaining;
private bool readChunkTrail; private bool readChunkTrail;
internal LimitedStream(ICustomStreamReader baseStream, bool isChunked, internal LimitedStream(ICustomStreamReader baseStream, IBufferPool bufferPool, bool isChunked,
long contentLength) long contentLength)
{ {
this.baseStream = baseStream; this.baseStream = baseStream;
this.bufferPool = bufferPool;
this.isChunked = isChunked; this.isChunked = isChunked;
bytesRemaining = isChunked bytesRemaining = isChunked
? 0 ? 0
...@@ -41,7 +43,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -41,7 +43,7 @@ namespace Titanium.Web.Proxy.EventArguments
set => throw new NotSupportedException(); set => throw new NotSupportedException();
} }
private void GetNextChunk() private void getNextChunk()
{ {
if (readChunkTrail) if (readChunkTrail)
{ {
...@@ -96,7 +98,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -96,7 +98,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
if (isChunked) if (isChunked)
{ {
GetNextChunk(); getNextChunk();
} }
else else
{ {
...@@ -125,7 +127,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -125,7 +127,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
if (bytesRemaining != -1) if (bytesRemaining != -1)
{ {
var buffer = BufferPool.GetBuffer(baseStream.BufferSize); var buffer = bufferPool.GetBuffer(baseStream.BufferSize);
try try
{ {
int res = await ReadAsync(buffer, 0, buffer.Length); int res = await ReadAsync(buffer, 0, buffer.Length);
...@@ -136,7 +138,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -136,7 +138,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
finally finally
{ {
BufferPool.ReturnBuffer(buffer); bufferPool.ReturnBuffer(buffer);
} }
} }
} }
......
using System; using System;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using StreamExtended;
using StreamExtended.Network; using StreamExtended.Network;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
...@@ -17,34 +18,33 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -17,34 +18,33 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public abstract class SessionEventArgsBase : EventArgs, IDisposable public abstract class SessionEventArgsBase : EventArgs, IDisposable
{ {
/// <summary>
/// Size of Buffers used by this object
/// </summary>
protected readonly int BufferSize;
internal readonly CancellationTokenSource CancellationTokenSource; internal readonly CancellationTokenSource CancellationTokenSource;
protected readonly ExceptionHandler ExceptionFunc; protected readonly int bufferSize;
protected readonly IBufferPool bufferPool;
protected readonly ExceptionHandler exceptionFunc;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class. /// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
/// </summary> /// </summary>
internal SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, internal SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
CancellationTokenSource cancellationTokenSource, ExceptionHandler exceptionFunc) CancellationTokenSource cancellationTokenSource)
: this(bufferSize, endPoint, cancellationTokenSource, null, exceptionFunc) : this(server, endPoint, cancellationTokenSource, null)
{ {
bufferSize = server.BufferSize;
bufferPool = server.BufferPool;
exceptionFunc = server.ExceptionFunc;
} }
protected SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
CancellationTokenSource cancellationTokenSource, CancellationTokenSource cancellationTokenSource,
Request request, ExceptionHandler exceptionFunc) Request request)
{ {
BufferSize = bufferSize;
ExceptionFunc = exceptionFunc;
CancellationTokenSource = cancellationTokenSource; CancellationTokenSource = cancellationTokenSource;
ProxyClient = new ProxyClient(); ProxyClient = new ProxyClient();
WebSession = new HttpWebClient(bufferSize, request); WebSession = new HttpWebClient(request);
LocalEndPoint = endPoint; LocalEndPoint = endPoint;
WebSession.ProcessId = new Lazy<int>(() => WebSession.ProcessId = new Lazy<int>(() =>
...@@ -151,7 +151,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -151,7 +151,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
catch (Exception ex) catch (Exception ex)
{ {
ExceptionFunc(new Exception("Exception thrown in user event", ex)); exceptionFunc(new Exception("Exception thrown in user event", ex));
} }
} }
...@@ -163,7 +163,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -163,7 +163,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
catch (Exception ex) catch (Exception ex)
{ {
ExceptionFunc(new Exception("Exception thrown in user event", ex)); exceptionFunc(new Exception("Exception thrown in user event", ex));
} }
} }
......
...@@ -12,9 +12,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -12,9 +12,9 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
private bool? isHttpsConnect; private bool? isHttpsConnect;
internal TunnelConnectSessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ConnectRequest connectRequest, internal TunnelConnectSessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, ConnectRequest connectRequest,
CancellationTokenSource cancellationTokenSource, ExceptionHandler exceptionFunc) CancellationTokenSource cancellationTokenSource)
: base(bufferSize, endPoint, cancellationTokenSource, connectRequest, exceptionFunc) : base(server, endPoint, cancellationTokenSource, connectRequest)
{ {
WebSession.ConnectRequest = connectRequest; WebSession.ConnectRequest = connectRequest;
} }
......
using System;
namespace Titanium.Web.Proxy.Exceptions
{
/// <summary>
/// The server connection was closed upon first read with the new connection from pool.
/// Should retry the request with a new connection.
/// </summary>
public class ServerConnectionException : ProxyException
{
internal ServerConnectionException(string message) : base(message)
{
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="message"></param>
/// <param name="e"></param>
internal ServerConnectionException(string message, Exception e) : base(message, e)
{
}
}
}
This diff is collapsed.
...@@ -13,11 +13,11 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -13,11 +13,11 @@ namespace Titanium.Web.Proxy.Extensions
foreach (var @delegate in invocationList) foreach (var @delegate in invocationList)
{ {
await InternalInvokeAsync((AsyncEventHandler<T>)@delegate, sender, args, exceptionFunc); await internalInvokeAsync((AsyncEventHandler<T>)@delegate, sender, args, exceptionFunc);
} }
} }
private static async Task InternalInvokeAsync<T>(AsyncEventHandler<T> callback, object sender, T args, private static async Task internalInvokeAsync<T>(AsyncEventHandler<T> callback, object sender, T args,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
try try
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Helpers; using StreamExtended;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
...@@ -19,9 +19,9 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -19,9 +19,9 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="onCopy"></param> /// <param name="onCopy"></param>
/// <param name="bufferSize"></param> /// <param name="bufferSize"></param>
internal static Task CopyToAsync(this Stream input, Stream output, Action<byte[], int, int> onCopy, internal static Task CopyToAsync(this Stream input, Stream output, Action<byte[], int, int> onCopy,
int bufferSize) IBufferPool bufferPool, int bufferSize)
{ {
return CopyToAsync(input, output, onCopy, bufferSize, CancellationToken.None); return CopyToAsync(input, output, onCopy, bufferPool, bufferSize, CancellationToken.None);
} }
/// <summary> /// <summary>
...@@ -33,9 +33,9 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -33,9 +33,9 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="bufferSize"></param> /// <param name="bufferSize"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
internal static async Task CopyToAsync(this Stream input, Stream output, Action<byte[], int, int> onCopy, internal static async Task CopyToAsync(this Stream input, Stream output, Action<byte[], int, int> onCopy,
int bufferSize, CancellationToken cancellationToken) IBufferPool bufferPool, int bufferSize, CancellationToken cancellationToken)
{ {
var buffer = BufferPool.GetBuffer(bufferSize); var buffer = bufferPool.GetBuffer(bufferSize);
try try
{ {
while (!cancellationToken.IsCancellationRequested) while (!cancellationToken.IsCancellationRequested)
...@@ -43,7 +43,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -43,7 +43,7 @@ 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.None)
.WithCancellation(cancellationToken); .withCancellation(cancellationToken);
int bytesRead; int bytesRead;
if ((bytesRead = num) != 0 && !cancellationToken.IsCancellationRequested) if ((bytesRead = num) != 0 && !cancellationToken.IsCancellationRequested)
{ {
...@@ -58,11 +58,11 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -58,11 +58,11 @@ namespace Titanium.Web.Proxy.Extensions
} }
finally finally
{ {
BufferPool.ReturnBuffer(buffer); bufferPool.ReturnBuffer(buffer);
} }
} }
private static async Task<T> WithCancellation<T>(this Task<T> task, CancellationToken cancellationToken) private static async Task<T> withCancellation<T>(this Task<T> task, CancellationToken cancellationToken)
{ {
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))
......
...@@ -122,7 +122,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -122,7 +122,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns> /// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns>
internal static Task<int> IsConnectMethod(ICustomStreamReader clientStreamReader) internal static Task<int> IsConnectMethod(ICustomStreamReader clientStreamReader)
{ {
return StartsWith(clientStreamReader, "CONNECT"); return startsWith(clientStreamReader, "CONNECT");
} }
/// <summary> /// <summary>
...@@ -132,7 +132,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -132,7 +132,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns>1: when PRI, 0: when valid HTTP method, -1: otherwise</returns> /// <returns>1: when PRI, 0: when valid HTTP method, -1: otherwise</returns>
internal static Task<int> IsPriMethod(ICustomStreamReader clientStreamReader) internal static Task<int> IsPriMethod(ICustomStreamReader clientStreamReader)
{ {
return StartsWith(clientStreamReader, "PRI"); return startsWith(clientStreamReader, "PRI");
} }
/// <summary> /// <summary>
...@@ -143,7 +143,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -143,7 +143,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns> /// <returns>
/// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise /// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise
/// </returns> /// </returns>
private static async Task<int> StartsWith(ICustomStreamReader clientStreamReader, string expectedStart) private static async Task<int> startsWith(ICustomStreamReader clientStreamReader, string expectedStart)
{ {
bool isExpected = true; bool isExpected = true;
int legthToCheck = 10; int legthToCheck = 10;
......
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
internal sealed class HttpRequestWriter : HttpWriter internal sealed class HttpRequestWriter : HttpWriter
{ {
internal HttpRequestWriter(Stream stream, int bufferSize) : base(stream, bufferSize) internal HttpRequestWriter(Stream stream, IBufferPool bufferPool, int bufferSize)
: base(stream, bufferPool, bufferSize)
{ {
} }
......
...@@ -2,13 +2,15 @@ ...@@ -2,13 +2,15 @@
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
internal sealed class HttpResponseWriter : HttpWriter internal sealed class HttpResponseWriter : HttpWriter
{ {
internal HttpResponseWriter(Stream stream, int bufferSize) : base(stream, bufferSize) internal HttpResponseWriter(Stream stream, IBufferPool bufferPool, int bufferSize)
: base(stream, bufferPool, bufferSize)
{ {
} }
......
...@@ -4,7 +4,7 @@ using System.IO; ...@@ -4,7 +4,7 @@ using System.IO;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Helpers; using StreamExtended;
using StreamExtended.Network; using StreamExtended.Network;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
...@@ -14,6 +14,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -14,6 +14,7 @@ namespace Titanium.Web.Proxy.Helpers
internal class HttpWriter : ICustomStreamWriter internal class HttpWriter : ICustomStreamWriter
{ {
private readonly Stream stream; private readonly Stream stream;
private readonly IBufferPool bufferPool;
private static readonly byte[] newLine = ProxyConstants.NewLine; private static readonly byte[] newLine = ProxyConstants.NewLine;
...@@ -21,10 +22,11 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -21,10 +22,11 @@ namespace Titanium.Web.Proxy.Helpers
private readonly char[] charBuffer; private readonly char[] charBuffer;
internal HttpWriter(Stream stream, int bufferSize) internal HttpWriter(Stream stream, IBufferPool bufferPool, int bufferSize)
{ {
BufferSize = bufferSize; BufferSize = bufferSize;
this.stream = stream; this.stream = stream;
this.bufferPool = bufferPool;
// ASCII encoder max byte count is char count + 1 // ASCII encoder max byte count is char count + 1
charBuffer = new char[BufferSize - 1]; charBuffer = new char[BufferSize - 1];
...@@ -44,10 +46,10 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -44,10 +46,10 @@ namespace Titanium.Web.Proxy.Helpers
internal Task WriteAsync(string value, CancellationToken cancellationToken = default) internal Task WriteAsync(string value, CancellationToken cancellationToken = default)
{ {
return WriteAsyncInternal(value, false, cancellationToken); return writeAsyncInternal(value, false, cancellationToken);
} }
private Task WriteAsyncInternal(string value, bool addNewLine, CancellationToken cancellationToken) private Task writeAsyncInternal(string value, bool addNewLine, CancellationToken cancellationToken)
{ {
int newLineChars = addNewLine ? newLine.Length : 0; int newLineChars = addNewLine ? newLine.Length : 0;
int charCount = value.Length; int charCount = value.Length;
...@@ -55,7 +57,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -55,7 +57,7 @@ namespace Titanium.Web.Proxy.Helpers
{ {
value.CopyTo(0, charBuffer, 0, charCount); value.CopyTo(0, charBuffer, 0, charCount);
var buffer = BufferPool.GetBuffer(BufferSize); var buffer = bufferPool.GetBuffer(BufferSize);
try try
{ {
int idx = encoder.GetBytes(charBuffer, 0, charCount, buffer, 0, true); int idx = encoder.GetBytes(charBuffer, 0, charCount, buffer, 0, true);
...@@ -69,7 +71,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -69,7 +71,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
finally finally
{ {
BufferPool.ReturnBuffer(buffer); bufferPool.ReturnBuffer(buffer);
} }
} }
else else
...@@ -91,7 +93,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -91,7 +93,7 @@ namespace Titanium.Web.Proxy.Helpers
internal Task WriteLineAsync(string value, CancellationToken cancellationToken = default) internal Task WriteLineAsync(string value, CancellationToken cancellationToken = default)
{ {
return WriteAsyncInternal(value, true, cancellationToken); return writeAsyncInternal(value, true, cancellationToken);
} }
/// <summary> /// <summary>
...@@ -104,12 +106,15 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -104,12 +106,15 @@ namespace Titanium.Web.Proxy.Helpers
internal async Task WriteHeadersAsync(HeaderCollection headers, bool flush = true, internal async Task WriteHeadersAsync(HeaderCollection headers, bool flush = true,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
var headerBuilder = new StringBuilder();
foreach (var header in headers) foreach (var header in headers)
{ {
await header.WriteToStreamAsync(this, cancellationToken); headerBuilder.AppendLine(header.ToString());
} }
headerBuilder.AppendLine();
await WriteAsync(headerBuilder.ToString(), cancellationToken);
await WriteLineAsync(cancellationToken);
if (flush) if (flush)
{ {
await stream.FlushAsync(cancellationToken); await stream.FlushAsync(cancellationToken);
...@@ -146,7 +151,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -146,7 +151,7 @@ namespace Titanium.Web.Proxy.Helpers
{ {
if (isChunked) if (isChunked)
{ {
return WriteBodyChunkedAsync(data, cancellationToken); return writeBodyChunkedAsync(data, cancellationToken);
} }
return WriteAsync(data, cancellationToken: cancellationToken); return WriteAsync(data, cancellationToken: cancellationToken);
...@@ -168,7 +173,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -168,7 +173,7 @@ namespace Titanium.Web.Proxy.Helpers
// For chunked request we need to read data as they arrive, until we reach a chunk end symbol // For chunked request we need to read data as they arrive, until we reach a chunk end symbol
if (isChunked) if (isChunked)
{ {
return CopyBodyChunkedAsync(streamReader, onCopy, cancellationToken); return copyBodyChunkedAsync(streamReader, onCopy, cancellationToken);
} }
// http 1.0 or the stream reader limits the stream // http 1.0 or the stream reader limits the stream
...@@ -178,7 +183,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -178,7 +183,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
// If not chunked then its easy just read the amount of bytes mentioned in content length header // If not chunked then its easy just read the amount of bytes mentioned in content length header
return CopyBytesFromStream(streamReader, contentLength, onCopy, cancellationToken); return copyBytesFromStream(streamReader, contentLength, onCopy, cancellationToken);
} }
/// <summary> /// <summary>
...@@ -187,7 +192,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -187,7 +192,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
private async Task WriteBodyChunkedAsync(byte[] data, CancellationToken cancellationToken) private async Task writeBodyChunkedAsync(byte[] data, CancellationToken cancellationToken)
{ {
var chunkHead = Encoding.ASCII.GetBytes(data.Length.ToString("x2")); var chunkHead = Encoding.ASCII.GetBytes(data.Length.ToString("x2"));
...@@ -207,7 +212,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -207,7 +212,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="onCopy"></param> /// <param name="onCopy"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
private async Task CopyBodyChunkedAsync(ICustomStreamReader reader, Action<byte[], int, int> onCopy, private async Task copyBodyChunkedAsync(ICustomStreamReader reader, Action<byte[], int, int> onCopy,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
while (true) while (true)
...@@ -225,7 +230,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -225,7 +230,7 @@ namespace Titanium.Web.Proxy.Helpers
if (chunkSize != 0) if (chunkSize != 0)
{ {
await CopyBytesFromStream(reader, chunkSize, onCopy, cancellationToken); await copyBytesFromStream(reader, chunkSize, onCopy, cancellationToken);
} }
await WriteLineAsync(cancellationToken); await WriteLineAsync(cancellationToken);
...@@ -248,10 +253,10 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -248,10 +253,10 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="onCopy"></param> /// <param name="onCopy"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
private async Task CopyBytesFromStream(ICustomStreamReader reader, long count, Action<byte[], int, int> onCopy, private async Task copyBytesFromStream(ICustomStreamReader reader, long count, Action<byte[], int, int> onCopy,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var buffer = BufferPool.GetBuffer(BufferSize); var buffer = bufferPool.GetBuffer(BufferSize);
try try
{ {
...@@ -280,7 +285,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -280,7 +285,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
finally finally
{ {
BufferPool.ReturnBuffer(buffer); bufferPool.ReturnBuffer(buffer);
} }
} }
......
...@@ -39,7 +39,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -39,7 +39,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
else else
{ {
overrides2.Add(BypassStringEscape(overrideHost)); overrides2.Add(bypassStringEscape(overrideHost));
} }
} }
...@@ -70,7 +70,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -70,7 +70,7 @@ namespace Titanium.Web.Proxy.Helpers
internal string[] BypassList { get; } internal string[] BypassList { get; }
private static string BypassStringEscape(string rawString) private static string bypassStringEscape(string rawString)
{ {
var match = var match =
new Regex("^(?<scheme>.*://)?(?<host>[^:]*)(?<port>:[0-9]{1,5})?$", new Regex("^(?<scheme>.*://)?(?<host>[^:]*)(?<port>:[0-9]{1,5})?$",
...@@ -91,9 +91,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -91,9 +91,9 @@ namespace Titanium.Web.Proxy.Helpers
empty2 = string.Empty; empty2 = string.Empty;
} }
string str1 = ConvertRegexReservedChars(empty1); string str1 = convertRegexReservedChars(empty1);
string str2 = ConvertRegexReservedChars(rawString1); string str2 = convertRegexReservedChars(rawString1);
string str3 = ConvertRegexReservedChars(empty2); string str3 = convertRegexReservedChars(empty2);
if (str1 == string.Empty) if (str1 == string.Empty)
{ {
str1 = "(?:.*://)?"; str1 = "(?:.*://)?";
...@@ -107,7 +107,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -107,7 +107,7 @@ namespace Titanium.Web.Proxy.Helpers
return "^" + str1 + str2 + str3 + "$"; return "^" + str1 + str2 + str3 + "$";
} }
private static string ConvertRegexReservedChars(string rawString) private static string convertRegexReservedChars(string rawString)
{ {
if (rawString.Length == 0) if (rawString.Length == 0)
{ {
...@@ -171,11 +171,11 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -171,11 +171,11 @@ namespace Titanium.Web.Proxy.Helpers
if (proxyValues.Length > 0) if (proxyValues.Length > 0)
{ {
result.AddRange(proxyValues.Select(ParseProxyValue).Where(parsedValue => parsedValue != null)); result.AddRange(proxyValues.Select(parseProxyValue).Where(parsedValue => parsedValue != null));
} }
else else
{ {
var parsedValue = ParseProxyValue(proxyServerValues); var parsedValue = parseProxyValue(proxyServerValues);
if (parsedValue != null) if (parsedValue != null)
{ {
result.Add(parsedValue); result.Add(parsedValue);
...@@ -190,7 +190,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -190,7 +190,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
private static HttpSystemProxyValue ParseProxyValue(string value) private static HttpSystemProxyValue parseProxyValue(string value)
{ {
string tmp = Regex.Replace(value, @"\s+", " ").Trim(); string tmp = Regex.Replace(value, @"\s+", " ").Trim();
......
...@@ -84,8 +84,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -84,8 +84,8 @@ namespace Titanium.Web.Proxy.Helpers
if (reg != null) if (reg != null)
{ {
SaveOriginalProxyConfiguration(reg); saveOriginalProxyConfiguration(reg);
PrepareRegistry(reg); prepareRegistry(reg);
string exisitingContent = reg.GetValue(regProxyServer) as string; string exisitingContent = reg.GetValue(regProxyServer) as string;
var existingSystemProxyValues = ProxyInfo.GetSystemProxyValues(exisitingContent); var existingSystemProxyValues = ProxyInfo.GetSystemProxyValues(exisitingContent);
...@@ -115,7 +115,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -115,7 +115,7 @@ namespace Titanium.Web.Proxy.Helpers
reg.SetValue(regProxyServer, reg.SetValue(regProxyServer,
string.Join(";", existingSystemProxyValues.Select(x => x.ToString()).ToArray())); string.Join(";", existingSystemProxyValues.Select(x => x.ToString()).ToArray()));
Refresh(); refresh();
} }
} }
...@@ -129,7 +129,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -129,7 +129,7 @@ namespace Titanium.Web.Proxy.Helpers
{ {
if (saveOriginalConfig) if (saveOriginalConfig)
{ {
SaveOriginalProxyConfiguration(reg); saveOriginalProxyConfiguration(reg);
} }
if (reg.GetValue(regProxyServer) != null) if (reg.GetValue(regProxyServer) != null)
...@@ -152,7 +152,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -152,7 +152,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
Refresh(); refresh();
} }
} }
...@@ -165,12 +165,12 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -165,12 +165,12 @@ namespace Titanium.Web.Proxy.Helpers
if (reg != null) if (reg != null)
{ {
SaveOriginalProxyConfiguration(reg); saveOriginalProxyConfiguration(reg);
reg.SetValue(regProxyEnable, 0); reg.SetValue(regProxyEnable, 0);
reg.SetValue(regProxyServer, string.Empty); reg.SetValue(regProxyServer, string.Empty);
Refresh(); refresh();
} }
} }
...@@ -180,9 +180,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -180,9 +180,9 @@ namespace Titanium.Web.Proxy.Helpers
if (reg != null) if (reg != null)
{ {
SaveOriginalProxyConfiguration(reg); saveOriginalProxyConfiguration(reg);
reg.SetValue(regAutoConfigUrl, url); reg.SetValue(regAutoConfigUrl, url);
Refresh(); refresh();
} }
} }
...@@ -192,9 +192,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -192,9 +192,9 @@ namespace Titanium.Web.Proxy.Helpers
if (reg != null) if (reg != null)
{ {
SaveOriginalProxyConfiguration(reg); saveOriginalProxyConfiguration(reg);
reg.SetValue(regProxyOverride, proxyOverride); reg.SetValue(regProxyOverride, proxyOverride);
Refresh(); refresh();
} }
} }
...@@ -247,7 +247,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -247,7 +247,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
originalValues = null; originalValues = null;
Refresh(); refresh();
} }
} }
...@@ -257,13 +257,13 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -257,13 +257,13 @@ namespace Titanium.Web.Proxy.Helpers
if (reg != null) if (reg != null)
{ {
return GetProxyInfoFromRegistry(reg); return getProxyInfoFromRegistry(reg);
} }
return null; return null;
} }
private ProxyInfo GetProxyInfoFromRegistry(RegistryKey reg) private ProxyInfo getProxyInfoFromRegistry(RegistryKey reg)
{ {
var pi = new ProxyInfo(null, reg.GetValue(regAutoConfigUrl) as string, reg.GetValue(regProxyEnable) as int?, var pi = new ProxyInfo(null, reg.GetValue(regAutoConfigUrl) as string, reg.GetValue(regProxyEnable) as int?,
reg.GetValue(regProxyServer) as string, reg.GetValue(regProxyServer) as string,
...@@ -272,21 +272,21 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -272,21 +272,21 @@ namespace Titanium.Web.Proxy.Helpers
return pi; return pi;
} }
private void SaveOriginalProxyConfiguration(RegistryKey reg) private void saveOriginalProxyConfiguration(RegistryKey reg)
{ {
if (originalValues != null) if (originalValues != null)
{ {
return; return;
} }
originalValues = GetProxyInfoFromRegistry(reg); originalValues = getProxyInfoFromRegistry(reg);
} }
/// <summary> /// <summary>
/// Prepares the proxy server registry (create empty values if they don't exist) /// Prepares the proxy server registry (create empty values if they don't exist)
/// </summary> /// </summary>
/// <param name="reg"></param> /// <param name="reg"></param>
private static void PrepareRegistry(RegistryKey reg) private static void prepareRegistry(RegistryKey reg)
{ {
if (reg.GetValue(regProxyEnable) == null) if (reg.GetValue(regProxyEnable) == null)
{ {
...@@ -302,7 +302,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -302,7 +302,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary> /// <summary>
/// Refresh the settings so that the system know about a change in proxy setting /// Refresh the settings so that the system know about a change in proxy setting
/// </summary> /// </summary>
private void Refresh() private static void refresh()
{ {
NativeMethods.InternetSetOption(IntPtr.Zero, InternetOptionSettingsChanged, IntPtr.Zero, 0); NativeMethods.InternetSetOption(IntPtr.Zero, InternetOptionSettingsChanged, IntPtr.Zero, 0);
NativeMethods.InternetSetOption(IntPtr.Zero, InternetOptionRefresh, IntPtr.Zero, 0); NativeMethods.InternetSetOption(IntPtr.Zero, InternetOptionRefresh, IntPtr.Zero, 0);
......
using System; using System;
using System.IO; using System.IO;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Helpers; using StreamExtended;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
...@@ -39,7 +37,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -39,7 +37,7 @@ namespace Titanium.Web.Proxy.Helpers
0) == 0) 0) == 0)
{ {
int rowCount = *(int*)tcpTable; int rowCount = *(int*)tcpTable;
uint portInNetworkByteOrder = ToNetworkByteOrder((uint)localPort); uint portInNetworkByteOrder = toNetworkByteOrder((uint)localPort);
if (ipVersion == IpVersion.Ipv4) if (ipVersion == IpVersion.Ipv4)
{ {
...@@ -90,7 +88,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -90,7 +88,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
/// <param name="port"></param> /// <param name="port"></param>
/// <returns></returns> /// <returns></returns>
private static uint ToNetworkByteOrder(uint port) private static uint toNetworkByteOrder(uint port)
{ {
return ((port >> 8) & 0x00FF00FFu) | ((port << 8) & 0xFF00FF00u); return ((port >> 8) & 0x00FF00FFu) | ((port << 8) & 0xFF00FF00u);
} }
...@@ -109,7 +107,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -109,7 +107,8 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="cancellationTokenSource"></param> /// <param name="cancellationTokenSource"></param>
/// <param name="exceptionFunc"></param> /// <param name="exceptionFunc"></param>
/// <returns></returns> /// <returns></returns>
internal static async Task SendRawApm(Stream clientStream, Stream serverStream, int bufferSize, internal static async Task SendRawApm(Stream clientStream, Stream serverStream,
IBufferPool bufferPool, int bufferSize,
Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive, Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive,
CancellationTokenSource cancellationTokenSource, CancellationTokenSource cancellationTokenSource,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
...@@ -118,23 +117,23 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -118,23 +117,23 @@ namespace Titanium.Web.Proxy.Helpers
cancellationTokenSource.Token.Register(() => taskCompletionSource.TrySetResult(true)); cancellationTokenSource.Token.Register(() => taskCompletionSource.TrySetResult(true));
// Now async relay all server=>client & client=>server data // Now async relay all server=>client & client=>server data
var clientBuffer = BufferPool.GetBuffer(bufferSize); var clientBuffer = bufferPool.GetBuffer(bufferSize);
var serverBuffer = BufferPool.GetBuffer(bufferSize); var serverBuffer = bufferPool.GetBuffer(bufferSize);
try try
{ {
BeginRead(clientStream, serverStream, clientBuffer, onDataSend, cancellationTokenSource, exceptionFunc); beginRead(clientStream, serverStream, clientBuffer, onDataSend, cancellationTokenSource, exceptionFunc);
BeginRead(serverStream, clientStream, serverBuffer, onDataReceive, cancellationTokenSource, beginRead(serverStream, clientStream, serverBuffer, onDataReceive, cancellationTokenSource,
exceptionFunc); exceptionFunc);
await taskCompletionSource.Task; await taskCompletionSource.Task;
} }
finally finally
{ {
BufferPool.ReturnBuffer(clientBuffer); bufferPool.ReturnBuffer(clientBuffer);
BufferPool.ReturnBuffer(serverBuffer); bufferPool.ReturnBuffer(serverBuffer);
} }
} }
private static void BeginRead(Stream inputStream, Stream outputStream, byte[] buffer, private static void beginRead(Stream inputStream, Stream outputStream, byte[] buffer,
Action<byte[], int, int> onCopy, CancellationTokenSource cancellationTokenSource, Action<byte[], int, int> onCopy, CancellationTokenSource cancellationTokenSource,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
...@@ -174,7 +173,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -174,7 +173,7 @@ namespace Titanium.Web.Proxy.Helpers
try try
{ {
outputStream.EndWrite(ar2); outputStream.EndWrite(ar2);
BeginRead(inputStream, outputStream, buffer, onCopy, cancellationTokenSource, beginRead(inputStream, outputStream, buffer, onCopy, cancellationTokenSource,
exceptionFunc); exceptionFunc);
} }
catch (IOException ex) catch (IOException ex)
...@@ -214,16 +213,17 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -214,16 +213,17 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="cancellationTokenSource"></param> /// <param name="cancellationTokenSource"></param>
/// <param name="exceptionFunc"></param> /// <param name="exceptionFunc"></param>
/// <returns></returns> /// <returns></returns>
private static async Task SendRawTap(Stream clientStream, Stream serverStream, int bufferSize, private static async Task sendRawTap(Stream clientStream, Stream serverStream,
IBufferPool bufferPool, int bufferSize,
Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive, Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive,
CancellationTokenSource cancellationTokenSource, CancellationTokenSource cancellationTokenSource,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
// Now async relay all server=>client & client=>server data // Now async relay all server=>client & client=>server data
var sendRelay = var sendRelay =
clientStream.CopyToAsync(serverStream, onDataSend, bufferSize, cancellationTokenSource.Token); clientStream.CopyToAsync(serverStream, onDataSend, bufferPool, bufferSize, cancellationTokenSource.Token);
var receiveRelay = var receiveRelay =
serverStream.CopyToAsync(clientStream, onDataReceive, bufferSize, cancellationTokenSource.Token); serverStream.CopyToAsync(clientStream, onDataReceive, bufferPool, bufferSize, cancellationTokenSource.Token);
await Task.WhenAny(sendRelay, receiveRelay); await Task.WhenAny(sendRelay, receiveRelay);
cancellationTokenSource.Cancel(); cancellationTokenSource.Cancel();
...@@ -244,13 +244,14 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -244,13 +244,14 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="cancellationTokenSource"></param> /// <param name="cancellationTokenSource"></param>
/// <param name="exceptionFunc"></param> /// <param name="exceptionFunc"></param>
/// <returns></returns> /// <returns></returns>
internal static Task SendRaw(Stream clientStream, Stream serverStream, int bufferSize, internal static Task SendRaw(Stream clientStream, Stream serverStream,
IBufferPool bufferPool, int bufferSize,
Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive, Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive,
CancellationTokenSource cancellationTokenSource, CancellationTokenSource cancellationTokenSource,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
// todo: fix APM mode // todo: fix APM mode
return SendRawTap(clientStream, serverStream, bufferSize, onDataSend, onDataReceive, return sendRawTap(clientStream, serverStream, bufferPool, bufferSize, onDataSend, onDataReceive,
cancellationTokenSource, cancellationTokenSource,
exceptionFunc); exceptionFunc);
} }
......
...@@ -19,7 +19,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -19,7 +19,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
session = NativeMethods.WinHttp.WinHttpOpen(null, NativeMethods.WinHttp.AccessType.NoProxy, null, null, 0); session = NativeMethods.WinHttp.WinHttpOpen(null, NativeMethods.WinHttp.AccessType.NoProxy, null, null, 0);
if (session == null || session.IsInvalid) if (session == null || session.IsInvalid)
{ {
int lastWin32Error = GetLastWin32Error(); int lastWin32Error = getLastWin32Error();
} }
else else
{ {
...@@ -30,7 +30,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -30,7 +30,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return; return;
} }
int lastWin32Error = GetLastWin32Error(); int lastWin32Error = getLastWin32Error();
} }
} }
...@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
public void Dispose() public void Dispose()
{ {
Dispose(true); dispose(true);
} }
public bool GetAutoProxies(Uri destination, out IList<string> proxyList) public bool GetAutoProxies(Uri destination, out IList<string> proxyList)
...@@ -65,8 +65,8 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -65,8 +65,8 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
var errorCode = NativeMethods.WinHttp.ErrorCodes.AudodetectionFailed; var errorCode = NativeMethods.WinHttp.ErrorCodes.AudodetectionFailed;
if (AutomaticallyDetectSettings && !autoDetectFailed) if (AutomaticallyDetectSettings && !autoDetectFailed)
{ {
errorCode = (NativeMethods.WinHttp.ErrorCodes)GetAutoProxies(destination, null, out proxyListString); errorCode = (NativeMethods.WinHttp.ErrorCodes)getAutoProxies(destination, null, out proxyListString);
autoDetectFailed = IsErrorFatalForAutoDetect(errorCode); autoDetectFailed = isErrorFatalForAutoDetect(errorCode);
if (errorCode == NativeMethods.WinHttp.ErrorCodes.UnrecognizedScheme) if (errorCode == NativeMethods.WinHttp.ErrorCodes.UnrecognizedScheme)
{ {
state = AutoWebProxyState.UnrecognizedScheme; state = AutoWebProxyState.UnrecognizedScheme;
...@@ -74,13 +74,13 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -74,13 +74,13 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
} }
} }
if (AutomaticConfigurationScript != null && IsRecoverableAutoProxyError(errorCode)) if (AutomaticConfigurationScript != null && isRecoverableAutoProxyError(errorCode))
{ {
errorCode = (NativeMethods.WinHttp.ErrorCodes)GetAutoProxies(destination, AutomaticConfigurationScript, errorCode = (NativeMethods.WinHttp.ErrorCodes)getAutoProxies(destination, AutomaticConfigurationScript,
out proxyListString); out proxyListString);
} }
state = GetStateFromErrorCode(errorCode); state = getStateFromErrorCode(errorCode);
if (state != AutoWebProxyState.Completed) if (state != AutoWebProxyState.Completed)
{ {
return false; return false;
...@@ -88,7 +88,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -88,7 +88,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
if (!string.IsNullOrEmpty(proxyListString)) if (!string.IsNullOrEmpty(proxyListString))
{ {
proxyListString = RemoveWhitespaces(proxyListString); proxyListString = removeWhitespaces(proxyListString);
proxyList = proxyListString.Split(';'); proxyList = proxyListString.Split(';');
} }
...@@ -149,7 +149,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -149,7 +149,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
public void LoadFromIE() public void LoadFromIE()
{ {
var pi = GetProxyInfo(); var pi = getProxyInfo();
ProxyInfo = pi; ProxyInfo = pi;
AutomaticallyDetectSettings = pi.AutoDetect == true; AutomaticallyDetectSettings = pi.AutoDetect == true;
AutomaticConfigurationScript = pi.AutoConfigUrl == null ? null : new Uri(pi.AutoConfigUrl); AutomaticConfigurationScript = pi.AutoConfigUrl == null ? null : new Uri(pi.AutoConfigUrl);
...@@ -158,7 +158,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -158,7 +158,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
proxy = new WebProxy(new Uri("http://localhost"), BypassOnLocal, pi.BypassList); proxy = new WebProxy(new Uri("http://localhost"), BypassOnLocal, pi.BypassList);
} }
private ProxyInfo GetProxyInfo() private ProxyInfo getProxyInfo()
{ {
var proxyConfig = new NativeMethods.WinHttp.WINHTTP_CURRENT_USER_IE_PROXY_CONFIG(); var proxyConfig = new NativeMethods.WinHttp.WINHTTP_CURRENT_USER_IE_PROXY_CONFIG();
RuntimeHelpers.PrepareConstrainedRegions(); RuntimeHelpers.PrepareConstrainedRegions();
...@@ -200,7 +200,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -200,7 +200,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
autoDetectFailed = false; autoDetectFailed = false;
} }
private void Dispose(bool disposing) private void dispose(bool disposing)
{ {
if (!disposing || session == null || session.IsInvalid) if (!disposing || session == null || session.IsInvalid)
{ {
...@@ -210,7 +210,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -210,7 +210,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
session.Close(); session.Close();
} }
private int GetAutoProxies(Uri destination, Uri scriptLocation, out string proxyListString) private int getAutoProxies(Uri destination, Uri scriptLocation, out string proxyListString)
{ {
int num = 0; int num = 0;
var autoProxyOptions = new NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS(); var autoProxyOptions = new NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS();
...@@ -229,16 +229,16 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -229,16 +229,16 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
autoProxyOptions.AutoDetectFlags = NativeMethods.WinHttp.AutoDetectType.None; autoProxyOptions.AutoDetectFlags = NativeMethods.WinHttp.AutoDetectType.None;
} }
if (!WinHttpGetProxyForUrl(destination.ToString(), ref autoProxyOptions, out proxyListString)) if (!winHttpGetProxyForUrl(destination.ToString(), ref autoProxyOptions, out proxyListString))
{ {
num = GetLastWin32Error(); num = getLastWin32Error();
if (num == (int)NativeMethods.WinHttp.ErrorCodes.LoginFailure && Credentials != null) if (num == (int)NativeMethods.WinHttp.ErrorCodes.LoginFailure && Credentials != null)
{ {
autoProxyOptions.AutoLogonIfChallenged = true; autoProxyOptions.AutoLogonIfChallenged = true;
if (!WinHttpGetProxyForUrl(destination.ToString(), ref autoProxyOptions, out proxyListString)) if (!winHttpGetProxyForUrl(destination.ToString(), ref autoProxyOptions, out proxyListString))
{ {
num = GetLastWin32Error(); num = getLastWin32Error();
} }
} }
} }
...@@ -246,7 +246,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -246,7 +246,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return num; return num;
} }
private bool WinHttpGetProxyForUrl(string destination, private bool winHttpGetProxyForUrl(string destination,
ref NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions, out string proxyListString) ref NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions, out string proxyListString)
{ {
proxyListString = null; proxyListString = null;
...@@ -271,7 +271,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -271,7 +271,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return flag; return flag;
} }
private static int GetLastWin32Error() private static int getLastWin32Error()
{ {
int lastWin32Error = Marshal.GetLastWin32Error(); int lastWin32Error = Marshal.GetLastWin32Error();
if (lastWin32Error == 8) if (lastWin32Error == 8)
...@@ -282,7 +282,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -282,7 +282,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return lastWin32Error; return lastWin32Error;
} }
private static bool IsRecoverableAutoProxyError(NativeMethods.WinHttp.ErrorCodes errorCode) private static bool isRecoverableAutoProxyError(NativeMethods.WinHttp.ErrorCodes errorCode)
{ {
switch (errorCode) switch (errorCode)
{ {
...@@ -300,7 +300,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -300,7 +300,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
} }
} }
private static AutoWebProxyState GetStateFromErrorCode(NativeMethods.WinHttp.ErrorCodes errorCode) private static AutoWebProxyState getStateFromErrorCode(NativeMethods.WinHttp.ErrorCodes errorCode)
{ {
if (errorCode == 0L) if (errorCode == 0L)
{ {
...@@ -324,7 +324,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -324,7 +324,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
} }
} }
private static string RemoveWhitespaces(string value) private static string removeWhitespaces(string value)
{ {
var stringBuilder = new StringBuilder(); var stringBuilder = new StringBuilder();
foreach (char c in value) foreach (char c in value)
...@@ -338,7 +338,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -338,7 +338,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return stringBuilder.ToString(); return stringBuilder.ToString();
} }
private static bool IsErrorFatalForAutoDetect(NativeMethods.WinHttp.ErrorCodes errorCode) private static bool isErrorFatalForAutoDetect(NativeMethods.WinHttp.ErrorCodes errorCode)
{ {
switch (errorCode) switch (errorCode)
{ {
......
...@@ -24,7 +24,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -24,7 +24,7 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
/// <param name="buffer"></param> /// <param name="buffer"></param>
/// <param name="size"></param> /// <param name="size"></param>
private static void ResizeBuffer(ref byte[] buffer, long size) private static void resizeBuffer(ref byte[] buffer, long size)
{ {
var newBuffer = new byte[size]; var newBuffer = new byte[size];
Buffer.BlockCopy(buffer, 0, newBuffer, 0, buffer.Length); Buffer.BlockCopy(buffer, 0, newBuffer, 0, buffer.Length);
......
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
...@@ -15,12 +16,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -15,12 +16,9 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public class HttpWebClient public class HttpWebClient
{ {
private readonly int bufferSize;
internal HttpWebClient(int bufferSize, Request request = null, Response response = null) internal HttpWebClient(Request request = null, Response response = null)
{ {
this.bufferSize = bufferSize;
Request = request ?? new Request(); Request = request ?? new Request();
Response = response ?? new Response(); Response = response ?? new Response();
} }
...@@ -98,16 +96,16 @@ namespace Titanium.Web.Proxy.Http ...@@ -98,16 +96,16 @@ namespace Titanium.Web.Proxy.Http
await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method, await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method,
useUpstreamProxy || isTransparent ? Request.OriginalUrl : Request.RequestUri.PathAndQuery, useUpstreamProxy || isTransparent ? Request.OriginalUrl : Request.RequestUri.PathAndQuery,
Request.HttpVersion), cancellationToken); Request.HttpVersion), cancellationToken);
var headerBuilder = new StringBuilder();
// Send Authentication to Upstream proxy if needed // Send Authentication to Upstream proxy if needed
if (!isTransparent && upstreamProxy != null if (!isTransparent && upstreamProxy != null
&& ServerConnection.IsHttps == false && ServerConnection.IsHttps == false
&& !string.IsNullOrEmpty(upstreamProxy.UserName) && !string.IsNullOrEmpty(upstreamProxy.UserName)
&& upstreamProxy.Password != null) && upstreamProxy.Password != null)
{ {
await HttpHeader.ProxyConnectionKeepAlive.WriteToStreamAsync(writer, cancellationToken); headerBuilder.AppendLine(HttpHeader.ProxyConnectionKeepAlive.ToString());
await HttpHeader.GetProxyAuthorizationHeader(upstreamProxy.UserName, upstreamProxy.Password) headerBuilder.AppendLine(HttpHeader.GetProxyAuthorizationHeader(upstreamProxy.UserName, upstreamProxy.Password).ToString());
.WriteToStreamAsync(writer, cancellationToken);
} }
// write request headers // write request headers
...@@ -115,17 +113,30 @@ namespace Titanium.Web.Proxy.Http ...@@ -115,17 +113,30 @@ namespace Titanium.Web.Proxy.Http
{ {
if (isTransparent || header.Name != KnownHeaders.ProxyAuthorization) if (isTransparent || header.Name != KnownHeaders.ProxyAuthorization)
{ {
await header.WriteToStreamAsync(writer, cancellationToken); headerBuilder.AppendLine(header.ToString());
} }
} }
await writer.WriteLineAsync(cancellationToken); headerBuilder.AppendLine();
await writer.WriteAsync(headerBuilder.ToString(), cancellationToken);
if (enable100ContinueBehaviour) if (enable100ContinueBehaviour)
{ {
if (Request.ExpectContinue) if (Request.ExpectContinue)
{ {
string httpStatus = await ServerConnection.Stream.ReadLineAsync(cancellationToken); string httpStatus;
try
{
httpStatus = await ServerConnection.Stream.ReadLineAsync(cancellationToken);
if (httpStatus == null)
{
throw new ServerConnectionException("Server connection was closed.");
}
}
catch (Exception e) when (!(e is ServerConnectionException))
{
throw new ServerConnectionException("Server connection was closed.");
}
Response.ParseResponseLine(httpStatus, out _, out int responseStatusCode, Response.ParseResponseLine(httpStatus, out _, out int responseStatusCode,
out string responseStatusDescription); out string responseStatusDescription);
...@@ -159,10 +170,18 @@ namespace Titanium.Web.Proxy.Http ...@@ -159,10 +170,18 @@ namespace Titanium.Web.Proxy.Http
return; return;
} }
string httpStatus = await ServerConnection.Stream.ReadLineAsync(cancellationToken); string httpStatus;
if (httpStatus == null) try
{ {
throw new IOException(); httpStatus = await ServerConnection.Stream.ReadLineAsync(cancellationToken);
if (httpStatus == null)
{
throw new ServerConnectionException("Server connection was closed.");
}
}
catch (Exception e) when (!(e is ServerConnectionException))
{
throw new ServerConnectionException("Server connection was closed.");
} }
if (httpStatus == string.Empty) if (httpStatus == string.Empty)
...@@ -217,6 +236,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -217,6 +236,9 @@ namespace Titanium.Web.Proxy.Http
ConnectRequest?.FinishSession(); ConnectRequest?.FinishSession();
Request?.FinishSession(); Request?.FinishSession();
Response?.FinishSession(); Response?.FinishSession();
Data.Clear();
UserData = null;
} }
} }
} }
...@@ -199,7 +199,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -199,7 +199,7 @@ namespace Titanium.Web.Proxy.Http
// Find the request Verb // Find the request Verb
httpMethod = httpCmdSplit[0]; httpMethod = httpCmdSplit[0];
if (!IsAllUpper(httpMethod)) if (!isAllUpper(httpMethod))
{ {
httpMethod = httpMethod.ToUpper(); httpMethod = httpMethod.ToUpper();
} }
...@@ -219,7 +219,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -219,7 +219,7 @@ namespace Titanium.Web.Proxy.Http
} }
} }
private static bool IsAllUpper(string input) private static bool isAllUpper(string input)
{ {
for (int i = 0; i < input.Length; i++) for (int i = 0; i < input.Length; i++)
{ {
......
...@@ -69,6 +69,15 @@ namespace Titanium.Web.Proxy.Models ...@@ -69,6 +69,15 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public int Port { get; set; } public int Port { get; set; }
/// <summary>
/// Get cache key for Tcp connection cahe.
/// </summary>
/// <returns></returns>
internal string GetCacheKey()
{
return $"{HostName}-{Port}" + (UseDefaultCredentials ? $"-{UserName}-{Password}" : string.Empty);
}
/// <summary> /// <summary>
/// returns data in Hostname:port format. /// returns data in Hostname:port format.
/// </summary> /// </summary>
...@@ -77,5 +86,6 @@ namespace Titanium.Web.Proxy.Models ...@@ -77,5 +86,6 @@ namespace Titanium.Web.Proxy.Models
{ {
return $"{HostName}:{Port}"; return $"{HostName}:{Port}";
} }
} }
} }
using System; using System;
using System.Text; using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Models namespace Titanium.Web.Proxy.Models
...@@ -63,12 +60,5 @@ namespace Titanium.Web.Proxy.Models ...@@ -63,12 +60,5 @@ namespace Titanium.Web.Proxy.Models
"Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{userName}:{password}"))); "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{userName}:{password}")));
return result; return result;
} }
internal async Task WriteToStreamAsync(HttpWriter writer, CancellationToken cancellationToken)
{
await writer.WriteAsync(Name, cancellationToken);
await writer.WriteAsync(": ", cancellationToken);
await writer.WriteLineAsync(Value, cancellationToken);
}
} }
} }
...@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <returns>X509Certificate2 instance.</returns> /// <returns>X509Certificate2 instance.</returns>
public X509Certificate2 MakeCertificate(string sSubjectCn, bool isRoot, X509Certificate2 signingCert = null) public X509Certificate2 MakeCertificate(string sSubjectCn, bool isRoot, X509Certificate2 signingCert = null)
{ {
return MakeCertificateInternal(sSubjectCn, isRoot, true, signingCert); return makeCertificateInternal(sSubjectCn, isRoot, true, signingCert);
} }
/// <summary> /// <summary>
...@@ -65,7 +65,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -65,7 +65,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <param name="hostName">The host name</param> /// <param name="hostName">The host name</param>
/// <returns>X509Certificate2 instance.</returns> /// <returns>X509Certificate2 instance.</returns>
/// <exception cref="PemException">Malformed sequence in RSA private key</exception> /// <exception cref="PemException">Malformed sequence in RSA private key</exception>
private static X509Certificate2 GenerateCertificate(string hostName, private static X509Certificate2 generateCertificate(string hostName,
string subjectName, string subjectName,
string issuerName, DateTime validFrom, string issuerName, DateTime validFrom,
DateTime validTo, int keyStrength = 2048, DateTime validTo, int keyStrength = 2048,
...@@ -145,7 +145,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -145,7 +145,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
var x509Certificate = new X509Certificate2(certificate.GetEncoded()); var x509Certificate = new X509Certificate2(certificate.GetEncoded());
x509Certificate.PrivateKey = DotNetUtilities.ToRSA(rsaparams); x509Certificate.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
#else #else
var x509Certificate = WithPrivateKey(certificate, rsaparams); var x509Certificate = withPrivateKey(certificate, rsaparams);
x509Certificate.FriendlyName = subjectName; x509Certificate.FriendlyName = subjectName;
#endif #endif
...@@ -164,7 +164,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -164,7 +164,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
return x509Certificate; return x509Certificate;
} }
private static X509Certificate2 WithPrivateKey(X509Certificate certificate, AsymmetricKeyParameter privateKey) private static X509Certificate2 withPrivateKey(X509Certificate certificate, AsymmetricKeyParameter privateKey)
{ {
const string password = "password"; const string password = "password";
var store = new Pkcs12Store(); var store = new Pkcs12Store();
...@@ -194,7 +194,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -194,7 +194,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// You must specify a Signing Certificate if and only if you are not creating a /// You must specify a Signing Certificate if and only if you are not creating a
/// root. /// root.
/// </exception> /// </exception>
private X509Certificate2 MakeCertificateInternal(bool isRoot, private X509Certificate2 makeCertificateInternal(bool isRoot,
string hostName, string subjectName, string hostName, string subjectName,
DateTime validFrom, DateTime validTo, X509Certificate2 signingCertificate) DateTime validFrom, DateTime validTo, X509Certificate2 signingCertificate)
{ {
...@@ -207,11 +207,11 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -207,11 +207,11 @@ namespace Titanium.Web.Proxy.Network.Certificate
if (isRoot) if (isRoot)
{ {
return GenerateCertificate(null, subjectName, subjectName, validFrom, validTo); return generateCertificate(null, subjectName, subjectName, validFrom, validTo);
} }
var kp = DotNetUtilities.GetKeyPair(signingCertificate.PrivateKey); var kp = DotNetUtilities.GetKeyPair(signingCertificate.PrivateKey);
return GenerateCertificate(hostName, subjectName, signingCertificate.Subject, validFrom, validTo, return generateCertificate(hostName, subjectName, signingCertificate.Subject, validFrom, validTo,
issuerPrivateKey: kp.Private); issuerPrivateKey: kp.Private);
} }
...@@ -224,7 +224,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -224,7 +224,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <param name="signingCert">The signing cert.</param> /// <param name="signingCert">The signing cert.</param>
/// <param name="cancellationToken">Task cancellation token</param> /// <param name="cancellationToken">Task cancellation token</param>
/// <returns>X509Certificate2.</returns> /// <returns>X509Certificate2.</returns>
private X509Certificate2 MakeCertificateInternal(string subject, bool isRoot, private X509Certificate2 makeCertificateInternal(string subject, bool isRoot,
bool switchToMtaIfNeeded, X509Certificate2 signingCert = null, bool switchToMtaIfNeeded, X509Certificate2 signingCert = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
...@@ -238,7 +238,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -238,7 +238,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
{ {
try try
{ {
certificate = MakeCertificateInternal(subject, isRoot, false, signingCert); certificate = makeCertificateInternal(subject, isRoot, false, signingCert);
} }
catch (Exception ex) catch (Exception ex)
{ {
...@@ -258,7 +258,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -258,7 +258,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
} }
#endif #endif
return MakeCertificateInternal(isRoot, subject, $"CN={subject}", return makeCertificateInternal(isRoot, subject, $"CN={subject}",
DateTime.UtcNow.AddDays(-certificateGraceDays), DateTime.UtcNow.AddDays(certificateValidDays), DateTime.UtcNow.AddDays(-certificateGraceDays), DateTime.UtcNow.AddDays(certificateValidDays),
isRoot ? null : signingCert); isRoot ? null : signingCert);
} }
......
...@@ -80,10 +80,10 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -80,10 +80,10 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <returns></returns> /// <returns></returns>
public X509Certificate2 MakeCertificate(string sSubjectCN, bool isRoot, X509Certificate2 signingCert = null) public X509Certificate2 MakeCertificate(string sSubjectCN, bool isRoot, X509Certificate2 signingCert = null)
{ {
return MakeCertificateInternal(sSubjectCN, isRoot, true, signingCert); return makeCertificateInternal(sSubjectCN, isRoot, true, signingCert);
} }
private X509Certificate2 MakeCertificate(bool isRoot, string subject, string fullSubject, private X509Certificate2 makeCertificate(bool isRoot, string subject, string fullSubject,
int privateKeyLength, string hashAlg, DateTime validFrom, DateTime validTo, int privateKeyLength, string hashAlg, DateTime validFrom, DateTime validTo,
X509Certificate2 signingCertificate) X509Certificate2 signingCertificate)
{ {
...@@ -274,13 +274,13 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -274,13 +274,13 @@ namespace Titanium.Web.Proxy.Network.Certificate
return new X509Certificate2(Convert.FromBase64String(empty), string.Empty, X509KeyStorageFlags.Exportable); return new X509Certificate2(Convert.FromBase64String(empty), string.Empty, X509KeyStorageFlags.Exportable);
} }
private X509Certificate2 MakeCertificateInternal(string sSubjectCN, bool isRoot, private X509Certificate2 makeCertificateInternal(string sSubjectCN, bool isRoot,
bool switchToMTAIfNeeded, X509Certificate2 signingCert = null, bool switchToMTAIfNeeded, X509Certificate2 signingCert = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
if (switchToMTAIfNeeded && Thread.CurrentThread.GetApartmentState() != ApartmentState.MTA) if (switchToMTAIfNeeded && Thread.CurrentThread.GetApartmentState() != ApartmentState.MTA)
{ {
return Task.Run(() => MakeCertificateInternal(sSubjectCN, isRoot, false, signingCert), return Task.Run(() => makeCertificateInternal(sSubjectCN, isRoot, false, signingCert),
cancellationToken).Result; cancellationToken).Result;
} }
...@@ -301,7 +301,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -301,7 +301,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
var graceTime = DateTime.Now.AddDays(graceDays); var graceTime = DateTime.Now.AddDays(graceDays);
var now = DateTime.Now; var now = DateTime.Now;
var certificate = MakeCertificate(isRoot, sSubjectCN, fullSubject, keyLength, hashAlgo, graceTime, var certificate = makeCertificate(isRoot, sSubjectCN, fullSubject, keyLength, hashAlgo, graceTime,
now.AddDays(validDays), isRoot ? null : signingCert); now.AddDays(validDays), isRoot ? null : signingCert);
return certificate; return certificate;
} }
......
...@@ -3,6 +3,7 @@ using System; ...@@ -3,6 +3,7 @@ using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using StreamExtended;
using StreamExtended.Network; using StreamExtended.Network;
namespace Titanium.Web.Proxy.Network namespace Titanium.Web.Proxy.Network
...@@ -17,7 +18,8 @@ namespace Titanium.Web.Proxy.Network ...@@ -17,7 +18,8 @@ namespace Titanium.Web.Proxy.Network
private readonly FileStream fileStreamSent; private readonly FileStream fileStreamSent;
public DebugCustomBufferedStream(Guid connectionId, string type, Stream baseStream, int bufferSize, bool leaveOpen = false) : base(baseStream, bufferSize, leaveOpen) public DebugCustomBufferedStream(Guid connectionId, string type, Stream baseStream, IBufferPool bufferPool, int bufferSize, bool leaveOpen = false)
: base(baseStream, bufferPool, bufferSize, leaveOpen)
{ {
Counter = Interlocked.Increment(ref counter); Counter = Interlocked.Increment(ref counter);
fileStreamSent = new FileStream(Path.Combine(basePath, $"{connectionId}_{type}_{Counter}_sent.dat"), FileMode.Create); fileStreamSent = new FileStream(Path.Combine(basePath, $"{connectionId}_{type}_{Counter}_sent.dat"), FileMode.Create);
......
using System; using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
...@@ -41,9 +40,8 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -41,9 +40,8 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
tcpClient.CloseSocket();
proxyServer.UpdateClientConnectionCount(false); proxyServer.UpdateClientConnectionCount(false);
tcpClient.CloseSocket();
} }
} }
} }
using System; using System;
using System.Net; using System.Net;
using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
using StreamExtended.Network; using StreamExtended.Network;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
...@@ -48,6 +47,11 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -48,6 +47,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
private readonly TcpClient tcpClient; private readonly TcpClient tcpClient;
/// <summary>
/// The TcpClient.
/// </summary>
internal TcpClient TcpClient => tcpClient;
/// <summary> /// <summary>
/// Used to write lines to server /// Used to write lines to server
/// </summary> /// </summary>
...@@ -63,16 +67,24 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -63,16 +67,24 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary> /// </summary>
internal DateTime LastAccess { get; set; } internal DateTime LastAccess { get; set; }
/// <summary>
/// The cache key used to uniquely identify this connection properties
/// </summary>
internal string CacheKey { get; set; }
/// <summary>
/// Is this connection authenticated via WinAuth
/// </summary>
internal bool IsWinAuthenticated { get; set; }
/// <summary> /// <summary>
/// Dispose. /// Dispose.
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
proxyServer.UpdateServerConnectionCount(false);
Stream?.Dispose(); Stream?.Dispose();
tcpClient.CloseSocket(); tcpClient.CloseSocket();
proxyServer.UpdateServerConnectionCount(false);
} }
} }
} }
...@@ -18,7 +18,7 @@ namespace Titanium.Web.Proxy ...@@ -18,7 +18,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="session">The session event arguments.</param> /// <param name="session">The session event arguments.</param>
/// <returns>True if authorized.</returns> /// <returns>True if authorized.</returns>
private async Task<bool> CheckAuthorization(SessionEventArgsBase session) private async Task<bool> checkAuthorization(SessionEventArgsBase session)
{ {
// If we are not authorizing clients return true // If we are not authorizing clients return true
if (AuthenticateUserFunc == null) if (AuthenticateUserFunc == null)
...@@ -33,7 +33,7 @@ namespace Titanium.Web.Proxy ...@@ -33,7 +33,7 @@ namespace Titanium.Web.Proxy
var header = httpHeaders.GetFirstHeader(KnownHeaders.ProxyAuthorization); var header = httpHeaders.GetFirstHeader(KnownHeaders.ProxyAuthorization);
if (header == null) if (header == null)
{ {
session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Required"); session.WebSession.Response = createAuthentication407Response("Proxy Authentication Required");
return false; return false;
} }
...@@ -42,7 +42,7 @@ namespace Titanium.Web.Proxy ...@@ -42,7 +42,7 @@ namespace Titanium.Web.Proxy
!headerValueParts[0].EqualsIgnoreCase(KnownHeaders.ProxyAuthorizationBasic)) !headerValueParts[0].EqualsIgnoreCase(KnownHeaders.ProxyAuthorizationBasic))
{ {
// Return not authorized // Return not authorized
session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Invalid"); session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false; return false;
} }
...@@ -51,7 +51,7 @@ namespace Titanium.Web.Proxy ...@@ -51,7 +51,7 @@ namespace Titanium.Web.Proxy
if (colonIndex == -1) if (colonIndex == -1)
{ {
// Return not authorized // Return not authorized
session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Invalid"); session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false; return false;
} }
...@@ -60,7 +60,7 @@ namespace Titanium.Web.Proxy ...@@ -60,7 +60,7 @@ namespace Titanium.Web.Proxy
bool authenticated = await AuthenticateUserFunc(username, password); bool authenticated = await AuthenticateUserFunc(username, password);
if (!authenticated) if (!authenticated)
{ {
session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Invalid"); session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
} }
return authenticated; return authenticated;
...@@ -71,7 +71,7 @@ namespace Titanium.Web.Proxy ...@@ -71,7 +71,7 @@ namespace Titanium.Web.Proxy
httpHeaders)); httpHeaders));
// Return not authorized // Return not authorized
session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Invalid"); session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false; return false;
} }
} }
...@@ -81,7 +81,7 @@ namespace Titanium.Web.Proxy ...@@ -81,7 +81,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="description">Response description.</param> /// <param name="description">Response description.</param>
/// <returns></returns> /// <returns></returns>
private Response CreateAuthentication407Response(string description) private Response createAuthentication407Response(string description)
{ {
var response = new Response var response = new Response
{ {
......
This diff is collapsed.
This diff is collapsed.
using System; using System.Net;
using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Network.WinAuth.Security; using Titanium.Web.Proxy.Network.WinAuth.Security;
...@@ -18,116 +16,111 @@ namespace Titanium.Web.Proxy ...@@ -18,116 +16,111 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="args">The session event arguments.</param> /// <param name="args">The session event arguments.</param>
/// <returns> The task.</returns> /// <returns> The task.</returns>
private async Task HandleHttpSessionResponse(SessionEventArgs args) private async Task handleHttpSessionResponse(SessionEventArgs args)
{ {
try
{
var cancellationToken = args.CancellationTokenSource.Token;
// read response & headers from server
await args.WebSession.ReceiveResponse(cancellationToken);
var response = args.WebSession.Response; var cancellationToken = args.CancellationTokenSource.Token;
args.ReRequest = false;
// check for windows authentication // read response & headers from server
if (isWindowsAuthenticationEnabledAndSupported) await args.WebSession.ReceiveResponse(cancellationToken);
{
if (response.StatusCode == (int)HttpStatusCode.Unauthorized)
{
await Handle401UnAuthorized(args);
}
else
{
WinAuthEndPoint.AuthenticatedResponse(args.WebSession.Data);
}
}
response.OriginalHasBody = response.HasBody; var response = args.WebSession.Response;
args.ReRequest = false;
// if user requested call back then do it // check for windows authentication
if (!response.Locked) if (isWindowsAuthenticationEnabledAndSupported)
{
if (response.StatusCode == (int)HttpStatusCode.Unauthorized)
{ {
await InvokeBeforeResponse(args); await handle401UnAuthorized(args);
} }
else
// it may changed in the user event
response = args.WebSession.Response;
var clientStreamWriter = args.ProxyClient.ClientStreamWriter;
if (response.TerminateResponse || response.Locked)
{ {
await clientStreamWriter.WriteResponseAsync(response, cancellationToken: cancellationToken); WinAuthEndPoint.AuthenticatedResponse(args.WebSession.Data);
if (!response.TerminateResponse)
{
// syphon out the response body from server before setting the new body
await args.SyphonOutBodyAsync(false, cancellationToken);
}
else
{
args.WebSession.ServerConnection.Dispose();
args.WebSession.ServerConnection = null;
}
return;
} }
}
// if user requested to send request again response.OriginalHasBody = response.HasBody;
// likely after making modifications from User Response Handler
if (args.ReRequest)
{
// clear current response
await args.ClearResponse(cancellationToken);
await HandleHttpSessionRequestInternal(args.WebSession.ServerConnection, args);
return;
}
response.Locked = true; // if user requested call back then do it
if (!response.Locked)
{
await invokeBeforeResponse(args);
}
// Write back to client 100-conitinue response if that's what server returned // it may changed in the user event
if (response.Is100Continue) response = args.WebSession.Response;
{
await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion,
(int)HttpStatusCode.Continue, "Continue", cancellationToken);
await clientStreamWriter.WriteLineAsync(cancellationToken);
}
else if (response.ExpectationFailed)
{
await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion,
(int)HttpStatusCode.ExpectationFailed, "Expectation Failed", cancellationToken);
await clientStreamWriter.WriteLineAsync(cancellationToken);
}
if (!args.IsTransparent) var clientStreamWriter = args.ProxyClient.ClientStreamWriter;
{
response.Headers.FixProxyHeaders(); if (response.TerminateResponse || response.Locked)
} {
await clientStreamWriter.WriteResponseAsync(response, cancellationToken: cancellationToken);
if (response.IsBodyRead) if (!response.TerminateResponse)
{ {
await clientStreamWriter.WriteResponseAsync(response, cancellationToken: cancellationToken); // syphon out the response body from server before setting the new body
await args.SyphonOutBodyAsync(false, cancellationToken);
} }
else else
{ {
// Write back response status to client await tcpConnectionFactory.Release(args.WebSession.ServerConnection, true);
await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, response.StatusCode, args.WebSession.ServerConnection = null;
response.StatusDescription, cancellationToken);
await clientStreamWriter.WriteHeadersAsync(response.Headers, cancellationToken: cancellationToken);
// Write body if exists
if (response.HasBody)
{
await args.CopyResponseBodyAsync(clientStreamWriter, TransformationMode.None,
cancellationToken);
}
} }
return;
}
// if user requested to send request again
// likely after making modifications from User Response Handler
if (args.ReRequest)
{
// clear current response
await args.ClearResponse(cancellationToken);
await handleHttpSessionRequestInternal(args.WebSession.ServerConnection, args);
return;
}
response.Locked = true;
// Write back to client 100-conitinue response if that's what server returned
if (response.Is100Continue)
{
await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion,
(int)HttpStatusCode.Continue, "Continue", cancellationToken);
await clientStreamWriter.WriteLineAsync(cancellationToken);
}
else if (response.ExpectationFailed)
{
await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion,
(int)HttpStatusCode.ExpectationFailed, "Expectation Failed", cancellationToken);
await clientStreamWriter.WriteLineAsync(cancellationToken);
} }
catch (Exception e) when (!(e is ProxyHttpException))
if (!args.IsTransparent)
{
response.Headers.FixProxyHeaders();
}
if (response.IsBodyRead)
{
await clientStreamWriter.WriteResponseAsync(response, cancellationToken: cancellationToken);
}
else
{ {
throw new ProxyHttpException("Error occured whilst handling session response", e, args); // Write back response status to client
await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, response.StatusCode,
response.StatusDescription, cancellationToken);
await clientStreamWriter.WriteHeadersAsync(response.Headers, cancellationToken: cancellationToken);
// Write body if exists
if (response.HasBody)
{
await args.CopyResponseBodyAsync(clientStreamWriter, TransformationMode.None,
cancellationToken);
}
} }
} }
/// <summary> /// <summary>
...@@ -135,7 +128,7 @@ namespace Titanium.Web.Proxy ...@@ -135,7 +128,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="args"></param> /// <param name="args"></param>
/// <returns></returns> /// <returns></returns>
private async Task InvokeBeforeResponse(SessionEventArgs args) private async Task invokeBeforeResponse(SessionEventArgs args)
{ {
if (BeforeResponse != null) if (BeforeResponse != null)
{ {
...@@ -148,7 +141,7 @@ namespace Titanium.Web.Proxy ...@@ -148,7 +141,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="args"></param> /// <param name="args"></param>
/// <returns></returns> /// <returns></returns>
private async Task InvokeAfterResponse(SessionEventArgs args) private async Task invokeAfterResponse(SessionEventArgs args)
{ {
if (AfterResponse != null) if (AfterResponse != null)
{ {
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Portable.BouncyCastle" Version="1.8.2" /> <PackageReference Include="Portable.BouncyCastle" Version="1.8.2" />
<PackageReference Include="StreamExtended" Version="1.0.164" /> <PackageReference Include="StreamExtended" Version="1.0.175-beta" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup Condition="'$(TargetFramework)' == 'net45'">
<Reference Include="System.Web" /> <Reference Include="System.Web" />
</ItemGroup> </ItemGroup>
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<copyright>Copyright &#x00A9; Titanium. All rights reserved.</copyright> <copyright>Copyright &#x00A9; Titanium. All rights reserved.</copyright>
<tags></tags> <tags></tags>
<dependencies> <dependencies>
<dependency id="StreamExtended" version="1.0.164" /> <dependency id="StreamExtended" version="1.0.175-beta" />
<dependency id="Portable.BouncyCastle" version="1.8.2" /> <dependency id="Portable.BouncyCastle" version="1.8.2" />
</dependencies> </dependencies>
</metadata> </metadata>
......
...@@ -6,7 +6,6 @@ using System.Security.Authentication; ...@@ -6,7 +6,6 @@ using System.Security.Authentication;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended; using StreamExtended;
using StreamExtended.Helpers;
using StreamExtended.Network; using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions; using Titanium.Web.Proxy.Exceptions;
...@@ -26,18 +25,21 @@ namespace Titanium.Web.Proxy ...@@ -26,18 +25,21 @@ namespace Titanium.Web.Proxy
/// <param name="endPoint">The transparent endpoint.</param> /// <param name="endPoint">The transparent endpoint.</param>
/// <param name="clientConnection">The client connection.</param> /// <param name="clientConnection">The client connection.</param>
/// <returns></returns> /// <returns></returns>
private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClientConnection clientConnection) private async Task handleClient(TransparentProxyEndPoint endPoint, TcpClientConnection clientConnection)
{ {
var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferSize); var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferPool, BufferSize);
var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);
var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); Task<TcpServerConnection> prefetchConnectionTask = null;
bool closeServerConnection = false;
bool calledRequestHandler = false;
try try
{ {
var clientHelloInfo = await SslTools.PeekClientHello(clientStream, cancellationToken); var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);
bool isHttps = clientHelloInfo != null; bool isHttps = clientHelloInfo != null;
string httpsHostName = null; string httpsHostName = null;
...@@ -60,8 +62,13 @@ namespace Titanium.Web.Proxy ...@@ -60,8 +62,13 @@ namespace Titanium.Web.Proxy
if (endPoint.DecryptSsl && args.DecryptSsl) if (endPoint.DecryptSsl && args.DecryptSsl)
{ {
prefetchConnectionTask = tcpConnectionFactory.GetClient(httpsHostName, endPoint.Port,
null, true, null,
false, this, UpStreamEndPoint, UpStreamHttpsProxy, cancellationToken);
SslStream sslStream = null; SslStream sslStream = null;
//do client authentication using fake certificate
try try
{ {
sslStream = new SslStream(clientStream); sslStream = new SslStream(clientStream);
...@@ -73,9 +80,9 @@ namespace Titanium.Web.Proxy ...@@ -73,9 +80,9 @@ 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 CustomBufferedStream(sslStream, BufferSize); clientStream = new CustomBufferedStream(sslStream, BufferPool, BufferSize);
clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -87,66 +94,77 @@ namespace Titanium.Web.Proxy ...@@ -87,66 +94,77 @@ namespace Titanium.Web.Proxy
else else
{ {
// create new connection // create new connection
var connection = new TcpClient(UpStreamEndPoint); var connection = await tcpConnectionFactory.GetClient(httpsHostName, endPoint.Port,
await connection.ConnectAsync(httpsHostName, endPoint.Port); null, false, null,
connection.ReceiveTimeout = ConnectionTimeOutSeconds * 1000; true, this, UpStreamEndPoint, UpStreamHttpsProxy, cancellationToken);
connection.SendTimeout = ConnectionTimeOutSeconds * 1000;
using (connection) var serverStream = connection.Stream;
int available = clientStream.Available;
if (available > 0)
{ {
var serverStream = connection.GetStream(); // send the buffered data
var data = BufferPool.GetBuffer(BufferSize);
int available = clientStream.Available; try
if (available > 0)
{ {
// send the buffered data // clientStream.Available sbould be at most BufferSize because it is using the same buffer size
var data = BufferPool.GetBuffer(BufferSize); await clientStream.ReadAsync(data, 0, available, cancellationToken);
await serverStream.WriteAsync(data, 0, available, cancellationToken);
try await serverStream.FlushAsync(cancellationToken);
{
// clientStream.Available sbould be at most BufferSize because it is using the same buffer size
await clientStream.ReadAsync(data, 0, available, cancellationToken);
await serverStream.WriteAsync(data, 0, available, cancellationToken);
await serverStream.FlushAsync(cancellationToken);
}
finally
{
BufferPool.ReturnBuffer(data);
}
} }
finally
{
BufferPool.ReturnBuffer(data);
}
}
////var serverHelloInfo = await SslTools.PeekServerHello(serverStream); await TcpHelper.SendRaw(clientStream, serverStream, BufferPool, BufferSize,
null, null, cancellationTokenSource, ExceptionFunc);
await tcpConnectionFactory.Release(connection, true);
return;
await TcpHelper.SendRaw(clientStream, serverStream, BufferSize,
null, null, cancellationTokenSource, ExceptionFunc);
}
} }
} }
calledRequestHandler = true;
// HTTPS server created - we can now decrypt the client's traffic // HTTPS server created - we can now decrypt the client's traffic
// Now create the request // Now create the request
await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
cancellationTokenSource, isHttps ? httpsHostName : null, null); cancellationTokenSource, isHttps ? httpsHostName : null, null, prefetchConnectionTask);
} }
catch (ProxyException e) catch (ProxyException e)
{ {
OnException(clientStream, e); closeServerConnection = true;
onException(clientStream, e);
} }
catch (IOException e) catch (IOException e)
{ {
OnException(clientStream, new Exception("Connection was aborted", e)); closeServerConnection = true;
onException(clientStream, new Exception("Connection was aborted", e));
} }
catch (SocketException e) catch (SocketException e)
{ {
OnException(clientStream, new Exception("Could not connect", e)); closeServerConnection = true;
onException(clientStream, new Exception("Could not connect", e));
} }
catch (Exception e) catch (Exception e)
{ {
OnException(clientStream, new Exception("Error occured in whilst handling the client", e)); closeServerConnection = true;
onException(clientStream, new Exception("Error occured in whilst handling the client", e));
} }
finally finally
{ {
if (!calledRequestHandler
&& prefetchConnectionTask != null)
{
var connection = await prefetchConnectionTask;
await tcpConnectionFactory.Release(connection, closeServerConnection);
}
clientStream.Dispose(); clientStream.Dispose();
if (!cancellationTokenSource.IsCancellationRequested) if (!cancellationTokenSource.IsCancellationRequested)
{ {
cancellationTokenSource.Cancel(); cancellationTokenSource.Cancel();
......
...@@ -45,7 +45,7 @@ namespace Titanium.Web.Proxy ...@@ -45,7 +45,7 @@ namespace Titanium.Web.Proxy
/// User to server to authenticate requests. /// User to server to authenticate requests.
/// To disable this set ProxyServer.EnableWinAuth to false. /// To disable this set ProxyServer.EnableWinAuth to false.
/// </summary> /// </summary>
internal async Task Handle401UnAuthorized(SessionEventArgs args) private async Task handle401UnAuthorized(SessionEventArgs args)
{ {
string headerName = null; string headerName = null;
HttpHeader authHeader = null; HttpHeader authHeader = null;
...@@ -99,7 +99,7 @@ namespace Titanium.Web.Proxy ...@@ -99,7 +99,7 @@ namespace Titanium.Web.Proxy
if (!WinAuthEndPoint.ValidateWinAuthState(args.WebSession.Data, expectedAuthState)) if (!WinAuthEndPoint.ValidateWinAuthState(args.WebSession.Data, expectedAuthState))
{ {
// Invalid state, create proper error message to client // Invalid state, create proper error message to client
await RewriteUnauthorizedResponse(args); await rewriteUnauthorizedResponse(args);
return; return;
} }
...@@ -145,6 +145,8 @@ namespace Titanium.Web.Proxy ...@@ -145,6 +145,8 @@ namespace Titanium.Web.Proxy
{ {
request.ContentLength = request.Body.Length; request.ContentLength = request.Body.Length;
} }
args.WebSession.ServerConnection.IsWinAuthenticated = true;
} }
// Need to revisit this. // Need to revisit this.
...@@ -161,7 +163,7 @@ namespace Titanium.Web.Proxy ...@@ -161,7 +163,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="args"></param> /// <param name="args"></param>
/// <returns></returns> /// <returns></returns>
internal async Task RewriteUnauthorizedResponse(SessionEventArgs args) private async Task rewriteUnauthorizedResponse(SessionEventArgs args)
{ {
var response = args.WebSession.Response; var response = args.WebSession.Response;
......
...@@ -2,5 +2,5 @@ ...@@ -2,5 +2,5 @@
<packages> <packages>
<package id="Portable.BouncyCastle" version="1.8.2" targetFramework="net45" /> <package id="Portable.BouncyCastle" version="1.8.2" targetFramework="net45" />
<package id="StreamExtended" version="1.0.164" targetFramework="net45" /> <package id="StreamExtended" version="1.0.175-beta" targetFramework="net45" />
</packages> </packages>
\ No newline at end of file
...@@ -103,10 +103,13 @@ or when server terminates connection from proxy.</p> ...@@ -103,10 +103,13 @@ or when server terminates connection from proxy.</p>
<div class="inheritedMembers"> <div class="inheritedMembers">
<h5>Inherited Members</h5> <h5>Inherited Members</h5>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize">SessionEventArgsBase.BufferSize</a> <a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferSize">SessionEventArgsBase.bufferSize</a>
</div> </div>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ExceptionFunc">SessionEventArgsBase.ExceptionFunc</a> <a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferPool">SessionEventArgsBase.bufferPool</a>
</div>
<div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_exceptionFunc">SessionEventArgsBase.exceptionFunc</a>
</div> </div>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData">SessionEventArgsBase.UserData</a> <a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData">SessionEventArgsBase.UserData</a>
...@@ -177,12 +180,12 @@ or when server terminates connection from proxy.</p> ...@@ -177,12 +180,12 @@ or when server terminates connection from proxy.</p>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs__ctor_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.#ctor*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs__ctor_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.#ctor*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs__ctor_System_Int32_Titanium_Web_Proxy_Models_ProxyEndPoint_Titanium_Web_Proxy_Http_Request_System_Threading_CancellationTokenSource_Titanium_Web_Proxy_ExceptionHandler_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.#ctor(System.Int32,Titanium.Web.Proxy.Models.ProxyEndPoint,Titanium.Web.Proxy.Http.Request,System.Threading.CancellationTokenSource,Titanium.Web.Proxy.ExceptionHandler)">SessionEventArgs(Int32, ProxyEndPoint, Request, CancellationTokenSource, ExceptionHandler)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs__ctor_Titanium_Web_Proxy_ProxyServer_Titanium_Web_Proxy_Models_ProxyEndPoint_Titanium_Web_Proxy_Http_Request_System_Threading_CancellationTokenSource_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.#ctor(Titanium.Web.Proxy.ProxyServer,Titanium.Web.Proxy.Models.ProxyEndPoint,Titanium.Web.Proxy.Http.Request,System.Threading.CancellationTokenSource)">SessionEventArgs(ProxyServer, ProxyEndPoint, Request, CancellationTokenSource)</h4>
<div class="markdown level1 summary"></div> <div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">protected SessionEventArgs(int bufferSize, ProxyEndPoint endPoint, Request request, CancellationTokenSource cancellationTokenSource, ExceptionHandler exceptionFunc)</code></pre> <pre><code class="lang-csharp hljs">protected SessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, Request request, CancellationTokenSource cancellationTokenSource)</code></pre>
</div> </div>
<h5 class="parameters">Parameters</h5> <h5 class="parameters">Parameters</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -195,8 +198,8 @@ or when server terminates connection from proxy.</p> ...@@ -195,8 +198,8 @@ or when server terminates connection from proxy.</p>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.int32">Int32</a></td> <td><a class="xref" href="Titanium.Web.Proxy.ProxyServer.html">ProxyServer</a></td>
<td><span class="parametername">bufferSize</span></td> <td><span class="parametername">server</span></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
...@@ -214,11 +217,6 @@ or when server terminates connection from proxy.</p> ...@@ -214,11 +217,6 @@ or when server terminates connection from proxy.</p>
<td><span class="parametername">cancellationTokenSource</span></td> <td><span class="parametername">cancellationTokenSource</span></td>
<td></td> <td></td>
</tr> </tr>
<tr>
<td><a class="xref" href="Titanium.Web.Proxy.ExceptionHandler.html">ExceptionHandler</a></td>
<td><span class="parametername">exceptionFunc</span></td>
<td></td>
</tr>
</tbody> </tbody>
</table> </table>
<h3 id="properties">Properties <h3 id="properties">Properties
......
...@@ -139,12 +139,12 @@ or when server terminates connection from proxy.</p> ...@@ -139,12 +139,12 @@ or when server terminates connection from proxy.</p>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase__ctor_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.#ctor*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase__ctor_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.#ctor*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase__ctor_System_Int32_Titanium_Web_Proxy_Models_ProxyEndPoint_System_Threading_CancellationTokenSource_Titanium_Web_Proxy_Http_Request_Titanium_Web_Proxy_ExceptionHandler_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.#ctor(System.Int32,Titanium.Web.Proxy.Models.ProxyEndPoint,System.Threading.CancellationTokenSource,Titanium.Web.Proxy.Http.Request,Titanium.Web.Proxy.ExceptionHandler)">SessionEventArgsBase(Int32, ProxyEndPoint, CancellationTokenSource, Request, ExceptionHandler)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase__ctor_Titanium_Web_Proxy_ProxyServer_Titanium_Web_Proxy_Models_ProxyEndPoint_System_Threading_CancellationTokenSource_Titanium_Web_Proxy_Http_Request_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.#ctor(Titanium.Web.Proxy.ProxyServer,Titanium.Web.Proxy.Models.ProxyEndPoint,System.Threading.CancellationTokenSource,Titanium.Web.Proxy.Http.Request)">SessionEventArgsBase(ProxyServer, ProxyEndPoint, CancellationTokenSource, Request)</h4>
<div class="markdown level1 summary"></div> <div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">protected SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, Request request, ExceptionHandler exceptionFunc)</code></pre> <pre><code class="lang-csharp hljs">protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, Request request)</code></pre>
</div> </div>
<h5 class="parameters">Parameters</h5> <h5 class="parameters">Parameters</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -157,8 +157,8 @@ or when server terminates connection from proxy.</p> ...@@ -157,8 +157,8 @@ or when server terminates connection from proxy.</p>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.int32">Int32</a></td> <td><a class="xref" href="Titanium.Web.Proxy.ProxyServer.html">ProxyServer</a></td>
<td><span class="parametername">bufferSize</span></td> <td><span class="parametername">server</span></td>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
...@@ -176,24 +176,42 @@ or when server terminates connection from proxy.</p> ...@@ -176,24 +176,42 @@ or when server terminates connection from proxy.</p>
<td><span class="parametername">request</span></td> <td><span class="parametername">request</span></td>
<td></td> <td></td>
</tr> </tr>
</tbody>
</table>
<h3 id="fields">Fields
</h3>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferPool" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferPool">bufferPool</h4>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected readonly IBufferPool bufferPool</code></pre>
</div>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr> <tr>
<td><a class="xref" href="Titanium.Web.Proxy.ExceptionHandler.html">ExceptionHandler</a></td> <td><span class="xref">StreamExtended.IBufferPool</span></td>
<td><span class="parametername">exceptionFunc</span></td>
<td></td> <td></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<h3 id="fields">Fields
</h3>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferSize">BufferSize</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferSize" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferSize">bufferSize</h4>
<div class="markdown level1 summary"><p>Size of Buffers used by this object</p> <div class="markdown level1 summary"></div>
</div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">protected readonly int BufferSize</code></pre> <pre><code class="lang-csharp hljs">protected readonly int bufferSize</code></pre>
</div> </div>
<h5 class="fieldValue">Field Value</h5> <h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -212,12 +230,12 @@ or when server terminates connection from proxy.</p> ...@@ -212,12 +230,12 @@ or when server terminates connection from proxy.</p>
</table> </table>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ExceptionFunc" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc">ExceptionFunc</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_exceptionFunc" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.exceptionFunc">exceptionFunc</h4>
<div class="markdown level1 summary"></div> <div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">protected readonly ExceptionHandler ExceptionFunc</code></pre> <pre><code class="lang-csharp hljs">protected readonly ExceptionHandler exceptionFunc</code></pre>
</div> </div>
<h5 class="fieldValue">Field Value</h5> <h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
......
...@@ -100,10 +100,13 @@ ...@@ -100,10 +100,13 @@
<div class="inheritedMembers"> <div class="inheritedMembers">
<h5>Inherited Members</h5> <h5>Inherited Members</h5>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize">SessionEventArgsBase.BufferSize</a> <a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferSize">SessionEventArgsBase.bufferSize</a>
</div> </div>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ExceptionFunc">SessionEventArgsBase.ExceptionFunc</a> <a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferPool">SessionEventArgsBase.bufferPool</a>
</div>
<div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_exceptionFunc">SessionEventArgsBase.exceptionFunc</a>
</div> </div>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData">SessionEventArgsBase.UserData</a> <a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData">SessionEventArgsBase.UserData</a>
......
...@@ -258,6 +258,32 @@ Should return true for successful authentication.</p> ...@@ -258,6 +258,32 @@ Should return true for successful authentication.</p>
</table> </table>
<a id="Titanium_Web_Proxy_ProxyServer_BufferPool_" data-uid="Titanium.Web.Proxy.ProxyServer.BufferPool*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_BufferPool" data-uid="Titanium.Web.Proxy.ProxyServer.BufferPool">BufferPool</h4>
<div class="markdown level1 summary"><p>The buffer pool used throughout this proxy instance.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public IBufferPool BufferPool { get; set; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><span class="xref">StreamExtended.IBufferPool</span></td>
<td></td>
</tr>
</tbody>
</table>
<a id="Titanium_Web_Proxy_ProxyServer_BufferSize_" data-uid="Titanium.Web.Proxy.ProxyServer.BufferSize*"></a> <a id="Titanium_Web_Proxy_ProxyServer_BufferSize_" data-uid="Titanium.Web.Proxy.ProxyServer.BufferSize*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_BufferSize" data-uid="Titanium.Web.Proxy.ProxyServer.BufferSize">BufferSize</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_BufferSize" data-uid="Titanium.Web.Proxy.ProxyServer.BufferSize">BufferSize</h4>
<div class="markdown level1 summary"><p>Buffer size used throughout this proxy.</p> <div class="markdown level1 summary"><p>Buffer size used throughout this proxy.</p>
...@@ -417,6 +443,33 @@ Defaults to false.</p> ...@@ -417,6 +443,33 @@ Defaults to false.</p>
</table> </table>
<a id="Titanium_Web_Proxy_ProxyServer_EnableConnectionPool_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableConnectionPool*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_EnableConnectionPool" data-uid="Titanium.Web.Proxy.ProxyServer.EnableConnectionPool">EnableConnectionPool</h4>
<div class="markdown level1 summary"><p>Should we enable experimental Tcp server connection pool?
Defaults to false.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public bool EnableConnectionPool { get; set; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.boolean">Boolean</a></td>
<td></td>
</tr>
</tbody>
</table>
<a id="Titanium_Web_Proxy_ProxyServer_EnableWinAuth_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableWinAuth*"></a> <a id="Titanium_Web_Proxy_ProxyServer_EnableWinAuth_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableWinAuth*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_EnableWinAuth" data-uid="Titanium.Web.Proxy.ProxyServer.EnableWinAuth">EnableWinAuth</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_EnableWinAuth" data-uid="Titanium.Web.Proxy.ProxyServer.EnableWinAuth">EnableWinAuth</h4>
<div class="markdown level1 summary"><p>Enable disable Windows Authentication (NTLM/Kerberos). <div class="markdown level1 summary"><p>Enable disable Windows Authentication (NTLM/Kerberos).
...@@ -525,6 +578,34 @@ User should return the ExternalProxy object with valid credentials.</p> ...@@ -525,6 +578,34 @@ User should return the ExternalProxy object with valid credentials.</p>
</table> </table>
<a id="Titanium_Web_Proxy_ProxyServer_MaxCachedConnections_" data-uid="Titanium.Web.Proxy.ProxyServer.MaxCachedConnections*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_MaxCachedConnections" data-uid="Titanium.Web.Proxy.ProxyServer.MaxCachedConnections">MaxCachedConnections</h4>
<div class="markdown level1 summary"><p>Maximum number of concurrent connections per remote host in cache.
Only valid when connection pooling is enabled.
Default value is 3.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public int MaxCachedConnections { get; set; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.int32">Int32</a></td>
<td></td>
</tr>
</tbody>
</table>
<a id="Titanium_Web_Proxy_ProxyServer_ProxyEndPoints_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyEndPoints*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ProxyEndPoints_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyEndPoints*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxyEndPoints" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyEndPoints">ProxyEndPoints</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ProxyEndPoints" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyEndPoints">ProxyEndPoints</h4>
<div class="markdown level1 summary"><p>A list of IpAddress and port this proxy is listening to.</p> <div class="markdown level1 summary"><p>A list of IpAddress and port this proxy is listening to.</p>
...@@ -1109,6 +1190,56 @@ Will throw error if the end point does&apos;nt exist.</p> ...@@ -1109,6 +1190,56 @@ Will throw error if the end point does&apos;nt exist.</p>
</table> </table>
<h4 id="Titanium_Web_Proxy_ProxyServer_OnClientConnectionCreate" data-uid="Titanium.Web.Proxy.ProxyServer.OnClientConnectionCreate">OnClientConnectionCreate</h4>
<div class="markdown level1 summary"><p>Customize TcpClient used for client connection upon create.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public event AsyncEventHandler&lt;TcpClient&gt; OnClientConnectionCreate</code></pre>
</div>
<h5 class="eventType">Event Type</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="Titanium.Web.Proxy.EventArguments.AsyncEventHandler-1.html">AsyncEventHandler</a>&lt;<span class="xref">System.Net.Sockets.TcpClient</span>&gt;</td>
<td></td>
</tr>
</tbody>
</table>
<h4 id="Titanium_Web_Proxy_ProxyServer_OnServerConnectionCreate" data-uid="Titanium.Web.Proxy.ProxyServer.OnServerConnectionCreate">OnServerConnectionCreate</h4>
<div class="markdown level1 summary"><p>Customize TcpClient used for server connection upon create.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public event AsyncEventHandler&lt;TcpClient&gt; OnServerConnectionCreate</code></pre>
</div>
<h5 class="eventType">Event Type</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="Titanium.Web.Proxy.EventArguments.AsyncEventHandler-1.html">AsyncEventHandler</a>&lt;<span class="xref">System.Net.Sockets.TcpClient</span>&gt;</td>
<td></td>
</tr>
</tbody>
</table>
<h4 id="Titanium_Web_Proxy_ProxyServer_ServerCertificateValidationCallback" data-uid="Titanium.Web.Proxy.ProxyServer.ServerCertificateValidationCallback">ServerCertificateValidationCallback</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ServerCertificateValidationCallback" data-uid="Titanium.Web.Proxy.ProxyServer.ServerCertificateValidationCallback">ServerCertificateValidationCallback</h4>
<div class="markdown level1 summary"><p>Event to override the default verification logic of remote SSL certificate received during authentication.</p> <div class="markdown level1 summary"><p>Event to override the default verification logic of remote SSL certificate received during authentication.</p>
</div> </div>
......
This diff is collapsed.
This diff is collapsed.
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