Commit b7a9c729 authored by justcoding121's avatar justcoding121

implement tcp server connection pool

parent ad1ab97f
...@@ -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);
......
...@@ -140,7 +140,7 @@ namespace Titanium.Web.Proxy ...@@ -140,7 +140,7 @@ namespace Titanium.Web.Proxy
SslExtensions.Http2ProtocolAsList, cancellationToken); SslExtensions.Http2ProtocolAsList, cancellationToken);
http2Supproted = connection.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2; http2Supproted = connection.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2;
tcpConnectionFactory.Release(connection); tcpConnectionFactory.Release(connection, true);
} }
SslStream sslStream = null; SslStream sslStream = null;
...@@ -235,7 +235,7 @@ namespace Titanium.Web.Proxy ...@@ -235,7 +235,7 @@ namespace Titanium.Web.Proxy
(buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
connectArgs.CancellationTokenSource, ExceptionFunc); connectArgs.CancellationTokenSource, ExceptionFunc);
tcpConnectionFactory.Release(connection); tcpConnectionFactory.Release(connection, true);
return; return;
} }
} }
...@@ -280,7 +280,7 @@ namespace Titanium.Web.Proxy ...@@ -280,7 +280,7 @@ namespace Titanium.Web.Proxy
(buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc); connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc);
#endif #endif
tcpConnectionFactory.Release(connection); tcpConnectionFactory.Release(connection, true);
} }
} }
......
...@@ -216,6 +216,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -216,6 +216,9 @@ namespace Titanium.Web.Proxy.Http
ConnectRequest?.FinishSession(); ConnectRequest?.FinishSession();
Request?.FinishSession(); Request?.FinishSession();
Response?.FinishSession(); Response?.FinishSession();
Data.Clear();
UserData = null;
} }
} }
} }
...@@ -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>
......
...@@ -43,7 +43,6 @@ namespace Titanium.Web.Proxy.Network ...@@ -43,7 +43,6 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
private readonly ConcurrentDictionary<string, CachedCertificate> certificateCache; private readonly ConcurrentDictionary<string, CachedCertificate> certificateCache;
private ExceptionHandler exceptionFunc;
private readonly ConcurrentDictionary<string, Task<X509Certificate2>> pendingCertificateCreationTasks; private readonly ConcurrentDictionary<string, Task<X509Certificate2>> pendingCertificateCreationTasks;
private ICertificateMaker certEngine; private ICertificateMaker certEngine;
...@@ -77,7 +76,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -77,7 +76,7 @@ namespace Titanium.Web.Proxy.Network
bool userTrustRootCertificate, bool machineTrustRootCertificate, bool trustRootCertificateAsAdmin, bool userTrustRootCertificate, bool machineTrustRootCertificate, bool trustRootCertificateAsAdmin,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
this.exceptionFunc = exceptionFunc; ExceptionFunc = exceptionFunc;
UserTrustRoot = userTrustRootCertificate || machineTrustRootCertificate; UserTrustRoot = userTrustRootCertificate || machineTrustRootCertificate;
...@@ -94,14 +93,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -94,14 +93,7 @@ namespace Titanium.Web.Proxy.Network
RootCertificateIssuerName = rootCertificateIssuerName; RootCertificateIssuerName = rootCertificateIssuerName;
} }
if (RunTime.IsWindows) CertificateEngine = RunTime.IsWindows ? CertificateEngine.DefaultWindows : CertificateEngine.BouncyCastle;
{
CertificateEngine = CertificateEngine.DefaultWindows;
}
else
{
CertificateEngine = CertificateEngine.BouncyCastle;
}
certificateCache = new ConcurrentDictionary<string, CachedCertificate>(); certificateCache = new ConcurrentDictionary<string, CachedCertificate>();
pendingCertificateCreationTasks = new ConcurrentDictionary<string, Task<X509Certificate2>>(); pendingCertificateCreationTasks = new ConcurrentDictionary<string, Task<X509Certificate2>>();
...@@ -131,6 +123,11 @@ namespace Titanium.Web.Proxy.Network ...@@ -131,6 +123,11 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
internal bool TrustRootAsAdministrator { get; set; } internal bool TrustRootAsAdministrator { get; set; }
/// <summary>
/// Exception handler
/// </summary>
internal ExceptionHandler ExceptionFunc { get; set; }
/// <summary> /// <summary>
/// Select Certificate Engine. /// Select Certificate Engine.
/// Optionally set to BouncyCastle. /// Optionally set to BouncyCastle.
...@@ -156,8 +153,8 @@ namespace Titanium.Web.Proxy.Network ...@@ -156,8 +153,8 @@ namespace Titanium.Web.Proxy.Network
if (certEngine == null) if (certEngine == null)
{ {
certEngine = engine == CertificateEngine.BouncyCastle certEngine = engine == CertificateEngine.BouncyCastle
? (ICertificateMaker)new BCCertificateMaker(exceptionFunc) ? (ICertificateMaker)new BCCertificateMaker(ExceptionFunc)
: new WinCertificateMaker(exceptionFunc); : new WinCertificateMaker(ExceptionFunc);
} }
} }
} }
...@@ -235,10 +232,6 @@ namespace Titanium.Web.Proxy.Network ...@@ -235,10 +232,6 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
public X509KeyStorageFlags StorageFlag { get; set; } = X509KeyStorageFlags.Exportable; public X509KeyStorageFlags StorageFlag { get; set; } = X509KeyStorageFlags.Exportable;
public ExceptionHandler ExceptionFunc {
set => exceptionFunc = value;
}
/// <summary> /// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary> /// </summary>
...@@ -329,7 +322,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -329,7 +322,7 @@ namespace Titanium.Web.Proxy.Network
{ {
if (RootCertificate == null) if (RootCertificate == null)
{ {
exceptionFunc(new Exception("Could not install certificate as it is null or empty.")); ExceptionFunc(new Exception("Could not install certificate as it is null or empty."));
return; return;
} }
...@@ -344,7 +337,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -344,7 +337,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc( ExceptionFunc(
new Exception("Failed to make system trust root certificate " new Exception("Failed to make system trust root certificate "
+ $" for {storeName}\\{storeLocation} store location. You may need admin rights.", + $" for {storeName}\\{storeLocation} store location. You may need admin rights.",
e)); e));
...@@ -366,7 +359,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -366,7 +359,7 @@ namespace Titanium.Web.Proxy.Network
{ {
if (certificate == null) if (certificate == null)
{ {
exceptionFunc(new Exception("Could not remove certificate as it is null or empty.")); ExceptionFunc(new Exception("Could not remove certificate as it is null or empty."));
return; return;
} }
...@@ -380,7 +373,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -380,7 +373,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc( ExceptionFunc(
new Exception("Failed to remove root certificate trust " new Exception("Failed to remove root certificate trust "
+ $" for {storeLocation} store location. You may need admin rights.", e)); + $" for {storeLocation} store location. You may need admin rights.", e));
} }
...@@ -438,7 +431,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -438,7 +431,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(new Exception("Failed to save fake certificate.", e)); ExceptionFunc(new Exception("Failed to save fake certificate.", e));
} }
}); });
} }
...@@ -462,7 +455,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -462,7 +455,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); ExceptionFunc(e);
} }
return certificate; return certificate;
...@@ -572,7 +565,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -572,7 +565,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); ExceptionFunc(e);
} }
if (persistToFile && RootCertificate != null) if (persistToFile && RootCertificate != null)
...@@ -593,7 +586,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -593,7 +586,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); ExceptionFunc(e);
} }
} }
...@@ -619,7 +612,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -619,7 +612,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); ExceptionFunc(e);
return null; return null;
} }
} }
...@@ -728,7 +721,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -728,7 +721,7 @@ namespace Titanium.Web.Proxy.Network
} }
catch (Exception e) catch (Exception e)
{ {
exceptionFunc(e); ExceptionFunc(e);
return false; return false;
} }
......
...@@ -5,6 +5,7 @@ using System.Linq; ...@@ -5,6 +5,7 @@ using System.Linq;
using System.Net; using System.Net;
using System.Net.Security; using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Network; using StreamExtended.Network;
...@@ -21,9 +22,21 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -21,9 +22,21 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary> /// </summary>
internal class TcpConnectionFactory internal class TcpConnectionFactory
{ {
//private readonly ConcurrentDictionary<string, List<TcpServerConnection>> cache //Tcp server connection pool cache
// = new ConcurrentDictionary<string, List<TcpServerConnection>>(); private readonly ConcurrentDictionary<string, ConcurrentQueue<TcpServerConnection>> cache
= new ConcurrentDictionary<string, ConcurrentQueue<TcpServerConnection>>();
//Tcp connections waiting to be disposed by cleanup task
private readonly ConcurrentBag<TcpServerConnection> disposalBag =
new ConcurrentBag<TcpServerConnection>();
//cache object race operations lock
private readonly SemaphoreSlim @lock = new SemaphoreSlim(1);
internal TcpConnectionFactory(int connectionTimeOutSeconds)
{
Task.Run(async () => await ClearOutdatedConnections(connectionTimeOutSeconds));
}
/// <summary> /// <summary>
/// Gets a TCP connection to server from connection pool. /// Gets a TCP connection to server from connection pool.
...@@ -35,7 +48,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -35,7 +48,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param> /// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param>
/// <param name="isConnect">Is this a CONNECT request.</param> /// <param name="isConnect">Is this a CONNECT request.</param>
/// <param name="proxyServer">The current ProxyServer instance.</param> /// <param name="proxyServer">The current ProxyServer instance.</param>
/// <param name="upStreamEndPoint">The upstream endpoint to make request via.</param> /// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
/// <param name="externalProxy">The external proxy to make request via.</param> /// <param name="externalProxy">The external proxy to make request via.</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param> /// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns> /// <returns></returns>
...@@ -44,23 +57,51 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -44,23 +57,51 @@ namespace Titanium.Web.Proxy.Network.Tcp
ProxyServer proxyServer, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy, ProxyServer proxyServer, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
//TODO fix cacheKey with all possible properties that uniquely identify a connection string cacheKey = null;
//var cacheKey = $"{remoteHostName}{remotePort}{httpVersion}" + if (proxyServer.EnableConnectionPool)
// $"{isHttps}{isConnect}"; {
var cacheKeyBuilder = new StringBuilder($"{remoteHostName}-{remotePort}" +
$"-{(httpVersion == null ? string.Empty : httpVersion.ToString())}" +
$"-{isHttps}-{isConnect}-");
if (applicationProtocols != null)
{
foreach (var protocol in applicationProtocols)
{
cacheKeyBuilder.Append($"{protocol}-");
}
}
cacheKeyBuilder.Append(upStreamEndPoint != null
? $"{upStreamEndPoint.Address}-{upStreamEndPoint.Port}-"
: string.Empty);
cacheKeyBuilder.Append(externalProxy != null ? $"{externalProxy.GetCacheKey()}-" : string.Empty);
cacheKey = cacheKeyBuilder.ToString();
if (cache.TryGetValue(cacheKey, out var existingConnections))
{
while (existingConnections.TryDequeue(out var recentConnection))
{
//+1 seconds for potential delay after getting connection
var cutOff = DateTime.Now.AddSeconds((-1 * proxyServer.ConnectionTimeOutSeconds) + 1);
if (recentConnection.LastAccess > cutOff
&& IsGoodConnection(recentConnection.TcpClient))
{
return recentConnection;
}
disposalBag.Add(recentConnection);
}
//if (cache.TryGetValue(cacheKey, out var existingConnections)) }
//{ }
// var recentConnection = existingConnections.Last();
// existingConnections.RemoveAt(existingConnections.Count - 1);
// //TODO check if connection is still active before returning
// return recentConnection;
//}
var connection = await CreateClient(remoteHostName, remotePort, httpVersion, isHttps, var connection = await CreateClient(remoteHostName, remotePort, httpVersion, isHttps,
applicationProtocols, isConnect, proxyServer, upStreamEndPoint, externalProxy, cancellationToken); applicationProtocols, isConnect, proxyServer, upStreamEndPoint, externalProxy, cancellationToken);
//connection.CacheKey = cacheKey; connection.CacheKey = cacheKey;
return connection; return connection;
} }
...@@ -74,7 +115,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -74,7 +115,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param> /// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param>
/// <param name="isConnect">Is this a CONNECT request.</param> /// <param name="isConnect">Is this a CONNECT request.</param>
/// <param name="proxyServer">The current ProxyServer instance.</param> /// <param name="proxyServer">The current ProxyServer instance.</param>
/// <param name="upStreamEndPoint">The upstream endpoint to make request via.</param> /// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
/// <param name="externalProxy">The external proxy to make request via.</param> /// <param name="externalProxy">The external proxy to make request via.</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param> /// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns> /// <returns></returns>
...@@ -114,7 +155,6 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -114,7 +155,6 @@ namespace Titanium.Web.Proxy.Network.Tcp
ReceiveBufferSize = proxyServer.BufferSize ReceiveBufferSize = proxyServer.BufferSize
}; };
await proxyServer.InvokeConnectionCreateEvent(tcpClient, false); await proxyServer.InvokeConnectionCreateEvent(tcpClient, false);
// If this proxy uses another external proxy then create a tunnel request for HTTP/HTTPS connections // If this proxy uses another external proxy then create a tunnel request for HTTP/HTTPS connections
...@@ -192,7 +232,6 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -192,7 +232,6 @@ namespace Titanium.Web.Proxy.Network.Tcp
return new TcpServerConnection(proxyServer, tcpClient) return new TcpServerConnection(proxyServer, tcpClient)
{ {
//CacheKey = cacheKey,
UpStreamProxy = externalProxy, UpStreamProxy = externalProxy,
UpStreamEndPoint = upStreamEndPoint, UpStreamEndPoint = upStreamEndPoint,
HostName = remoteHostName, HostName = remoteHostName,
...@@ -210,24 +249,106 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -210,24 +249,106 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// Release connection back to cache. /// Release connection back to cache.
/// </summary> /// </summary>
/// <param name="connection">The Tcp server connection to return.</param> /// <param name="connection">The Tcp server connection to return.</param>
internal void Release(TcpServerConnection connection) /// <param name="close">Should we just close the connection instead of reusing?</param>
internal void Release(TcpServerConnection connection, bool close = false)
{
if (close || connection.IsWinAuthenticated)
{
disposalBag.Add(connection);
return;
}
connection.LastAccess = DateTime.Now;
@lock.Wait();
while (true)
{
if (cache.TryGetValue(connection.CacheKey, out var existingConnections))
{
existingConnections.Enqueue(connection);
break;
}
if (cache.TryAdd(connection.CacheKey, new ConcurrentQueue<TcpServerConnection>(new[] { connection })))
{
break;
};
}
@lock.Release();
}
private async Task ClearOutdatedConnections(int connectionTimeOutSeconds)
{
while (true)
{
foreach (var item in cache)
{
var queue = item.Value;
while (queue.TryDequeue(out var connection))
{
var cutOff = DateTime.Now.AddSeconds(-1 * connectionTimeOutSeconds);
if (connection.LastAccess < cutOff)
{
disposalBag.Add(connection);
continue;
}
queue.Enqueue(connection);
break;
}
}
//clear empty queues
await @lock.WaitAsync();
var emptyKeys = cache.Where(x => x.Value.Count == 0).Select(x => x.Key).ToList();
foreach (var key in emptyKeys)
{
cache.TryRemove(key, out var _);
}
@lock.Release();
while (disposalBag.TryTake(out TcpServerConnection connection))
{
connection?.Dispose();
}
//cleanup every ten seconds by default
await Task.Delay(1000 * 10);
}
}
/// <summary>
/// Check if a TcpClient is good to be used.
/// https://msdn.microsoft.com/en-us/library/system.net.sockets.socket.connected(v=vs.110).aspx
/// </summary>
/// <param name="client"></param>
/// <returns></returns>
private static bool IsGoodConnection(TcpClient client)
{ {
//while (true) var socket = client.Client;
//{ // This is how you can determine whether a socket is still connected.
// if (cache.TryGetValue(connection.Key, out var existingConnections)) bool blockingState = socket.Blocking;
// { try
// existingConnections.Add(connection); {
// break; var tmp = new byte[1];
// }
socket.Blocking = false;
// if (cache.TryAdd(connection.Key, new List<TcpServerConnection> { connection })) socket.Send(tmp, 0, 0);
// { //Connected!
// break; }
// }; catch
//} {
//Should we let 10035 == WSAEWOULDBLOCK as valid connection?
connection?.Dispose(); return false;
}
finally
{
socket.Blocking = blockingState;
}
return true;
} }
} }
} }
...@@ -48,6 +48,11 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -48,6 +48,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>
...@@ -68,6 +73,11 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -68,6 +73,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary> /// </summary>
internal string CacheKey { get; set; } internal string CacheKey { get; set; }
/// <summary>
/// Is this connection authenticated via WinAuth
/// </summary>
internal bool IsWinAuthenticated { get; set; }
/// <summary> /// <summary>
/// Dispose. /// Dispose.
/// </summary> /// </summary>
......
...@@ -98,7 +98,7 @@ namespace Titanium.Web.Proxy ...@@ -98,7 +98,7 @@ namespace Titanium.Web.Proxy
ConnectionTimeOutSeconds = 60; ConnectionTimeOutSeconds = 60;
ProxyEndPoints = new List<ProxyEndPoint>(); ProxyEndPoints = new List<ProxyEndPoint>();
tcpConnectionFactory = new TcpConnectionFactory(); tcpConnectionFactory = new TcpConnectionFactory(ConnectionTimeOutSeconds);
if (!RunTime.IsRunningOnMono && RunTime.IsWindows) if (!RunTime.IsRunningOnMono && RunTime.IsWindows)
{ {
systemProxySettingsManager = new SystemProxyManager(); systemProxySettingsManager = new SystemProxyManager();
...@@ -149,6 +149,12 @@ namespace Titanium.Web.Proxy ...@@ -149,6 +149,12 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public bool Enable100ContinueBehaviour { get; set; } public bool Enable100ContinueBehaviour { get; set; }
/// <summary>
/// Should we enable experimental Tcp server connection pool?
/// Defaults to false.
/// </summary>
public bool EnableConnectionPool { get; set; }
/// <summary> /// <summary>
/// Buffer size used throughout this proxy. /// Buffer size used throughout this proxy.
/// </summary> /// </summary>
......
...@@ -55,6 +55,7 @@ namespace Titanium.Web.Proxy ...@@ -55,6 +55,7 @@ namespace Titanium.Web.Proxy
{ {
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
TcpServerConnection serverConnection = null; TcpServerConnection serverConnection = null;
bool serverConnectionClose = false;
try try
{ {
...@@ -182,7 +183,7 @@ namespace Titanium.Web.Proxy ...@@ -182,7 +183,7 @@ namespace Titanium.Web.Proxy
|| args.WebSession.UpStreamEndPoint?.Equals(serverConnection.UpStreamEndPoint) == || args.WebSession.UpStreamEndPoint?.Equals(serverConnection.UpStreamEndPoint) ==
false)) false))
{ {
serverConnection.Dispose(); tcpConnectionFactory.Release(serverConnection, true);
serverConnection = null; serverConnection = null;
} }
...@@ -241,6 +242,7 @@ namespace Titanium.Web.Proxy ...@@ -241,6 +242,7 @@ namespace Titanium.Web.Proxy
// if connection is closing exit // if connection is closing exit
if (!response.KeepAlive) if (!response.KeepAlive)
{ {
serverConnectionClose = true;
return; return;
} }
...@@ -257,6 +259,7 @@ namespace Titanium.Web.Proxy ...@@ -257,6 +259,7 @@ namespace Titanium.Web.Proxy
catch (Exception e) catch (Exception e)
{ {
args.Exception = e; args.Exception = e;
serverConnectionClose = true;
throw; throw;
} }
finally finally
...@@ -268,7 +271,7 @@ namespace Titanium.Web.Proxy ...@@ -268,7 +271,7 @@ namespace Titanium.Web.Proxy
} }
finally finally
{ {
tcpConnectionFactory.Release(serverConnection); tcpConnectionFactory.Release(serverConnection, serverConnectionClose || !EnableConnectionPool);
} }
} }
......
...@@ -89,7 +89,7 @@ namespace Titanium.Web.Proxy ...@@ -89,7 +89,7 @@ namespace Titanium.Web.Proxy
{ {
// create new connection // create new connection
var connection = await tcpConnectionFactory.GetClient(httpsHostName, endPoint.Port, var connection = await tcpConnectionFactory.GetClient(httpsHostName, endPoint.Port,
null, false, new List<SslApplicationProtocol> { clientConnection.NegotiatedApplicationProtocol }, null, false, null,
true, this, UpStreamEndPoint, UpStreamHttpsProxy, cancellationToken); true, this, UpStreamEndPoint, UpStreamHttpsProxy, cancellationToken);
...@@ -117,7 +117,7 @@ namespace Titanium.Web.Proxy ...@@ -117,7 +117,7 @@ namespace Titanium.Web.Proxy
await TcpHelper.SendRaw(clientStream, serverStream, BufferSize, await TcpHelper.SendRaw(clientStream, serverStream, BufferSize,
null, null, cancellationTokenSource, ExceptionFunc); null, null, cancellationTokenSource, ExceptionFunc);
tcpConnectionFactory.Release(connection); tcpConnectionFactory.Release(connection, true);
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.
......
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