Commit 687a8740 authored by Honfika's avatar Honfika

TcpClientConnection class

parent c882467b
...@@ -9,7 +9,6 @@ using System.Windows; ...@@ -9,7 +9,6 @@ using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
......
...@@ -11,6 +11,7 @@ using Titanium.Web.Proxy.Helpers; ...@@ -11,6 +11,7 @@ using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http.Responses; using Titanium.Web.Proxy.Http.Responses;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
......
...@@ -87,7 +87,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -87,7 +87,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Client End Point. /// Client End Point.
/// </summary> /// </summary>
public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint; public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.ClientConnection.RemoteEndPoint;
/// <summary> /// <summary>
/// A web session corresponding to a single request/response sequence /// A web session corresponding to a single request/response sequence
......
...@@ -15,6 +15,8 @@ using Titanium.Web.Proxy.Extensions; ...@@ -15,6 +15,8 @@ using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
...@@ -25,14 +27,14 @@ namespace Titanium.Web.Proxy ...@@ -25,14 +27,14 @@ namespace Titanium.Web.Proxy
/// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy /// So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
/// </summary> /// </summary>
/// <param name="endPoint">The explicit endpoint.</param> /// <param name="endPoint">The explicit endpoint.</param>
/// <param name="tcpClient">The client.</param> /// <param name="clientConnection">The client connection.</param>
/// <returns>The task.</returns> /// <returns>The task.</returns>
private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpClient) private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClientConnection clientConnection)
{ {
var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize); var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferSize);
var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize);
...@@ -67,7 +69,7 @@ namespace Titanium.Web.Proxy ...@@ -67,7 +69,7 @@ namespace Titanium.Web.Proxy
connectArgs = new TunnelConnectSessionEventArgs(BufferSize, endPoint, connectRequest, connectArgs = new TunnelConnectSessionEventArgs(BufferSize, endPoint, connectRequest,
cancellationTokenSource, ExceptionFunc); cancellationTokenSource, ExceptionFunc);
connectArgs.ProxyClient.TcpClient = tcpClient; connectArgs.ProxyClient.ClientConnection = clientConnection;
connectArgs.ProxyClient.ClientStream = clientStream; connectArgs.ProxyClient.ClientStream = clientStream;
await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc); await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc);
...@@ -158,7 +160,7 @@ namespace Titanium.Web.Proxy ...@@ -158,7 +160,7 @@ namespace Titanium.Web.Proxy
options.ApplicationProtocols = clientHelloInfo.GetAlpn(); options.ApplicationProtocols = clientHelloInfo.GetAlpn();
if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0) if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0)
{ {
options.ApplicationProtocols = Titanium.Web.Proxy.Extensions.SslExtensions.Http11ProtocolAsList; options.ApplicationProtocols = SslExtensions.Http11ProtocolAsList;
} }
} }
...@@ -270,13 +272,13 @@ namespace Titanium.Web.Proxy ...@@ -270,13 +272,13 @@ namespace Titanium.Web.Proxy
await TcpHelper.SendHttp2(clientStream, connection.Stream, BufferSize, await TcpHelper.SendHttp2(clientStream, connection.Stream, BufferSize,
(buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); },
(buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
connectArgs.CancellationTokenSource, ExceptionFunc); connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc);
} }
} }
} }
//Now create the request //Now create the request
await HandleHttpSessionRequest(endPoint, tcpClient, clientStream, await HandleHttpSessionRequest(endPoint, clientConnection, clientStream,
clientStreamWriter, cancellationTokenSource, connectHostname, clientStreamWriter, cancellationTokenSource, connectHostname,
connectArgs?.WebSession.ConnectRequest); connectArgs?.WebSession.ConnectRequest);
} }
......
...@@ -265,15 +265,14 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -265,15 +265,14 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="onDataSend"></param> /// <param name="onDataSend"></param>
/// <param name="onDataReceive"></param> /// <param name="onDataReceive"></param>
/// <param name="cancellationTokenSource"></param> /// <param name="cancellationTokenSource"></param>
/// <param name="connectionId"></param>
/// <param name="exceptionFunc"></param> /// <param name="exceptionFunc"></param>
/// <returns></returns> /// <returns></returns>
internal static async Task SendHttp2(Stream clientStream, Stream serverStream, int bufferSize, internal static async Task SendHttp2(Stream clientStream, Stream serverStream, int bufferSize,
Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive, Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive,
CancellationTokenSource cancellationTokenSource, CancellationTokenSource cancellationTokenSource, Guid connectionId,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
var connectionId = Guid.NewGuid();
//Now async relay all server=>client & client=>server data //Now async relay all server=>client & client=>server data
var sendRelay = var sendRelay =
CopyHttp2FrameAsync(clientStream, serverStream, onDataSend, bufferSize, connectionId, CopyHttp2FrameAsync(clientStream, serverStream, onDataSend, bufferSize, connectionId,
......
...@@ -28,7 +28,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -28,7 +28,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Connection to server /// Connection to server
/// </summary> /// </summary>
internal TcpConnection ServerConnection { get; set; } internal TcpServerConnection ServerConnection { get; set; }
/// <summary> /// <summary>
/// Request ID. /// Request ID.
...@@ -69,11 +69,11 @@ namespace Titanium.Web.Proxy.Http ...@@ -69,11 +69,11 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Set the tcp connection to server used by this webclient /// Set the tcp connection to server used by this webclient
/// </summary> /// </summary>
/// <param name="connection">Instance of <see cref="TcpConnection" /></param> /// <param name="serverConnection">Instance of <see cref="TcpServerConnection" /></param>
internal void SetConnection(TcpConnection connection) internal void SetConnection(TcpServerConnection serverConnection)
{ {
connection.LastAccess = DateTime.Now; serverConnection.LastAccess = DateTime.Now;
ServerConnection = connection; ServerConnection = serverConnection;
} }
/// <summary> /// <summary>
......
#if DEBUG #if DEBUG
using System;
using System.IO; using System.IO;
using System.Text;
using System.Threading; using System.Threading;
using StreamExtended.Network; using StreamExtended.Network;
...@@ -15,11 +17,11 @@ namespace Titanium.Web.Proxy.Network ...@@ -15,11 +17,11 @@ namespace Titanium.Web.Proxy.Network
private readonly FileStream fileStreamSent; private readonly FileStream fileStreamSent;
public DebugCustomBufferedStream(Stream baseStream, int bufferSize) : base(baseStream, bufferSize) public DebugCustomBufferedStream(Guid connectionId, string type, Stream baseStream, int bufferSize, bool leaveOpen = false) : base(baseStream, bufferSize, leaveOpen)
{ {
Counter = Interlocked.Increment(ref counter); Counter = Interlocked.Increment(ref counter);
fileStreamSent = new FileStream(Path.Combine(basePath, $"{Counter}_sent.dat"), FileMode.Create); fileStreamSent = new FileStream(Path.Combine(basePath, $"{connectionId}_{type}_{Counter}_sent.dat"), FileMode.Create);
fileStreamReceived = new FileStream(Path.Combine(basePath, $"{Counter}_received.dat"), FileMode.Create); fileStreamReceived = new FileStream(Path.Combine(basePath, $"{connectionId}_{type}_{Counter}_received.dat"), FileMode.Create);
} }
public int Counter { get; } public int Counter { get; }
...@@ -27,18 +29,42 @@ namespace Titanium.Web.Proxy.Network ...@@ -27,18 +29,42 @@ namespace Titanium.Web.Proxy.Network
protected override void OnDataWrite(byte[] buffer, int offset, int count) protected override void OnDataWrite(byte[] buffer, int offset, int count)
{ {
fileStreamSent.Write(buffer, offset, count); fileStreamSent.Write(buffer, offset, count);
Flush();
} }
protected override void OnDataRead(byte[] buffer, int offset, int count) protected override void OnDataRead(byte[] buffer, int offset, int count)
{ {
fileStreamReceived.Write(buffer, offset, count); fileStreamReceived.Write(buffer, offset, count);
Flush();
} }
public void LogException(Exception ex)
{
var data = Encoding.UTF8.GetBytes("EXCEPTION: " + ex);
fileStreamReceived.Write(data, 0, data.Length);
fileStreamReceived.Flush();
}
public override void Flush() public override void Flush()
{ {
fileStreamSent.Flush(true); fileStreamSent.Flush(true);
fileStreamReceived.Flush(true); fileStreamReceived.Flush(true);
base.Flush();
if (CanWrite)
{
base.Flush();
}
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Flush();
fileStreamSent.Dispose();
fileStreamReceived.Dispose();
}
base.Dispose(disposing);
} }
} }
} }
......
using System.Net.Sockets; using StreamExtended.Network;
using StreamExtended.Network;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy.Network namespace Titanium.Web.Proxy.Network
{ {
...@@ -10,9 +10,9 @@ namespace Titanium.Web.Proxy.Network ...@@ -10,9 +10,9 @@ namespace Titanium.Web.Proxy.Network
internal class ProxyClient internal class ProxyClient
{ {
/// <summary> /// <summary>
/// TcpClient used to communicate with client /// TcpClient connection used to communicate with client
/// </summary> /// </summary>
internal TcpClient TcpClient { get; set; } internal TcpClientConnection ClientConnection { get; set; }
/// <summary> /// <summary>
/// Holds the stream to client /// Holds the stream to client
......
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using Titanium.Web.Proxy.Extensions;
namespace Titanium.Web.Proxy.Network.Tcp
{
/// <summary>
/// An object that holds TcpConnection to a particular server and port
/// </summary>
internal class TcpClientConnection : IDisposable
{
internal TcpClientConnection(ProxyServer proxyServer, TcpClient tcpClient)
{
this.tcpClient = tcpClient;
this.proxyServer = proxyServer;
this.proxyServer.UpdateClientConnectionCount(true);
}
private ProxyServer proxyServer { get; }
public Guid Id { get; } = Guid.NewGuid();
public EndPoint LocalEndPoint => tcpClient.Client.LocalEndPoint;
public EndPoint RemoteEndPoint => tcpClient.Client.RemoteEndPoint;
private readonly TcpClient tcpClient;
public Stream GetStream()
{
return tcpClient.GetStream();
}
/// <summary>
/// Dispose.
/// </summary>
public void Dispose()
{
tcpClient.CloseSocket();
proxyServer.UpdateClientConnectionCount(false);
}
}
}
...@@ -32,7 +32,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -32,7 +32,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="externalProxy"></param> /// <param name="externalProxy"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
internal async Task<TcpConnection> CreateClient(string remoteHostName, int remotePort, internal async Task<TcpServerConnection> CreateClient(string remoteHostName, int remotePort,
List<SslApplicationProtocol> applicationProtocols, Version httpVersion, bool decryptSsl, bool isConnect, List<SslApplicationProtocol> applicationProtocols, Version httpVersion, bool decryptSsl, bool isConnect,
ProxyServer proxyServer, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy, ProxyServer proxyServer, IPEndPoint upStreamEndPoint, ExternalProxy externalProxy,
CancellationToken cancellationToken) CancellationToken cancellationToken)
...@@ -52,26 +52,26 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -52,26 +52,26 @@ namespace Titanium.Web.Proxy.Network.Tcp
} }
} }
TcpClient client = null; TcpClient tcpClient = null;
CustomBufferedStream stream = null; CustomBufferedStream stream = null;
bool http2Supported = false; bool http2Supported = false;
try try
{ {
client = new TcpClient(upStreamEndPoint); tcpClient = new TcpClient(upStreamEndPoint);
//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
if (useUpstreamProxy) if (useUpstreamProxy)
{ {
await client.ConnectAsync(externalProxy.HostName, externalProxy.Port); await tcpClient.ConnectAsync(externalProxy.HostName, externalProxy.Port);
} }
else else
{ {
await client.ConnectAsync(remoteHostName, remotePort); await tcpClient.ConnectAsync(remoteHostName, remotePort);
} }
stream = new CustomBufferedStream(client.GetStream(), proxyServer.BufferSize); stream = new CustomBufferedStream(tcpClient.GetStream(), proxyServer.BufferSize);
if (useUpstreamProxy && (isConnect || decryptSsl)) if (useUpstreamProxy && (isConnect || decryptSsl))
{ {
...@@ -129,17 +129,17 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -129,17 +129,17 @@ namespace Titanium.Web.Proxy.Network.Tcp
#endif #endif
} }
client.ReceiveTimeout = proxyServer.ConnectionTimeOutSeconds * 1000; tcpClient.ReceiveTimeout = proxyServer.ConnectionTimeOutSeconds * 1000;
client.SendTimeout = proxyServer.ConnectionTimeOutSeconds * 1000; tcpClient.SendTimeout = proxyServer.ConnectionTimeOutSeconds * 1000;
} }
catch (Exception) catch (Exception)
{ {
stream?.Dispose(); stream?.Dispose();
client?.Close(); tcpClient?.Close();
throw; throw;
} }
return new TcpConnection(proxyServer) return new TcpServerConnection(proxyServer, tcpClient)
{ {
UpStreamProxy = externalProxy, UpStreamProxy = externalProxy,
UpStreamEndPoint = upStreamEndPoint, UpStreamEndPoint = upStreamEndPoint,
...@@ -148,7 +148,6 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -148,7 +148,6 @@ namespace Titanium.Web.Proxy.Network.Tcp
IsHttps = decryptSsl, IsHttps = decryptSsl,
IsHttp2Supported = http2Supported, IsHttp2Supported = http2Supported,
UseUpstreamProxy = useUpstreamProxy, UseUpstreamProxy = useUpstreamProxy,
TcpClient = client,
StreamWriter = new HttpRequestWriter(stream, proxyServer.BufferSize), StreamWriter = new HttpRequestWriter(stream, proxyServer.BufferSize),
Stream = stream, Stream = stream,
Version = httpVersion Version = httpVersion
......
...@@ -11,10 +11,11 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -11,10 +11,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary> /// <summary>
/// An object that holds TcpConnection to a particular server and port /// An object that holds TcpConnection to a particular server and port
/// </summary> /// </summary>
internal class TcpConnection : IDisposable internal class TcpServerConnection : IDisposable
{ {
internal TcpConnection(ProxyServer proxyServer) internal TcpServerConnection(ProxyServer proxyServer, TcpClient tcpClient)
{ {
this.tcpClient = tcpClient;
LastAccess = DateTime.Now; LastAccess = DateTime.Now;
this.proxyServer = proxyServer; this.proxyServer = proxyServer;
this.proxyServer.UpdateServerConnectionCount(true); this.proxyServer.UpdateServerConnectionCount(true);
...@@ -44,7 +45,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -44,7 +45,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary> /// </summary>
internal Version Version { get; set; } internal Version Version { get; set; }
internal TcpClient TcpClient { private get; set; } private readonly TcpClient tcpClient;
/// <summary> /// <summary>
/// Used to write lines to server /// Used to write lines to server
...@@ -68,7 +69,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -68,7 +69,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
{ {
Stream?.Dispose(); Stream?.Dispose();
TcpClient.CloseSocket(); tcpClient.CloseSocket();
proxyServer.UpdateServerConnectionCount(false); proxyServer.UpdateServerConnectionCount(false);
} }
......
...@@ -8,7 +8,6 @@ using System.Security.Cryptography.X509Certificates; ...@@ -8,7 +8,6 @@ using System.Security.Cryptography.X509Certificates;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Helpers.WinHttp; using Titanium.Web.Proxy.Helpers.WinHttp;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
...@@ -648,27 +647,20 @@ namespace Titanium.Web.Proxy ...@@ -648,27 +647,20 @@ namespace Titanium.Web.Proxy
private async Task HandleClient(TcpClient tcpClient, ProxyEndPoint endPoint) private async Task HandleClient(TcpClient tcpClient, ProxyEndPoint endPoint)
{ {
UpdateClientConnectionCount(true);
tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000; tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000;
tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000; tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000;
try using (var clientConnection = new TcpClientConnection(this, tcpClient))
{ {
if (endPoint is TransparentProxyEndPoint tep) if (endPoint is TransparentProxyEndPoint tep)
{ {
await HandleClient(tep, tcpClient); await HandleClient(tep, clientConnection);
} }
else else
{ {
await HandleClient((ExplicitProxyEndPoint)endPoint, tcpClient); await HandleClient((ExplicitProxyEndPoint)endPoint, clientConnection);
} }
} }
finally
{
UpdateClientConnectionCount(false);
tcpClient.CloseSocket();
}
} }
/// <summary> /// <summary>
......
using System; using System;
using System.Net; using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
...@@ -32,7 +31,7 @@ namespace Titanium.Web.Proxy ...@@ -32,7 +31,7 @@ namespace Titanium.Web.Proxy
/// client/server abruptly terminates connection or by normal HTTP termination. /// client/server abruptly terminates connection or by normal HTTP termination.
/// </summary> /// </summary>
/// <param name="endPoint">The proxy endpoint.</param> /// <param name="endPoint">The proxy endpoint.</param>
/// <param name="client">The client.</param> /// <param name="clientConnection">The client connection.</param>
/// <param name="clientStream">The client stream.</param> /// <param name="clientStream">The client stream.</param>
/// <param name="clientStreamWriter">The client stream writer.</param> /// <param name="clientStreamWriter">The client stream writer.</param>
/// <param name="cancellationTokenSource">The cancellation token source for this async task.</param> /// <param name="cancellationTokenSource">The cancellation token source for this async task.</param>
...@@ -43,13 +42,13 @@ namespace Titanium.Web.Proxy ...@@ -43,13 +42,13 @@ namespace Titanium.Web.Proxy
/// <param name="connectRequest">The Connect request if this is a HTTPS request from explicit endpoint.</param> /// <param name="connectRequest">The Connect request if this is a HTTPS request from explicit endpoint.</param>
/// <param name="isTransparentEndPoint">Is this a request from transparent endpoint?</param> /// <param name="isTransparentEndPoint">Is this a request from transparent endpoint?</param>
/// <returns></returns> /// <returns></returns>
private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClient client, private async Task HandleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientConnection clientConnection,
CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter, CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter,
CancellationTokenSource cancellationTokenSource, string httpsConnectHostname, ConnectRequest connectRequest, CancellationTokenSource cancellationTokenSource, string httpsConnectHostname, ConnectRequest connectRequest,
bool isTransparentEndPoint = false) bool isTransparentEndPoint = false)
{ {
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
TcpConnection connection = null; TcpServerConnection serverConnection = null;
try try
{ {
...@@ -67,7 +66,7 @@ namespace Titanium.Web.Proxy ...@@ -67,7 +66,7 @@ namespace Titanium.Web.Proxy
var args = new SessionEventArgs(BufferSize, endPoint, cancellationTokenSource, ExceptionFunc) var args = new SessionEventArgs(BufferSize, endPoint, cancellationTokenSource, ExceptionFunc)
{ {
ProxyClient = { TcpClient = client }, ProxyClient = { ClientConnection = clientConnection },
WebSession = { ConnectRequest = connectRequest } WebSession = { ConnectRequest = connectRequest }
}; };
...@@ -173,29 +172,29 @@ namespace Titanium.Web.Proxy ...@@ -173,29 +172,29 @@ namespace Titanium.Web.Proxy
} }
//create a new connection if hostname/upstream end point changes //create a new connection if hostname/upstream end point changes
if (connection != null if (serverConnection != null
&& (!connection.HostName.Equals(request.RequestUri.Host, && (!serverConnection.HostName.Equals(request.RequestUri.Host,
StringComparison.OrdinalIgnoreCase) StringComparison.OrdinalIgnoreCase)
|| args.WebSession.UpStreamEndPoint != null || args.WebSession.UpStreamEndPoint != null
&& !args.WebSession.UpStreamEndPoint.Equals(connection.UpStreamEndPoint))) && !args.WebSession.UpStreamEndPoint.Equals(serverConnection.UpStreamEndPoint)))
{ {
connection.Dispose(); serverConnection.Dispose();
connection = null; serverConnection = null;
} }
if (connection == null) if (serverConnection == null)
{ {
connection = await GetServerConnection(args, false, cancellationToken); serverConnection = await GetServerConnection(args, false, cancellationToken);
} }
//if upgrading to websocket then relay the requet without reading the contents //if upgrading to websocket then relay the requet without reading the contents
if (request.UpgradeToWebSocket) if (request.UpgradeToWebSocket)
{ {
//prepare the prefix content //prepare the prefix content
await connection.StreamWriter.WriteLineAsync(httpCmd, cancellationToken); await serverConnection.StreamWriter.WriteLineAsync(httpCmd, cancellationToken);
await connection.StreamWriter.WriteHeadersAsync(request.Headers, await serverConnection.StreamWriter.WriteHeadersAsync(request.Headers,
cancellationToken: cancellationToken); cancellationToken: cancellationToken);
string httpStatus = await connection.Stream.ReadLineAsync(cancellationToken); string httpStatus = await serverConnection.Stream.ReadLineAsync(cancellationToken);
Response.ParseResponseLine(httpStatus, out var responseVersion, Response.ParseResponseLine(httpStatus, out var responseVersion,
out int responseStatusCode, out int responseStatusCode,
...@@ -204,7 +203,7 @@ namespace Titanium.Web.Proxy ...@@ -204,7 +203,7 @@ namespace Titanium.Web.Proxy
response.StatusCode = responseStatusCode; response.StatusCode = responseStatusCode;
response.StatusDescription = responseStatusDescription; response.StatusDescription = responseStatusDescription;
await HeaderParser.ReadHeaders(connection.Stream, response.Headers, await HeaderParser.ReadHeaders(serverConnection.Stream, response.Headers,
cancellationToken); cancellationToken);
if (!args.IsTransparent) if (!args.IsTransparent)
...@@ -219,7 +218,7 @@ namespace Titanium.Web.Proxy ...@@ -219,7 +218,7 @@ namespace Titanium.Web.Proxy
await InvokeBeforeResponse(args); await InvokeBeforeResponse(args);
} }
await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, await TcpHelper.SendRaw(clientStream, serverConnection.Stream, BufferSize,
(buffer, offset, count) => { args.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { args.OnDataSent(buffer, offset, count); },
(buffer, offset, count) => { args.OnDataReceived(buffer, offset, count); }, (buffer, offset, count) => { args.OnDataReceived(buffer, offset, count); },
cancellationTokenSource, ExceptionFunc); cancellationTokenSource, ExceptionFunc);
...@@ -228,7 +227,7 @@ namespace Titanium.Web.Proxy ...@@ -228,7 +227,7 @@ namespace Titanium.Web.Proxy
} }
//construct the web request that we are going to issue on behalf of the client. //construct the web request that we are going to issue on behalf of the client.
await HandleHttpSessionRequestInternal(connection, args); await HandleHttpSessionRequestInternal(serverConnection, args);
if (args.WebSession.ServerConnection == null) if (args.WebSession.ServerConnection == null)
{ {
...@@ -265,17 +264,17 @@ namespace Titanium.Web.Proxy ...@@ -265,17 +264,17 @@ namespace Titanium.Web.Proxy
} }
finally finally
{ {
connection?.Dispose(); serverConnection?.Dispose();
} }
} }
/// <summary> /// <summary>
/// Handle a specific session (request/response sequence) /// Handle a specific session (request/response sequence)
/// </summary> /// </summary>
/// <param name="connection">The tcp connection.</param> /// <param name="serverConnection">The tcp connection.</param>
/// <param name="args">The session event arguments.</param> /// <param name="args">The session event arguments.</param>
/// <returns></returns> /// <returns></returns>
private async Task HandleHttpSessionRequestInternal(TcpConnection connection, SessionEventArgs args) private async Task HandleHttpSessionRequestInternal(TcpServerConnection serverConnection, SessionEventArgs args)
{ {
try try
{ {
...@@ -289,7 +288,7 @@ namespace Titanium.Web.Proxy ...@@ -289,7 +288,7 @@ namespace Titanium.Web.Proxy
//and see if server would return 100 conitinue //and see if server would return 100 conitinue
if (request.ExpectContinue) if (request.ExpectContinue)
{ {
args.WebSession.SetConnection(connection); args.WebSession.SetConnection(serverConnection);
await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent, await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent,
cancellationToken); cancellationToken);
} }
...@@ -316,7 +315,7 @@ namespace Titanium.Web.Proxy ...@@ -316,7 +315,7 @@ namespace Titanium.Web.Proxy
//If expect continue is not enabled then set the connectio and send request headers //If expect continue is not enabled then set the connectio and send request headers
if (!request.ExpectContinue) if (!request.ExpectContinue)
{ {
args.WebSession.SetConnection(connection); args.WebSession.SetConnection(serverConnection);
await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent, await args.WebSession.SendRequest(Enable100ContinueBehaviour, args.IsTransparent,
cancellationToken); cancellationToken);
} }
...@@ -361,7 +360,7 @@ namespace Titanium.Web.Proxy ...@@ -361,7 +360,7 @@ namespace Titanium.Web.Proxy
/// <param name="isConnect">Is this a CONNECT request.</param> /// <param name="isConnect">Is this a CONNECT request.</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>
private async Task<TcpConnection> GetServerConnection(SessionEventArgsBase args, bool isConnect, private async Task<TcpServerConnection> GetServerConnection(SessionEventArgsBase args, bool isConnect,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
ExternalProxy customUpStreamProxy = null; ExternalProxy customUpStreamProxy = null;
......
...@@ -11,6 +11,7 @@ using Titanium.Web.Proxy.EventArguments; ...@@ -11,6 +11,7 @@ using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
...@@ -21,14 +22,14 @@ namespace Titanium.Web.Proxy ...@@ -21,14 +22,14 @@ namespace Titanium.Web.Proxy
/// So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client /// So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client
/// </summary> /// </summary>
/// <param name="endPoint">The transparent endpoint.</param> /// <param name="endPoint">The transparent endpoint.</param>
/// <param name="tcpClient">The client.</param> /// <param name="clientConnection">The client connection.</param>
/// <returns></returns> /// <returns></returns>
private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient) private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClientConnection clientConnection)
{ {
var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize); var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferSize);
var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferSize);
...@@ -123,7 +124,7 @@ namespace Titanium.Web.Proxy ...@@ -123,7 +124,7 @@ namespace Titanium.Web.Proxy
//HTTPS server created - we can now decrypt the client's traffic //HTTPS server created - we can now decrypt the client's traffic
//Now create the request //Now create the request
await HandleHttpSessionRequest(endPoint, tcpClient, clientStream, clientStreamWriter, await HandleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
cancellationTokenSource, isHttps ? httpsHostName : null, null, true); cancellationTokenSource, isHttps ? httpsHostName : null, null, true);
} }
finally finally
......
...@@ -172,7 +172,7 @@ namespace Titanium.Web.Proxy ...@@ -172,7 +172,7 @@ namespace Titanium.Web.Proxy
// Add custom div to body to clarify that the proxy (not the client browser) failed authentication // Add custom div to body to clarify that the proxy (not the client browser) failed authentication
string authErrorMessage = string authErrorMessage =
"<div class=\"inserted-by-proxy\"><h2>NTLM authentication through Titanium.Web.Proxy (" + "<div class=\"inserted-by-proxy\"><h2>NTLM authentication through Titanium.Web.Proxy (" +
args.ProxyClient.TcpClient.Client.LocalEndPoint + args.ProxyClient.ClientConnection.LocalEndPoint +
") failed. Please check credentials.</h2></div>"; ") failed. Please check credentials.</h2></div>";
string originalErrorMessage = string originalErrorMessage =
"<div class=\"inserted-by-proxy\"><h3>Response from remote web server below.</h3></div><br/>"; "<div class=\"inserted-by-proxy\"><h3>Response from remote web server below.</h3></div><br/>";
......
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