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
public ProxyTestController()
{
proxyServer = new ProxyServer();
proxyServer.EnableConnectionPool = true;
// generate root certificate without storing it in file system
//proxyServer.CertificateManager.CreateRootCertificate(false);
......
......@@ -51,8 +51,8 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="StreamExtended, Version=1.0.164.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL">
<HintPath>..\..\packages\StreamExtended.1.0.164\lib\net45\StreamExtended.dll</HintPath>
<Reference Include="StreamExtended, Version=1.0.175.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL">
<HintPath>..\..\packages\StreamExtended.1.0.175-beta\lib\net45\StreamExtended.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
......
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="StreamExtended" version="1.0.164" targetFramework="net45" />
<package id="StreamExtended" version="1.0.175-beta" targetFramework="net45" />
</packages>
\ No newline at end of file
......@@ -2,23 +2,25 @@
using System.Globalization;
using System.IO;
using System.Threading.Tasks;
using StreamExtended.Helpers;
using StreamExtended;
using StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments
{
internal class LimitedStream : Stream
{
private readonly IBufferPool bufferPool;
private readonly ICustomStreamReader baseStream;
private readonly bool isChunked;
private long bytesRemaining;
private bool readChunkTrail;
internal LimitedStream(ICustomStreamReader baseStream, bool isChunked,
internal LimitedStream(ICustomStreamReader baseStream, IBufferPool bufferPool, bool isChunked,
long contentLength)
{
{
this.baseStream = baseStream;
this.bufferPool = bufferPool;
this.isChunked = isChunked;
bytesRemaining = isChunked
? 0
......@@ -41,7 +43,7 @@ namespace Titanium.Web.Proxy.EventArguments
set => throw new NotSupportedException();
}
private void GetNextChunk()
private void getNextChunk()
{
if (readChunkTrail)
{
......@@ -96,7 +98,7 @@ namespace Titanium.Web.Proxy.EventArguments
{
if (isChunked)
{
GetNextChunk();
getNextChunk();
}
else
{
......@@ -125,7 +127,7 @@ namespace Titanium.Web.Proxy.EventArguments
{
if (bytesRemaining != -1)
{
var buffer = BufferPool.GetBuffer(baseStream.BufferSize);
var buffer = bufferPool.GetBuffer(baseStream.BufferSize);
try
{
int res = await ReadAsync(buffer, 0, buffer.Length);
......@@ -136,7 +138,7 @@ namespace Titanium.Web.Proxy.EventArguments
}
finally
{
BufferPool.ReturnBuffer(buffer);
bufferPool.ReturnBuffer(buffer);
}
}
}
......
using System;
using System.Net;
using System.Threading;
using StreamExtended;
using StreamExtended.Network;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
......@@ -17,34 +18,33 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public abstract class SessionEventArgsBase : EventArgs, IDisposable
{
/// <summary>
/// Size of Buffers used by this object
/// </summary>
protected readonly int BufferSize;
internal readonly CancellationTokenSource CancellationTokenSource;
protected readonly ExceptionHandler ExceptionFunc;
protected readonly int bufferSize;
protected readonly IBufferPool bufferPool;
protected readonly ExceptionHandler exceptionFunc;
/// <summary>
/// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
/// </summary>
internal SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint,
CancellationTokenSource cancellationTokenSource, ExceptionHandler exceptionFunc)
: this(bufferSize, endPoint, cancellationTokenSource, null, exceptionFunc)
internal SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
CancellationTokenSource cancellationTokenSource)
: 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,
Request request, ExceptionHandler exceptionFunc)
Request request)
{
BufferSize = bufferSize;
ExceptionFunc = exceptionFunc;
CancellationTokenSource = cancellationTokenSource;
ProxyClient = new ProxyClient();
WebSession = new HttpWebClient(bufferSize, request);
WebSession = new HttpWebClient(request);
LocalEndPoint = endPoint;
WebSession.ProcessId = new Lazy<int>(() =>
......@@ -151,7 +151,7 @@ namespace Titanium.Web.Proxy.EventArguments
}
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
}
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
{
private bool? isHttpsConnect;
internal TunnelConnectSessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ConnectRequest connectRequest,
CancellationTokenSource cancellationTokenSource, ExceptionHandler exceptionFunc)
: base(bufferSize, endPoint, cancellationTokenSource, connectRequest, exceptionFunc)
internal TunnelConnectSessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, ConnectRequest connectRequest,
CancellationTokenSource cancellationTokenSource)
: base(server, endPoint, cancellationTokenSource, 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
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)
{
try
......
......@@ -2,7 +2,7 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended.Helpers;
using StreamExtended;
namespace Titanium.Web.Proxy.Extensions
{
......@@ -19,9 +19,9 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="onCopy"></param>
/// <param name="bufferSize"></param>
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>
......@@ -33,9 +33,9 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="bufferSize"></param>
/// <param name="cancellationToken"></param>
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
{
while (!cancellationToken.IsCancellationRequested)
......@@ -43,7 +43,7 @@ namespace Titanium.Web.Proxy.Extensions
// cancellation is not working on Socket ReadAsync
// https://github.com/dotnet/corefx/issues/15033
int num = await input.ReadAsync(buffer, 0, buffer.Length, CancellationToken.None)
.WithCancellation(cancellationToken);
.withCancellation(cancellationToken);
int bytesRead;
if ((bytesRead = num) != 0 && !cancellationToken.IsCancellationRequested)
{
......@@ -58,11 +58,11 @@ namespace Titanium.Web.Proxy.Extensions
}
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>();
using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
......
......@@ -122,7 +122,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns>
internal static Task<int> IsConnectMethod(ICustomStreamReader clientStreamReader)
{
return StartsWith(clientStreamReader, "CONNECT");
return startsWith(clientStreamReader, "CONNECT");
}
/// <summary>
......@@ -132,7 +132,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns>1: when PRI, 0: when valid HTTP method, -1: otherwise</returns>
internal static Task<int> IsPriMethod(ICustomStreamReader clientStreamReader)
{
return StartsWith(clientStreamReader, "PRI");
return startsWith(clientStreamReader, "PRI");
}
/// <summary>
......@@ -143,7 +143,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns>
/// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise
/// </returns>
private static async Task<int> StartsWith(ICustomStreamReader clientStreamReader, string expectedStart)
private static async Task<int> startsWith(ICustomStreamReader clientStreamReader, string expectedStart)
{
bool isExpected = true;
int legthToCheck = 10;
......
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Helpers
{
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 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Helpers
{
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;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended.Helpers;
using StreamExtended;
using StreamExtended.Network;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared;
......@@ -14,6 +14,7 @@ namespace Titanium.Web.Proxy.Helpers
internal class HttpWriter : ICustomStreamWriter
{
private readonly Stream stream;
private readonly IBufferPool bufferPool;
private static readonly byte[] newLine = ProxyConstants.NewLine;
......@@ -21,10 +22,11 @@ namespace Titanium.Web.Proxy.Helpers
private readonly char[] charBuffer;
internal HttpWriter(Stream stream, int bufferSize)
internal HttpWriter(Stream stream, IBufferPool bufferPool, int bufferSize)
{
BufferSize = bufferSize;
this.stream = stream;
this.bufferPool = bufferPool;
// ASCII encoder max byte count is char count + 1
charBuffer = new char[BufferSize - 1];
......@@ -44,10 +46,10 @@ namespace Titanium.Web.Proxy.Helpers
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 charCount = value.Length;
......@@ -55,7 +57,7 @@ namespace Titanium.Web.Proxy.Helpers
{
value.CopyTo(0, charBuffer, 0, charCount);
var buffer = BufferPool.GetBuffer(BufferSize);
var buffer = bufferPool.GetBuffer(BufferSize);
try
{
int idx = encoder.GetBytes(charBuffer, 0, charCount, buffer, 0, true);
......@@ -69,7 +71,7 @@ namespace Titanium.Web.Proxy.Helpers
}
finally
{
BufferPool.ReturnBuffer(buffer);
bufferPool.ReturnBuffer(buffer);
}
}
else
......@@ -91,7 +93,7 @@ namespace Titanium.Web.Proxy.Helpers
internal Task WriteLineAsync(string value, CancellationToken cancellationToken = default)
{
return WriteAsyncInternal(value, true, cancellationToken);
return writeAsyncInternal(value, true, cancellationToken);
}
/// <summary>
......@@ -104,12 +106,15 @@ namespace Titanium.Web.Proxy.Helpers
internal async Task WriteHeadersAsync(HeaderCollection headers, bool flush = true,
CancellationToken cancellationToken = default)
{
var headerBuilder = new StringBuilder();
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)
{
await stream.FlushAsync(cancellationToken);
......@@ -146,7 +151,7 @@ namespace Titanium.Web.Proxy.Helpers
{
if (isChunked)
{
return WriteBodyChunkedAsync(data, cancellationToken);
return writeBodyChunkedAsync(data, cancellationToken);
}
return WriteAsync(data, cancellationToken: cancellationToken);
......@@ -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
if (isChunked)
{
return CopyBodyChunkedAsync(streamReader, onCopy, cancellationToken);
return copyBodyChunkedAsync(streamReader, onCopy, cancellationToken);
}
// http 1.0 or the stream reader limits the stream
......@@ -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
return CopyBytesFromStream(streamReader, contentLength, onCopy, cancellationToken);
return copyBytesFromStream(streamReader, contentLength, onCopy, cancellationToken);
}
/// <summary>
......@@ -187,7 +192,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="data"></param>
/// <param name="cancellationToken"></param>
/// <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"));
......@@ -207,7 +212,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="onCopy"></param>
/// <param name="cancellationToken"></param>
/// <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)
{
while (true)
......@@ -225,7 +230,7 @@ namespace Titanium.Web.Proxy.Helpers
if (chunkSize != 0)
{
await CopyBytesFromStream(reader, chunkSize, onCopy, cancellationToken);
await copyBytesFromStream(reader, chunkSize, onCopy, cancellationToken);
}
await WriteLineAsync(cancellationToken);
......@@ -248,10 +253,10 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="onCopy"></param>
/// <param name="cancellationToken"></param>
/// <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)
{
var buffer = BufferPool.GetBuffer(BufferSize);
var buffer = bufferPool.GetBuffer(BufferSize);
try
{
......@@ -280,7 +285,7 @@ namespace Titanium.Web.Proxy.Helpers
}
finally
{
BufferPool.ReturnBuffer(buffer);
bufferPool.ReturnBuffer(buffer);
}
}
......
......@@ -39,7 +39,7 @@ namespace Titanium.Web.Proxy.Helpers
}
else
{
overrides2.Add(BypassStringEscape(overrideHost));
overrides2.Add(bypassStringEscape(overrideHost));
}
}
......@@ -70,7 +70,7 @@ namespace Titanium.Web.Proxy.Helpers
internal string[] BypassList { get; }
private static string BypassStringEscape(string rawString)
private static string bypassStringEscape(string rawString)
{
var match =
new Regex("^(?<scheme>.*://)?(?<host>[^:]*)(?<port>:[0-9]{1,5})?$",
......@@ -91,9 +91,9 @@ namespace Titanium.Web.Proxy.Helpers
empty2 = string.Empty;
}
string str1 = ConvertRegexReservedChars(empty1);
string str2 = ConvertRegexReservedChars(rawString1);
string str3 = ConvertRegexReservedChars(empty2);
string str1 = convertRegexReservedChars(empty1);
string str2 = convertRegexReservedChars(rawString1);
string str3 = convertRegexReservedChars(empty2);
if (str1 == string.Empty)
{
str1 = "(?:.*://)?";
......@@ -107,7 +107,7 @@ namespace Titanium.Web.Proxy.Helpers
return "^" + str1 + str2 + str3 + "$";
}
private static string ConvertRegexReservedChars(string rawString)
private static string convertRegexReservedChars(string rawString)
{
if (rawString.Length == 0)
{
......@@ -171,11 +171,11 @@ namespace Titanium.Web.Proxy.Helpers
if (proxyValues.Length > 0)
{
result.AddRange(proxyValues.Select(ParseProxyValue).Where(parsedValue => parsedValue != null));
result.AddRange(proxyValues.Select(parseProxyValue).Where(parsedValue => parsedValue != null));
}
else
{
var parsedValue = ParseProxyValue(proxyServerValues);
var parsedValue = parseProxyValue(proxyServerValues);
if (parsedValue != null)
{
result.Add(parsedValue);
......@@ -190,7 +190,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static HttpSystemProxyValue ParseProxyValue(string value)
private static HttpSystemProxyValue parseProxyValue(string value)
{
string tmp = Regex.Replace(value, @"\s+", " ").Trim();
......
......@@ -84,8 +84,8 @@ namespace Titanium.Web.Proxy.Helpers
if (reg != null)
{
SaveOriginalProxyConfiguration(reg);
PrepareRegistry(reg);
saveOriginalProxyConfiguration(reg);
prepareRegistry(reg);
string exisitingContent = reg.GetValue(regProxyServer) as string;
var existingSystemProxyValues = ProxyInfo.GetSystemProxyValues(exisitingContent);
......@@ -115,7 +115,7 @@ namespace Titanium.Web.Proxy.Helpers
reg.SetValue(regProxyServer,
string.Join(";", existingSystemProxyValues.Select(x => x.ToString()).ToArray()));
Refresh();
refresh();
}
}
......@@ -129,7 +129,7 @@ namespace Titanium.Web.Proxy.Helpers
{
if (saveOriginalConfig)
{
SaveOriginalProxyConfiguration(reg);
saveOriginalProxyConfiguration(reg);
}
if (reg.GetValue(regProxyServer) != null)
......@@ -152,7 +152,7 @@ namespace Titanium.Web.Proxy.Helpers
}
}
Refresh();
refresh();
}
}
......@@ -165,12 +165,12 @@ namespace Titanium.Web.Proxy.Helpers
if (reg != null)
{
SaveOriginalProxyConfiguration(reg);
saveOriginalProxyConfiguration(reg);
reg.SetValue(regProxyEnable, 0);
reg.SetValue(regProxyServer, string.Empty);
Refresh();
refresh();
}
}
......@@ -180,9 +180,9 @@ namespace Titanium.Web.Proxy.Helpers
if (reg != null)
{
SaveOriginalProxyConfiguration(reg);
saveOriginalProxyConfiguration(reg);
reg.SetValue(regAutoConfigUrl, url);
Refresh();
refresh();
}
}
......@@ -192,9 +192,9 @@ namespace Titanium.Web.Proxy.Helpers
if (reg != null)
{
SaveOriginalProxyConfiguration(reg);
saveOriginalProxyConfiguration(reg);
reg.SetValue(regProxyOverride, proxyOverride);
Refresh();
refresh();
}
}
......@@ -247,7 +247,7 @@ namespace Titanium.Web.Proxy.Helpers
}
originalValues = null;
Refresh();
refresh();
}
}
......@@ -257,13 +257,13 @@ namespace Titanium.Web.Proxy.Helpers
if (reg != null)
{
return GetProxyInfoFromRegistry(reg);
return getProxyInfoFromRegistry(reg);
}
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?,
reg.GetValue(regProxyServer) as string,
......@@ -272,21 +272,21 @@ namespace Titanium.Web.Proxy.Helpers
return pi;
}
private void SaveOriginalProxyConfiguration(RegistryKey reg)
private void saveOriginalProxyConfiguration(RegistryKey reg)
{
if (originalValues != null)
{
return;
}
originalValues = GetProxyInfoFromRegistry(reg);
originalValues = getProxyInfoFromRegistry(reg);
}
/// <summary>
/// Prepares the proxy server registry (create empty values if they don't exist)
/// </summary>
/// <param name="reg"></param>
private static void PrepareRegistry(RegistryKey reg)
private static void prepareRegistry(RegistryKey reg)
{
if (reg.GetValue(regProxyEnable) == null)
{
......@@ -302,7 +302,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary>
/// Refresh the settings so that the system know about a change in proxy setting
/// </summary>
private void Refresh()
private static void refresh()
{
NativeMethods.InternetSetOption(IntPtr.Zero, InternetOptionSettingsChanged, IntPtr.Zero, 0);
NativeMethods.InternetSetOption(IntPtr.Zero, InternetOptionRefresh, IntPtr.Zero, 0);
......
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended.Helpers;
using StreamExtended;
using Titanium.Web.Proxy.Extensions;
namespace Titanium.Web.Proxy.Helpers
......@@ -39,7 +37,7 @@ namespace Titanium.Web.Proxy.Helpers
0) == 0)
{
int rowCount = *(int*)tcpTable;
uint portInNetworkByteOrder = ToNetworkByteOrder((uint)localPort);
uint portInNetworkByteOrder = toNetworkByteOrder((uint)localPort);
if (ipVersion == IpVersion.Ipv4)
{
......@@ -90,7 +88,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
/// <param name="port"></param>
/// <returns></returns>
private static uint ToNetworkByteOrder(uint port)
private static uint toNetworkByteOrder(uint port)
{
return ((port >> 8) & 0x00FF00FFu) | ((port << 8) & 0xFF00FF00u);
}
......@@ -109,7 +107,8 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="cancellationTokenSource"></param>
/// <param name="exceptionFunc"></param>
/// <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,
CancellationTokenSource cancellationTokenSource,
ExceptionHandler exceptionFunc)
......@@ -118,23 +117,23 @@ namespace Titanium.Web.Proxy.Helpers
cancellationTokenSource.Token.Register(() => taskCompletionSource.TrySetResult(true));
// Now async relay all server=>client & client=>server data
var clientBuffer = BufferPool.GetBuffer(bufferSize);
var serverBuffer = BufferPool.GetBuffer(bufferSize);
var clientBuffer = bufferPool.GetBuffer(bufferSize);
var serverBuffer = bufferPool.GetBuffer(bufferSize);
try
{
BeginRead(clientStream, serverStream, clientBuffer, onDataSend, cancellationTokenSource, exceptionFunc);
BeginRead(serverStream, clientStream, serverBuffer, onDataReceive, cancellationTokenSource,
beginRead(clientStream, serverStream, clientBuffer, onDataSend, cancellationTokenSource, exceptionFunc);
beginRead(serverStream, clientStream, serverBuffer, onDataReceive, cancellationTokenSource,
exceptionFunc);
await taskCompletionSource.Task;
}
finally
{
BufferPool.ReturnBuffer(clientBuffer);
BufferPool.ReturnBuffer(serverBuffer);
bufferPool.ReturnBuffer(clientBuffer);
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,
ExceptionHandler exceptionFunc)
{
......@@ -174,7 +173,7 @@ namespace Titanium.Web.Proxy.Helpers
try
{
outputStream.EndWrite(ar2);
BeginRead(inputStream, outputStream, buffer, onCopy, cancellationTokenSource,
beginRead(inputStream, outputStream, buffer, onCopy, cancellationTokenSource,
exceptionFunc);
}
catch (IOException ex)
......@@ -214,16 +213,17 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="cancellationTokenSource"></param>
/// <param name="exceptionFunc"></param>
/// <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,
CancellationTokenSource cancellationTokenSource,
ExceptionHandler exceptionFunc)
{
// Now async relay all server=>client & client=>server data
var sendRelay =
clientStream.CopyToAsync(serverStream, onDataSend, bufferSize, cancellationTokenSource.Token);
clientStream.CopyToAsync(serverStream, onDataSend, bufferPool, bufferSize, cancellationTokenSource.Token);
var receiveRelay =
serverStream.CopyToAsync(clientStream, onDataReceive, bufferSize, cancellationTokenSource.Token);
serverStream.CopyToAsync(clientStream, onDataReceive, bufferPool, bufferSize, cancellationTokenSource.Token);
await Task.WhenAny(sendRelay, receiveRelay);
cancellationTokenSource.Cancel();
......@@ -244,13 +244,14 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="cancellationTokenSource"></param>
/// <param name="exceptionFunc"></param>
/// <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,
CancellationTokenSource cancellationTokenSource,
ExceptionHandler exceptionFunc)
{
// todo: fix APM mode
return SendRawTap(clientStream, serverStream, bufferSize, onDataSend, onDataReceive,
return sendRawTap(clientStream, serverStream, bufferPool, bufferSize, onDataSend, onDataReceive,
cancellationTokenSource,
exceptionFunc);
}
......
......@@ -19,7 +19,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
session = NativeMethods.WinHttp.WinHttpOpen(null, NativeMethods.WinHttp.AccessType.NoProxy, null, null, 0);
if (session == null || session.IsInvalid)
{
int lastWin32Error = GetLastWin32Error();
int lastWin32Error = getLastWin32Error();
}
else
{
......@@ -30,7 +30,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return;
}
int lastWin32Error = GetLastWin32Error();
int lastWin32Error = getLastWin32Error();
}
}
......@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
public void Dispose()
{
Dispose(true);
dispose(true);
}
public bool GetAutoProxies(Uri destination, out IList<string> proxyList)
......@@ -65,8 +65,8 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
var errorCode = NativeMethods.WinHttp.ErrorCodes.AudodetectionFailed;
if (AutomaticallyDetectSettings && !autoDetectFailed)
{
errorCode = (NativeMethods.WinHttp.ErrorCodes)GetAutoProxies(destination, null, out proxyListString);
autoDetectFailed = IsErrorFatalForAutoDetect(errorCode);
errorCode = (NativeMethods.WinHttp.ErrorCodes)getAutoProxies(destination, null, out proxyListString);
autoDetectFailed = isErrorFatalForAutoDetect(errorCode);
if (errorCode == NativeMethods.WinHttp.ErrorCodes.UnrecognizedScheme)
{
state = AutoWebProxyState.UnrecognizedScheme;
......@@ -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);
}
state = GetStateFromErrorCode(errorCode);
state = getStateFromErrorCode(errorCode);
if (state != AutoWebProxyState.Completed)
{
return false;
......@@ -88,7 +88,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
if (!string.IsNullOrEmpty(proxyListString))
{
proxyListString = RemoveWhitespaces(proxyListString);
proxyListString = removeWhitespaces(proxyListString);
proxyList = proxyListString.Split(';');
}
......@@ -149,7 +149,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
public void LoadFromIE()
{
var pi = GetProxyInfo();
var pi = getProxyInfo();
ProxyInfo = pi;
AutomaticallyDetectSettings = pi.AutoDetect == true;
AutomaticConfigurationScript = pi.AutoConfigUrl == null ? null : new Uri(pi.AutoConfigUrl);
......@@ -158,7 +158,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
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();
RuntimeHelpers.PrepareConstrainedRegions();
......@@ -200,7 +200,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
autoDetectFailed = false;
}
private void Dispose(bool disposing)
private void dispose(bool disposing)
{
if (!disposing || session == null || session.IsInvalid)
{
......@@ -210,7 +210,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
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;
var autoProxyOptions = new NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS();
......@@ -229,16 +229,16 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
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)
{
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
return num;
}
private bool WinHttpGetProxyForUrl(string destination,
private bool winHttpGetProxyForUrl(string destination,
ref NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions, out string proxyListString)
{
proxyListString = null;
......@@ -271,7 +271,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return flag;
}
private static int GetLastWin32Error()
private static int getLastWin32Error()
{
int lastWin32Error = Marshal.GetLastWin32Error();
if (lastWin32Error == 8)
......@@ -282,7 +282,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return lastWin32Error;
}
private static bool IsRecoverableAutoProxyError(NativeMethods.WinHttp.ErrorCodes errorCode)
private static bool isRecoverableAutoProxyError(NativeMethods.WinHttp.ErrorCodes errorCode)
{
switch (errorCode)
{
......@@ -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)
{
......@@ -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();
foreach (char c in value)
......@@ -338,7 +338,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return stringBuilder.ToString();
}
private static bool IsErrorFatalForAutoDetect(NativeMethods.WinHttp.ErrorCodes errorCode)
private static bool isErrorFatalForAutoDetect(NativeMethods.WinHttp.ErrorCodes errorCode)
{
switch (errorCode)
{
......
......@@ -24,7 +24,7 @@ namespace Titanium.Web.Proxy.Http
/// </summary>
/// <param name="buffer"></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];
Buffer.BlockCopy(buffer, 0, newBuffer, 0, buffer.Length);
......
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network.Tcp;
......@@ -15,12 +16,9 @@ namespace Titanium.Web.Proxy.Http
/// </summary>
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();
Response = response ?? new Response();
}
......@@ -98,16 +96,16 @@ namespace Titanium.Web.Proxy.Http
await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method,
useUpstreamProxy || isTransparent ? Request.OriginalUrl : Request.RequestUri.PathAndQuery,
Request.HttpVersion), cancellationToken);
var headerBuilder = new StringBuilder();
// Send Authentication to Upstream proxy if needed
if (!isTransparent && upstreamProxy != null
&& ServerConnection.IsHttps == false
&& !string.IsNullOrEmpty(upstreamProxy.UserName)
&& upstreamProxy.Password != null)
{
await HttpHeader.ProxyConnectionKeepAlive.WriteToStreamAsync(writer, cancellationToken);
await HttpHeader.GetProxyAuthorizationHeader(upstreamProxy.UserName, upstreamProxy.Password)
.WriteToStreamAsync(writer, cancellationToken);
headerBuilder.AppendLine(HttpHeader.ProxyConnectionKeepAlive.ToString());
headerBuilder.AppendLine(HttpHeader.GetProxyAuthorizationHeader(upstreamProxy.UserName, upstreamProxy.Password).ToString());
}
// write request headers
......@@ -115,17 +113,30 @@ namespace Titanium.Web.Proxy.Http
{
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 (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,
out string responseStatusDescription);
......@@ -159,10 +170,18 @@ namespace Titanium.Web.Proxy.Http
return;
}
string httpStatus = await ServerConnection.Stream.ReadLineAsync(cancellationToken);
if (httpStatus == null)
string httpStatus;
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)
......@@ -217,6 +236,9 @@ namespace Titanium.Web.Proxy.Http
ConnectRequest?.FinishSession();
Request?.FinishSession();
Response?.FinishSession();
Data.Clear();
UserData = null;
}
}
}
......@@ -199,7 +199,7 @@ namespace Titanium.Web.Proxy.Http
// Find the request Verb
httpMethod = httpCmdSplit[0];
if (!IsAllUpper(httpMethod))
if (!isAllUpper(httpMethod))
{
httpMethod = httpMethod.ToUpper();
}
......@@ -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++)
{
......
......@@ -69,6 +69,15 @@ namespace Titanium.Web.Proxy.Models
/// </summary>
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>
/// returns data in Hostname:port format.
/// </summary>
......@@ -77,5 +86,6 @@ namespace Titanium.Web.Proxy.Models
{
return $"{HostName}:{Port}";
}
}
}
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Models
......@@ -63,12 +60,5 @@ namespace Titanium.Web.Proxy.Models
"Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{userName}:{password}")));
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
/// <returns>X509Certificate2 instance.</returns>
public X509Certificate2 MakeCertificate(string sSubjectCn, bool isRoot, X509Certificate2 signingCert = null)
{
return MakeCertificateInternal(sSubjectCn, isRoot, true, signingCert);
return makeCertificateInternal(sSubjectCn, isRoot, true, signingCert);
}
/// <summary>
......@@ -65,7 +65,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <param name="hostName">The host name</param>
/// <returns>X509Certificate2 instance.</returns>
/// <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 issuerName, DateTime validFrom,
DateTime validTo, int keyStrength = 2048,
......@@ -145,7 +145,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
var x509Certificate = new X509Certificate2(certificate.GetEncoded());
x509Certificate.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
#else
var x509Certificate = WithPrivateKey(certificate, rsaparams);
var x509Certificate = withPrivateKey(certificate, rsaparams);
x509Certificate.FriendlyName = subjectName;
#endif
......@@ -164,7 +164,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
return x509Certificate;
}
private static X509Certificate2 WithPrivateKey(X509Certificate certificate, AsymmetricKeyParameter privateKey)
private static X509Certificate2 withPrivateKey(X509Certificate certificate, AsymmetricKeyParameter privateKey)
{
const string password = "password";
var store = new Pkcs12Store();
......@@ -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
/// root.
/// </exception>
private X509Certificate2 MakeCertificateInternal(bool isRoot,
private X509Certificate2 makeCertificateInternal(bool isRoot,
string hostName, string subjectName,
DateTime validFrom, DateTime validTo, X509Certificate2 signingCertificate)
{
......@@ -207,11 +207,11 @@ namespace Titanium.Web.Proxy.Network.Certificate
if (isRoot)
{
return GenerateCertificate(null, subjectName, subjectName, validFrom, validTo);
return generateCertificate(null, subjectName, subjectName, validFrom, validTo);
}
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);
}
......@@ -224,7 +224,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <param name="signingCert">The signing cert.</param>
/// <param name="cancellationToken">Task cancellation token</param>
/// <returns>X509Certificate2.</returns>
private X509Certificate2 MakeCertificateInternal(string subject, bool isRoot,
private X509Certificate2 makeCertificateInternal(string subject, bool isRoot,
bool switchToMtaIfNeeded, X509Certificate2 signingCert = null,
CancellationToken cancellationToken = default)
{
......@@ -238,7 +238,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
{
try
{
certificate = MakeCertificateInternal(subject, isRoot, false, signingCert);
certificate = makeCertificateInternal(subject, isRoot, false, signingCert);
}
catch (Exception ex)
{
......@@ -258,7 +258,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
}
#endif
return MakeCertificateInternal(isRoot, subject, $"CN={subject}",
return makeCertificateInternal(isRoot, subject, $"CN={subject}",
DateTime.UtcNow.AddDays(-certificateGraceDays), DateTime.UtcNow.AddDays(certificateValidDays),
isRoot ? null : signingCert);
}
......
......@@ -80,10 +80,10 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <returns></returns>
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,
X509Certificate2 signingCertificate)
{
......@@ -274,13 +274,13 @@ namespace Titanium.Web.Proxy.Network.Certificate
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,
CancellationToken cancellationToken = default)
{
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;
}
......@@ -301,7 +301,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
var graceTime = DateTime.Now.AddDays(graceDays);
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);
return certificate;
}
......
......@@ -3,6 +3,7 @@ using System;
using System.IO;
using System.Text;
using System.Threading;
using StreamExtended;
using StreamExtended.Network;
namespace Titanium.Web.Proxy.Network
......@@ -17,7 +18,8 @@ namespace Titanium.Web.Proxy.Network
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);
fileStreamSent = new FileStream(Path.Combine(basePath, $"{connectionId}_{type}_{Counter}_sent.dat"), FileMode.Create);
......
using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using Titanium.Web.Proxy.Extensions;
......@@ -41,9 +40,8 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary>
public void Dispose()
{
tcpClient.CloseSocket();
proxyServer.UpdateClientConnectionCount(false);
tcpClient.CloseSocket();
}
}
}
using System;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using StreamExtended.Network;
using Titanium.Web.Proxy.Extensions;
......@@ -48,6 +47,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
private readonly TcpClient tcpClient;
/// <summary>
/// The TcpClient.
/// </summary>
internal TcpClient TcpClient => tcpClient;
/// <summary>
/// Used to write lines to server
/// </summary>
......@@ -63,16 +67,24 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary>
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>
/// Dispose.
/// </summary>
public void Dispose()
{
proxyServer.UpdateServerConnectionCount(false);
Stream?.Dispose();
tcpClient.CloseSocket();
proxyServer.UpdateServerConnectionCount(false);
}
}
}
......@@ -18,7 +18,7 @@ namespace Titanium.Web.Proxy
/// </summary>
/// <param name="session">The session event arguments.</param>
/// <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 (AuthenticateUserFunc == null)
......@@ -33,7 +33,7 @@ namespace Titanium.Web.Proxy
var header = httpHeaders.GetFirstHeader(KnownHeaders.ProxyAuthorization);
if (header == null)
{
session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Required");
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Required");
return false;
}
......@@ -42,7 +42,7 @@ namespace Titanium.Web.Proxy
!headerValueParts[0].EqualsIgnoreCase(KnownHeaders.ProxyAuthorizationBasic))
{
// Return not authorized
session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Invalid");
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false;
}
......@@ -51,7 +51,7 @@ namespace Titanium.Web.Proxy
if (colonIndex == -1)
{
// Return not authorized
session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Invalid");
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false;
}
......@@ -60,7 +60,7 @@ namespace Titanium.Web.Proxy
bool authenticated = await AuthenticateUserFunc(username, password);
if (!authenticated)
{
session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Invalid");
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
}
return authenticated;
......@@ -71,7 +71,7 @@ namespace Titanium.Web.Proxy
httpHeaders));
// Return not authorized
session.WebSession.Response = CreateAuthentication407Response("Proxy Authentication Invalid");
session.WebSession.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false;
}
}
......@@ -81,7 +81,7 @@ namespace Titanium.Web.Proxy
/// </summary>
/// <param name="description">Response description.</param>
/// <returns></returns>
private Response CreateAuthentication407Response(string description)
private Response createAuthentication407Response(string description)
{
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 Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Network.WinAuth.Security;
......@@ -18,116 +16,111 @@ namespace Titanium.Web.Proxy
/// </summary>
/// <param name="args">The session event arguments.</param>
/// <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;
args.ReRequest = false;
var cancellationToken = args.CancellationTokenSource.Token;
// check for windows authentication
if (isWindowsAuthenticationEnabledAndSupported)
{
if (response.StatusCode == (int)HttpStatusCode.Unauthorized)
{
await Handle401UnAuthorized(args);
}
else
{
WinAuthEndPoint.AuthenticatedResponse(args.WebSession.Data);
}
}
// read response & headers from server
await args.WebSession.ReceiveResponse(cancellationToken);
response.OriginalHasBody = response.HasBody;
var response = args.WebSession.Response;
args.ReRequest = false;
// if user requested call back then do it
if (!response.Locked)
// check for windows authentication
if (isWindowsAuthenticationEnabledAndSupported)
{
if (response.StatusCode == (int)HttpStatusCode.Unauthorized)
{
await InvokeBeforeResponse(args);
await handle401UnAuthorized(args);
}
// it may changed in the user event
response = args.WebSession.Response;
var clientStreamWriter = args.ProxyClient.ClientStreamWriter;
if (response.TerminateResponse || response.Locked)
else
{
await clientStreamWriter.WriteResponseAsync(response, cancellationToken: cancellationToken);
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;
WinAuthEndPoint.AuthenticatedResponse(args.WebSession.Data);
}
}
// 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.OriginalHasBody = response.HasBody;
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
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);
}
// it may changed in the user event
response = args.WebSession.Response;
if (!args.IsTransparent)
{
response.Headers.FixProxyHeaders();
}
var clientStreamWriter = args.ProxyClient.ClientStreamWriter;
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
{
// 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);
}
await tcpConnectionFactory.Release(args.WebSession.ServerConnection, true);
args.WebSession.ServerConnection = null;
}
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>
......@@ -135,7 +128,7 @@ namespace Titanium.Web.Proxy
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private async Task InvokeBeforeResponse(SessionEventArgs args)
private async Task invokeBeforeResponse(SessionEventArgs args)
{
if (BeforeResponse != null)
{
......@@ -148,7 +141,7 @@ namespace Titanium.Web.Proxy
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private async Task InvokeAfterResponse(SessionEventArgs args)
private async Task invokeAfterResponse(SessionEventArgs args)
{
if (AfterResponse != null)
{
......
......@@ -13,7 +13,7 @@
<ItemGroup>
<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 Condition="'$(TargetFramework)' == 'netstandard2.0'">
......@@ -34,7 +34,7 @@
</PackageReference>
</ItemGroup>
<ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
<Reference Include="System.Web" />
</ItemGroup>
......
......@@ -14,7 +14,7 @@
<copyright>Copyright &#x00A9; Titanium. All rights reserved.</copyright>
<tags></tags>
<dependencies>
<dependency id="StreamExtended" version="1.0.164" />
<dependency id="StreamExtended" version="1.0.175-beta" />
<dependency id="Portable.BouncyCastle" version="1.8.2" />
</dependencies>
</metadata>
......
......@@ -6,7 +6,6 @@ using System.Security.Authentication;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using StreamExtended.Helpers;
using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions;
......@@ -26,18 +25,21 @@ namespace Titanium.Web.Proxy
/// <param name="endPoint">The transparent endpoint.</param>
/// <param name="clientConnection">The client connection.</param>
/// <returns></returns>
private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClientConnection clientConnection)
private async Task handleClient(TransparentProxyEndPoint endPoint, TcpClientConnection clientConnection)
{
var cancellationTokenSource = new CancellationTokenSource();
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
{
var clientHelloInfo = await SslTools.PeekClientHello(clientStream, cancellationToken);
var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);
bool isHttps = clientHelloInfo != null;
string httpsHostName = null;
......@@ -60,8 +62,13 @@ namespace Titanium.Web.Proxy
if (endPoint.DecryptSsl && args.DecryptSsl)
{
prefetchConnectionTask = tcpConnectionFactory.GetClient(httpsHostName, endPoint.Port,
null, true, null,
false, this, UpStreamEndPoint, UpStreamHttpsProxy, cancellationToken);
SslStream sslStream = null;
//do client authentication using fake certificate
try
{
sslStream = new SslStream(clientStream);
......@@ -73,9 +80,9 @@ namespace Titanium.Web.Proxy
await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false);
// HTTPS server created - we can now decrypt the client's traffic
clientStream = new CustomBufferedStream(sslStream, BufferSize);
clientStream = new CustomBufferedStream(sslStream, BufferPool, BufferSize);
clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize);
clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize);
}
catch (Exception e)
{
......@@ -87,66 +94,77 @@ namespace Titanium.Web.Proxy
else
{
// create new connection
var connection = new TcpClient(UpStreamEndPoint);
await connection.ConnectAsync(httpsHostName, endPoint.Port);
connection.ReceiveTimeout = ConnectionTimeOutSeconds * 1000;
connection.SendTimeout = ConnectionTimeOutSeconds * 1000;
var connection = await tcpConnectionFactory.GetClient(httpsHostName, endPoint.Port,
null, false, null,
true, this, UpStreamEndPoint, UpStreamHttpsProxy, cancellationToken);
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;
if (available > 0)
try
{
// send the buffered data
var data = BufferPool.GetBuffer(BufferSize);
try
{
// 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);
}
// 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);
}
}
////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
// Now create the request
await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
cancellationTokenSource, isHttps ? httpsHostName : null, null);
await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
cancellationTokenSource, isHttps ? httpsHostName : null, null, prefetchConnectionTask);
}
catch (ProxyException e)
{
OnException(clientStream, e);
closeServerConnection = true;
onException(clientStream, 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)
{
OnException(clientStream, new Exception("Could not connect", e));
closeServerConnection = true;
onException(clientStream, new Exception("Could not connect", 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
{
if (!calledRequestHandler
&& prefetchConnectionTask != null)
{
var connection = await prefetchConnectionTask;
await tcpConnectionFactory.Release(connection, closeServerConnection);
}
clientStream.Dispose();
if (!cancellationTokenSource.IsCancellationRequested)
{
cancellationTokenSource.Cancel();
......
......@@ -45,7 +45,7 @@ namespace Titanium.Web.Proxy
/// User to server to authenticate requests.
/// To disable this set ProxyServer.EnableWinAuth to false.
/// </summary>
internal async Task Handle401UnAuthorized(SessionEventArgs args)
private async Task handle401UnAuthorized(SessionEventArgs args)
{
string headerName = null;
HttpHeader authHeader = null;
......@@ -99,7 +99,7 @@ namespace Titanium.Web.Proxy
if (!WinAuthEndPoint.ValidateWinAuthState(args.WebSession.Data, expectedAuthState))
{
// Invalid state, create proper error message to client
await RewriteUnauthorizedResponse(args);
await rewriteUnauthorizedResponse(args);
return;
}
......@@ -145,6 +145,8 @@ namespace Titanium.Web.Proxy
{
request.ContentLength = request.Body.Length;
}
args.WebSession.ServerConnection.IsWinAuthenticated = true;
}
// Need to revisit this.
......@@ -161,7 +163,7 @@ namespace Titanium.Web.Proxy
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
internal async Task RewriteUnauthorizedResponse(SessionEventArgs args)
private async Task rewriteUnauthorizedResponse(SessionEventArgs args)
{
var response = args.WebSession.Response;
......
......@@ -2,5 +2,5 @@
<packages>
<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>
\ No newline at end of file
......@@ -103,10 +103,13 @@ or when server terminates connection from proxy.</p>
<div class="inheritedMembers">
<h5>Inherited Members</h5>
<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>
<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>
<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>
<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 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="parameters">Parameters</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -195,8 +198,8 @@ or when server terminates connection from proxy.</p>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.int32">Int32</a></td>
<td><span class="parametername">bufferSize</span></td>
<td><a class="xref" href="Titanium.Web.Proxy.ProxyServer.html">ProxyServer</a></td>
<td><span class="parametername">server</span></td>
<td></td>
</tr>
<tr>
......@@ -214,11 +217,6 @@ or when server terminates connection from proxy.</p>
<td><span class="parametername">cancellationTokenSource</span></td>
<td></td>
</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>
</table>
<h3 id="properties">Properties
......
......@@ -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>
<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 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="parameters">Parameters</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -157,8 +157,8 @@ or when server terminates connection from proxy.</p>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.int32">Int32</a></td>
<td><span class="parametername">bufferSize</span></td>
<td><a class="xref" href="Titanium.Web.Proxy.ProxyServer.html">ProxyServer</a></td>
<td><span class="parametername">server</span></td>
<td></td>
</tr>
<tr>
......@@ -176,24 +176,42 @@ or when server terminates connection from proxy.</p>
<td><span class="parametername">request</span></td>
<td></td>
</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>
<td><a class="xref" href="Titanium.Web.Proxy.ExceptionHandler.html">ExceptionHandler</a></td>
<td><span class="parametername">exceptionFunc</span></td>
<td><span class="xref">StreamExtended.IBufferPool</span></td>
<td></td>
</tr>
</tbody>
</table>
<h3 id="fields">Fields
</h3>
<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>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferSize" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferSize">bufferSize</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 int BufferSize</code></pre>
<pre><code class="lang-csharp hljs">protected readonly int bufferSize</code></pre>
</div>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -212,12 +230,12 @@ or when server terminates connection from proxy.</p>
</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 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......
......@@ -100,10 +100,13 @@
<div class="inheritedMembers">
<h5>Inherited Members</h5>
<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>
<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>
<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>
</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>
<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>
......@@ -417,6 +443,33 @@ Defaults to false.</p>
</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>
<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).
......@@ -525,6 +578,34 @@ User should return the ExternalProxy object with valid credentials.</p>
</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>
<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>
......@@ -1109,6 +1190,56 @@ Will throw error if the end point does&apos;nt exist.</p>
</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>
<div class="markdown level1 summary"><p>Event to override the default verification logic of remote SSL certificate received during authentication.</p>
</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