Unverified Commit 0c70019f authored by honfika's avatar honfika Committed by GitHub

Merge pull request #693 from justcoding121/master

beta
parents f9a74d7b 9be5226b
using Titanium.Web.Proxy.EventArguments;
namespace Titanium.Web.Proxy.Examples.Basic
{
public static class ProxyEventArgsBaseExtensions
{
public static SampleClientState GetState(this ProxyEventArgsBase args)
{
if (args.ClientUserData == null)
{
args.ClientUserData = new SampleClientState();
}
return (SampleClientState)args.ClientUserData;
}
}
}
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Security; using System.Net.Security;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
...@@ -64,6 +61,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -64,6 +61,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
{ {
proxyServer.BeforeRequest += onRequest; proxyServer.BeforeRequest += onRequest;
proxyServer.BeforeResponse += onResponse; proxyServer.BeforeResponse += onResponse;
proxyServer.AfterResponse += onAfterResponse;
proxyServer.ServerCertificateValidationCallback += OnCertificateValidation; proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection; proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
...@@ -128,19 +126,32 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -128,19 +126,32 @@ namespace Titanium.Web.Proxy.Examples.Basic
private async Task<IExternalProxy> onGetCustomUpStreamProxyFunc(SessionEventArgsBase arg) private async Task<IExternalProxy> onGetCustomUpStreamProxyFunc(SessionEventArgsBase arg)
{ {
arg.GetState().PipelineInfo.AppendLine(nameof(onGetCustomUpStreamProxyFunc));
// this is just to show the functionality, provided values are junk // this is just to show the functionality, provided values are junk
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.9", Port = 9090, Password = "fake", UserName = "fake", UseDefaultCredentials = false }; return new ExternalProxy
{
BypassLocalhost = false, HostName = "127.0.0.9", Port = 9090, Password = "fake", UserName = "fake",
UseDefaultCredentials = false
};
} }
private async Task<IExternalProxy> onCustomUpStreamProxyFailureFunc(SessionEventArgsBase arg) private async Task<IExternalProxy> onCustomUpStreamProxyFailureFunc(SessionEventArgsBase arg)
{ {
arg.GetState().PipelineInfo.AppendLine(nameof(onCustomUpStreamProxyFailureFunc));
// this is just to show the functionality, provided values are junk // this is just to show the functionality, provided values are junk
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.10", Port = 9191, Password = "fake2", UserName = "fake2", UseDefaultCredentials = false }; return new ExternalProxy
{
BypassLocalhost = false, HostName = "127.0.0.10", Port = 9191, Password = "fake2", UserName = "fake2",
UseDefaultCredentials = false
};
} }
private async Task onBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) private async Task onBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{ {
string hostname = e.HttpClient.Request.RequestUri.Host; string hostname = e.HttpClient.Request.RequestUri.Host;
e.GetState().PipelineInfo.AppendLine(nameof(onBeforeTunnelConnectRequest) + ":" + hostname);
await writeToConsole("Tunnel to: " + hostname); await writeToConsole("Tunnel to: " + hostname);
if (hostname.Contains("dropbox.com")) if (hostname.Contains("dropbox.com"))
...@@ -186,12 +197,16 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -186,12 +197,16 @@ namespace Titanium.Web.Proxy.Examples.Basic
private Task onBeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e) private Task onBeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e)
{ {
e.GetState().PipelineInfo.AppendLine(nameof(onBeforeTunnelConnectResponse) + ":" + e.HttpClient.Request.RequestUri);
return Task.FromResult(false); return Task.FromResult(false);
} }
// intercept & cancel redirect or update requests // intercept & cancel redirect or update requests
private async Task onRequest(object sender, SessionEventArgs e) private async Task onRequest(object sender, SessionEventArgs e)
{ {
e.GetState().PipelineInfo.AppendLine(nameof(onRequest) + ":" + e.HttpClient.Request.RequestUri);
await writeToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount); await writeToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
await writeToConsole(e.HttpClient.Request.Url); await writeToConsole(e.HttpClient.Request.Url);
...@@ -233,6 +248,8 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -233,6 +248,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
// Modify response // Modify response
private async Task multipartRequestPartSent(object sender, MultipartRequestPartSentEventArgs e) private async Task multipartRequestPartSent(object sender, MultipartRequestPartSentEventArgs e)
{ {
e.GetState().PipelineInfo.AppendLine(nameof(multipartRequestPartSent));
var session = (SessionEventArgs)sender; var session = (SessionEventArgs)sender;
await writeToConsole("Multipart form data headers:"); await writeToConsole("Multipart form data headers:");
foreach (var header in e.Headers) foreach (var header in e.Headers)
...@@ -243,6 +260,8 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -243,6 +260,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
private async Task onResponse(object sender, SessionEventArgs e) private async Task onResponse(object sender, SessionEventArgs e)
{ {
e.GetState().PipelineInfo.AppendLine(nameof(onResponse));
if (e.HttpClient.ConnectRequest?.TunnelType == TunnelType.Websocket) if (e.HttpClient.ConnectRequest?.TunnelType == TunnelType.Websocket)
{ {
e.DataSent += WebSocket_DataSent; e.DataSent += WebSocket_DataSent;
...@@ -293,6 +312,11 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -293,6 +312,11 @@ namespace Titanium.Web.Proxy.Examples.Basic
//} //}
} }
private async Task onAfterResponse(object sender, SessionEventArgs e)
{
await writeToConsole($"Pipelineinfo: {e.GetState().PipelineInfo}", ConsoleColor.Yellow);
}
/// <summary> /// <summary>
/// Allows overriding default certificate validation logic /// Allows overriding default certificate validation logic
/// </summary> /// </summary>
...@@ -300,6 +324,8 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -300,6 +324,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
/// <param name="e"></param> /// <param name="e"></param>
public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e) public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{ {
e.GetState().PipelineInfo.AppendLine(nameof(OnCertificateValidation));
// set IsValid to true/false based on Certificate Errors // set IsValid to true/false based on Certificate Errors
if (e.SslPolicyErrors == SslPolicyErrors.None) if (e.SslPolicyErrors == SslPolicyErrors.None)
{ {
...@@ -316,6 +342,8 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -316,6 +342,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
/// <param name="e"></param> /// <param name="e"></param>
public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e) public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
{ {
e.GetState().PipelineInfo.AppendLine(nameof(OnCertificateSelection));
// set e.clientCertificate to override // set e.clientCertificate to override
return Task.FromResult(0); return Task.FromResult(0);
...@@ -352,3 +380,4 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -352,3 +380,4 @@ namespace Titanium.Web.Proxy.Examples.Basic
//} //}
} }
} }
using System;
using System.Text;
namespace Titanium.Web.Proxy.Examples.Basic
{
public class SampleClientState
{
public StringBuilder PipelineInfo { get; } = new StringBuilder();
}
}
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean> <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">120</s:Int64> <s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">120</s:Int64>
<s:String x:Key="/Default/CodeStyle/CSharpUsing/MandatoryImports/=System/@EntryIndexedValue">System</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseExplicitType</s:String> <s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseExplicitType</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseVar</s:String> <s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseVar</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BC/@EntryIndexedValue">BC</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BC/@EntryIndexedValue">BC</s:String>
......
...@@ -12,17 +12,18 @@ namespace Titanium.Web.Proxy ...@@ -12,17 +12,18 @@ namespace Titanium.Web.Proxy
/// Call back to override server certificate validation /// Call back to override server certificate validation
/// </summary> /// </summary>
/// <param name="sender">The sender object.</param> /// <param name="sender">The sender object.</param>
/// <param name="sessionArgs">The http session.</param>
/// <param name="certificate">The remote certificate.</param> /// <param name="certificate">The remote certificate.</param>
/// <param name="chain">The certificate chain.</param> /// <param name="chain">The certificate chain.</param>
/// <param name="sslPolicyErrors">Ssl policy errors</param> /// <param name="sslPolicyErrors">Ssl policy errors</param>
/// <returns>Return true if valid certificate.</returns> /// <returns>Return true if valid certificate.</returns>
internal bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, internal bool ValidateServerCertificate(object sender, SessionEventArgsBase sessionArgs, X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslPolicyErrors) SslPolicyErrors sslPolicyErrors)
{ {
// if user callback is registered then do it // if user callback is registered then do it
if (ServerCertificateValidationCallback != null) if (ServerCertificateValidationCallback != null)
{ {
var args = new CertificateValidationEventArgs(certificate, chain, sslPolicyErrors); var args = new CertificateValidationEventArgs(sessionArgs, certificate, chain, sslPolicyErrors);
// why is the sender null? // why is the sender null?
ServerCertificateValidationCallback.InvokeAsync(this, args, ExceptionFunc).Wait(); ServerCertificateValidationCallback.InvokeAsync(this, args, ExceptionFunc).Wait();
...@@ -43,12 +44,13 @@ namespace Titanium.Web.Proxy ...@@ -43,12 +44,13 @@ namespace Titanium.Web.Proxy
/// Call back to select client certificate used for mutual authentication /// Call back to select client certificate used for mutual authentication
/// </summary> /// </summary>
/// <param name="sender">The sender.</param> /// <param name="sender">The sender.</param>
/// <param name="sessionArgs">The http session.</param>
/// <param name="targetHost">The remote hostname.</param> /// <param name="targetHost">The remote hostname.</param>
/// <param name="localCertificates">Selected local certificates by SslStream.</param> /// <param name="localCertificates">Selected local certificates by SslStream.</param>
/// <param name="remoteCertificate">The remote certificate of server.</param> /// <param name="remoteCertificate">The remote certificate of server.</param>
/// <param name="acceptableIssuers">The acceptable issues for client certificate as listed by server.</param> /// <param name="acceptableIssuers">The acceptable issues for client certificate as listed by server.</param>
/// <returns></returns> /// <returns></returns>
internal X509Certificate? SelectClientCertificate(object sender, string targetHost, internal X509Certificate? SelectClientCertificate(object sender, SessionEventArgsBase sessionArgs, string targetHost,
X509CertificateCollection localCertificates, X509CertificateCollection localCertificates,
X509Certificate remoteCertificate, string[] acceptableIssuers) X509Certificate remoteCertificate, string[] acceptableIssuers)
{ {
...@@ -75,12 +77,8 @@ namespace Titanium.Web.Proxy ...@@ -75,12 +77,8 @@ namespace Titanium.Web.Proxy
// If user call back is registered // If user call back is registered
if (ClientCertificateSelectionCallback != null) if (ClientCertificateSelectionCallback != null)
{ {
var args = new CertificateSelectionEventArgs var args = new CertificateSelectionEventArgs(sessionArgs, targetHost, localCertificates, remoteCertificate, acceptableIssuers)
{ {
TargetHost = targetHost,
LocalCertificates = localCertificates,
RemoteCertificate = remoteCertificate,
AcceptableIssuers = acceptableIssuers,
ClientCertificate = clientCertificate ClientCertificate = clientCertificate
}; };
......
using System; using System;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Compression namespace Titanium.Web.Proxy.Compression
{ {
......
using System; using System;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Compression namespace Titanium.Web.Proxy.Compression
{ {
......
using System.IO.Compression; using System;
namespace Titanium.Web.Proxy.Compression namespace Titanium.Web.Proxy.Compression
{ {
......
using System; using System;
using System.Threading; using System.Threading;
using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
/// <summary> /// <summary>
/// This is used in transparent endpoint before authenticating client. /// This is used in transparent endpoint before authenticating client.
/// </summary> /// </summary>
public class BeforeSslAuthenticateEventArgs : EventArgs public class BeforeSslAuthenticateEventArgs : ProxyEventArgsBase
{ {
internal readonly CancellationTokenSource TaskCancellationSource; internal readonly CancellationTokenSource TaskCancellationSource;
internal BeforeSslAuthenticateEventArgs(CancellationTokenSource taskCancellationSource, string sniHostName) internal BeforeSslAuthenticateEventArgs(TcpClientConnection clientConnection, CancellationTokenSource taskCancellationSource, string sniHostName) : base(clientConnection)
{ {
TaskCancellationSource = taskCancellationSource; TaskCancellationSource = taskCancellationSource;
SniHostName = sniHostName; SniHostName = sniHostName;
......
...@@ -6,32 +6,42 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -6,32 +6,42 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// An argument passed on to user for client certificate selection during mutual SSL authentication. /// An argument passed on to user for client certificate selection during mutual SSL authentication.
/// </summary> /// </summary>
public class CertificateSelectionEventArgs : EventArgs public class CertificateSelectionEventArgs : ProxyEventArgsBase
{ {
/// <summary> public CertificateSelectionEventArgs(SessionEventArgsBase session, string targetHost,
/// The proxy server instance. X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) : base(session.ClientConnection)
/// </summary> {
public object? Sender { get; internal set; } Session = session;
TargetHost = targetHost;
LocalCertificates = localCertificates;
RemoteCertificate = remoteCertificate;
AcceptableIssuers = acceptableIssuers;
}
/// <value>
/// The session.
/// </value>
public SessionEventArgsBase Session { get; }
/// <summary> /// <summary>
/// The remote hostname to which we are authenticating against. /// The remote hostname to which we are authenticating against.
/// </summary> /// </summary>
public string? TargetHost { get; internal set; } public string TargetHost { get; }
/// <summary> /// <summary>
/// Local certificates in store with matching issuers requested by TargetHost website. /// Local certificates in store with matching issuers requested by TargetHost website.
/// </summary> /// </summary>
public X509CertificateCollection? LocalCertificates { get; internal set; } public X509CertificateCollection LocalCertificates { get; }
/// <summary> /// <summary>
/// Certificate of the remote server. /// Certificate of the remote server.
/// </summary> /// </summary>
public X509Certificate? RemoteCertificate { get; internal set; } public X509Certificate RemoteCertificate { get; }
/// <summary> /// <summary>
/// Acceptable issuers as listed by remote server. /// Acceptable issuers as listed by remote server.
/// </summary> /// </summary>
public string[]? AcceptableIssuers { get; internal set; } public string[] AcceptableIssuers { get; }
/// <summary> /// <summary>
/// Client Certificate we selected. Set this value to override. /// Client Certificate we selected. Set this value to override.
......
...@@ -8,15 +8,21 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -8,15 +8,21 @@ namespace Titanium.Web.Proxy.EventArguments
/// An argument passed on to the user for validating the server certificate /// An argument passed on to the user for validating the server certificate
/// during SSL authentication. /// during SSL authentication.
/// </summary> /// </summary>
public class CertificateValidationEventArgs : EventArgs public class CertificateValidationEventArgs : ProxyEventArgsBase
{ {
public CertificateValidationEventArgs(X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) public CertificateValidationEventArgs(SessionEventArgsBase session, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) : base(session.ClientConnection)
{ {
Session = session;
Certificate = certificate; Certificate = certificate;
Chain = chain; Chain = chain;
SslPolicyErrors = sslPolicyErrors; SslPolicyErrors = sslPolicyErrors;
} }
/// <value>
/// The session.
/// </value>
public SessionEventArgsBase Session { get; }
/// <summary> /// <summary>
/// Server certificate. /// Server certificate.
/// </summary> /// </summary>
......
using System; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
/// <summary> /// <summary>
/// Class that wraps the multipart sent request arguments. /// Class that wraps the multipart sent request arguments.
/// </summary> /// </summary>
public class MultipartRequestPartSentEventArgs : EventArgs public class MultipartRequestPartSentEventArgs : ProxyEventArgsBase
{ {
internal MultipartRequestPartSentEventArgs(string boundary, HeaderCollection headers) internal MultipartRequestPartSentEventArgs(SessionEventArgs session, string boundary, HeaderCollection headers) : base(session.ClientConnection)
{ {
Session = session;
Boundary = boundary; Boundary = boundary;
Headers = headers; Headers = headers;
} }
/// <value>
/// The session arguments.
/// </value>
public SessionEventArgs Session { get; }
/// <summary> /// <summary>
/// Boundary. /// Boundary.
/// </summary> /// </summary>
......
using System;
using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy.EventArguments
{
/// <summary>
/// The base event arguments
/// </summary>
/// <seealso cref="System.EventArgs" />
public abstract class ProxyEventArgsBase : EventArgs
{
private readonly TcpClientConnection clientConnection;
public object ClientUserData
{
get => clientConnection.ClientUserData;
set => clientConnection.ClientUserData = value;
}
internal ProxyEventArgsBase(TcpClientConnection clientConnection)
{
this.clientConnection = clientConnection;
}
}
}
...@@ -8,7 +8,6 @@ using Titanium.Web.Proxy.Helpers; ...@@ -8,7 +8,6 @@ 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.Tcp;
using Titanium.Web.Proxy.StreamExtended.Network; using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
...@@ -36,8 +35,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -36,8 +35,8 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Constructor to initialize the proxy /// Constructor to initialize the proxy
/// </summary> /// </summary>
internal SessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, TcpClientConnection clientConnection, HttpClientStream clientStream, ConnectRequest? connectRequest, CancellationTokenSource cancellationTokenSource) internal SessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, HttpClientStream clientStream, ConnectRequest? connectRequest, CancellationTokenSource cancellationTokenSource)
: base(server, endPoint, clientConnection, clientStream, connectRequest, new Request(), cancellationTokenSource) : base(server, endPoint, clientStream, connectRequest, new Request(), cancellationTokenSource)
{ {
} }
...@@ -127,7 +126,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -127,7 +126,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
try try
{ {
MultipartRequestPartSent?.Invoke(this, new MultipartRequestPartSentEventArgs(boundary.ToString(), headers)); MultipartRequestPartSent?.Invoke(this, new MultipartRequestPartSentEventArgs(this, boundary.ToString(), headers));
} }
catch (Exception ex) catch (Exception ex)
{ {
......
...@@ -5,7 +5,6 @@ using System.Threading; ...@@ -5,7 +5,6 @@ using System.Threading;
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; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended.BufferPool; using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network; using Titanium.Web.Proxy.StreamExtended.Network;
...@@ -18,7 +17,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -18,7 +17,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// A proxy session ends when client terminates connection to proxy /// A proxy session ends when client terminates connection to proxy
/// or when server terminates connection from proxy. /// or when server terminates connection from proxy.
/// </summary> /// </summary>
public abstract class SessionEventArgsBase : EventArgs, IDisposable public abstract class SessionEventArgsBase : ProxyEventArgsBase, IDisposable
{ {
private static bool isWindowsAuthenticationSupported => RunTime.IsWindows; private static bool isWindowsAuthenticationSupported => RunTime.IsWindows;
...@@ -29,7 +28,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -29,7 +28,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Holds a reference to client /// Holds a reference to client
/// </summary> /// </summary>
internal TcpClientConnection ClientConnection { get; } internal TcpClientConnection ClientConnection => ClientStream.Connection;
internal HttpClientStream ClientStream { get; } internal HttpClientStream ClientStream { get; }
...@@ -50,7 +49,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -50,7 +49,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class. /// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
/// </summary> /// </summary>
private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
TcpClientConnection clientConnection, HttpClientStream clientStream, ConnectRequest? connectRequest, Request request, CancellationTokenSource cancellationTokenSource) HttpClientStream clientStream, ConnectRequest? connectRequest, Request request, CancellationTokenSource cancellationTokenSource) : base(clientStream.Connection)
{ {
BufferPool = server.BufferPool; BufferPool = server.BufferPool;
ExceptionFunc = server.ExceptionFunc; ExceptionFunc = server.ExceptionFunc;
...@@ -58,9 +57,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -58,9 +57,8 @@ namespace Titanium.Web.Proxy.EventArguments
CancellationTokenSource = cancellationTokenSource; CancellationTokenSource = cancellationTokenSource;
ClientConnection = clientConnection;
ClientStream = clientStream; ClientStream = clientStream;
HttpClient = new HttpWebClient(connectRequest, request, new Lazy<int>(() => clientConnection.GetProcessId(endPoint))); HttpClient = new HttpWebClient(connectRequest, request, new Lazy<int>(() => clientStream.Connection.GetProcessId(endPoint)));
LocalEndPoint = endPoint; LocalEndPoint = endPoint;
EnableWinAuth = server.EnableWinAuth && isWindowsAuthenticationSupported; EnableWinAuth = server.EnableWinAuth && isWindowsAuthenticationSupported;
} }
......
...@@ -3,8 +3,6 @@ using System.Threading; ...@@ -3,8 +3,6 @@ using System.Threading;
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;
using Titanium.Web.Proxy.StreamExtended.Network; using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
...@@ -17,8 +15,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -17,8 +15,8 @@ namespace Titanium.Web.Proxy.EventArguments
private bool? isHttpsConnect; private bool? isHttpsConnect;
internal TunnelConnectSessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, ConnectRequest connectRequest, internal TunnelConnectSessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, ConnectRequest connectRequest,
TcpClientConnection clientConnection, HttpClientStream clientStream, CancellationTokenSource cancellationTokenSource) HttpClientStream clientStream, CancellationTokenSource cancellationTokenSource)
: base(server, endPoint, clientConnection, clientStream, connectRequest, connectRequest, cancellationTokenSource) : base(server, endPoint, clientStream, connectRequest, connectRequest, cancellationTokenSource)
{ {
} }
......
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.Security; using System.Net.Security;
...@@ -14,10 +13,8 @@ using Titanium.Web.Proxy.Helpers; ...@@ -14,10 +13,8 @@ using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http2; using Titanium.Web.Proxy.Http2;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended; using Titanium.Web.Proxy.StreamExtended;
using Titanium.Web.Proxy.StreamExtended.Network;
using SslExtensions = Titanium.Web.Proxy.Extensions.SslExtensions; using SslExtensions = Titanium.Web.Proxy.Extensions.SslExtensions;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
...@@ -36,7 +33,7 @@ namespace Titanium.Web.Proxy ...@@ -36,7 +33,7 @@ namespace Titanium.Web.Proxy
var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
var clientStream = new HttpClientStream(clientConnection.GetStream(), BufferPool); var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool);
Task<TcpServerConnection>? prefetchConnectionTask = null; Task<TcpServerConnection>? prefetchConnectionTask = null;
bool closeServerConnection = false; bool closeServerConnection = false;
...@@ -72,8 +69,7 @@ namespace Titanium.Web.Proxy ...@@ -72,8 +69,7 @@ namespace Titanium.Web.Proxy
await HeaderParser.ReadHeaders(clientStream, connectRequest.Headers, cancellationToken); await HeaderParser.ReadHeaders(clientStream, connectRequest.Headers, cancellationToken);
connectArgs = new TunnelConnectSessionEventArgs(this, endPoint, connectRequest, connectArgs = new TunnelConnectSessionEventArgs(this, endPoint, connectRequest, clientStream, cancellationTokenSource);
clientConnection, clientStream, cancellationTokenSource);
clientStream.DataRead += (o, args) => connectArgs.OnDataSent(args.Buffer, args.Offset, args.Count); clientStream.DataRead += (o, args) => connectArgs.OnDataSent(args.Buffer, args.Offset, args.Count);
clientStream.DataWrite += (o, args) => connectArgs.OnDataReceived(args.Buffer, args.Offset, args.Count); clientStream.DataWrite += (o, args) => connectArgs.OnDataReceived(args.Buffer, args.Offset, args.Count);
...@@ -137,7 +133,7 @@ namespace Titanium.Web.Proxy ...@@ -137,7 +133,7 @@ namespace Titanium.Web.Proxy
if (decryptSsl && clientHelloInfo != null) if (decryptSsl && clientHelloInfo != null)
{ {
connectRequest.IsHttps = true; // todo: move this line to the previous "if" connectRequest.IsHttps = true; // todo: move this line to the previous "if"
clientConnection.SslProtocol = clientHelloInfo.SslProtocol; clientStream.Connection.SslProtocol = clientHelloInfo.SslProtocol;
bool http2Supported = false; bool http2Supported = false;
...@@ -221,11 +217,11 @@ namespace Titanium.Web.Proxy ...@@ -221,11 +217,11 @@ namespace Titanium.Web.Proxy
await sslStream.AuthenticateAsServerAsync(options, cancellationToken); await sslStream.AuthenticateAsServerAsync(options, cancellationToken);
#if NETSTANDARD2_1 #if NETSTANDARD2_1
clientConnection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol; clientStream.Connection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol;
#endif #endif
// HTTPS server created - we can now decrypt the client's traffic // HTTPS server created - we can now decrypt the client's traffic
clientStream = new HttpClientStream(sslStream, BufferPool); clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool);
sslStream = null; // clientStream was created, no need to keep SSL stream reference sslStream = null; // clientStream was created, no need to keep SSL stream reference
clientStream.DataRead += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count); clientStream.DataRead += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count);
...@@ -362,13 +358,13 @@ namespace Titanium.Web.Proxy ...@@ -362,13 +358,13 @@ namespace Titanium.Web.Proxy
var connectionPreface = new ReadOnlyMemory<byte>(Http2Helper.ConnectionPreface); var connectionPreface = new ReadOnlyMemory<byte>(Http2Helper.ConnectionPreface);
await connection.Stream.WriteAsync(connectionPreface, cancellationToken); await connection.Stream.WriteAsync(connectionPreface, cancellationToken);
await Http2Helper.SendHttp2(clientStream, connection.Stream, await Http2Helper.SendHttp2(clientStream, connection.Stream,
() => new SessionEventArgs(this, endPoint, clientConnection, clientStream, connectArgs?.HttpClient.ConnectRequest, cancellationTokenSource) () => new SessionEventArgs(this, endPoint, clientStream, connectArgs?.HttpClient.ConnectRequest, cancellationTokenSource)
{ {
UserData = connectArgs?.UserData UserData = connectArgs?.UserData
}, },
async args => { await onBeforeRequest(args); }, async args => { await onBeforeRequest(args); },
async args => { await onBeforeResponse(args); }, async args => { await onBeforeResponse(args); },
connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc); connectArgs.CancellationTokenSource, clientStream.Connection.Id, ExceptionFunc);
#endif #endif
} }
finally finally
...@@ -381,7 +377,7 @@ namespace Titanium.Web.Proxy ...@@ -381,7 +377,7 @@ namespace Titanium.Web.Proxy
calledRequestHandler = true; calledRequestHandler = true;
// Now create the request // Now create the request
await handleHttpSessionRequest(endPoint, clientConnection, clientStream, cancellationTokenSource, connectArgs, prefetchConnectionTask); await handleHttpSessionRequest(endPoint, clientStream, cancellationTokenSource, connectArgs, prefetchConnectionTask);
} }
catch (ProxyException e) catch (ProxyException e)
{ {
......
using System; using System;
using System.Globalization; using System.Globalization;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
internal static class StringExtensions internal static class StringExtensions
{ {
internal static bool EqualsIgnoreCase(this string str, string value) internal static bool EqualsIgnoreCase(this string str, string? value)
{ {
return str.Equals(value, StringComparison.CurrentCultureIgnoreCase); return str.Equals(value, StringComparison.CurrentCultureIgnoreCase);
} }
...@@ -16,12 +15,12 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -16,12 +15,12 @@ namespace Titanium.Web.Proxy.Extensions
return str.Equals(value, StringComparison.CurrentCultureIgnoreCase); return str.Equals(value, StringComparison.CurrentCultureIgnoreCase);
} }
internal static bool ContainsIgnoreCase(this string str, string value) internal static bool ContainsIgnoreCase(this string str, string? value)
{ {
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(str, value, CompareOptions.IgnoreCase) >= 0; return CultureInfo.CurrentCulture.CompareInfo.IndexOf(str, value, CompareOptions.IgnoreCase) >= 0;
} }
internal static int IndexOfIgnoreCase(this string str, string value) internal static int IndexOfIgnoreCase(this string str, string? value)
{ {
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(str, value, CompareOptions.IgnoreCase); return CultureInfo.CurrentCulture.CompareInfo.IndexOf(str, value, CompareOptions.IgnoreCase);
} }
......
using System; using System;
using System.Text;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
......
...@@ -3,15 +3,19 @@ using System.IO; ...@@ -3,15 +3,19 @@ using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended.BufferPool; using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
internal sealed class HttpClientStream : HttpStream internal sealed class HttpClientStream : HttpStream
{ {
internal HttpClientStream(Stream stream, IBufferPool bufferPool) public TcpClientConnection Connection { get; }
internal HttpClientStream(TcpClientConnection connection, Stream stream, IBufferPool bufferPool)
: base(stream, bufferPool) : base(stream, bufferPool)
{ {
Connection = connection;
} }
/// <summary> /// <summary>
......
...@@ -6,7 +6,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -6,7 +6,7 @@ namespace Titanium.Web.Proxy.Helpers
internal partial class NativeMethods internal partial class NativeMethods
{ {
// Keeps it from getting garbage collected // Keeps it from getting garbage collected
internal static ConsoleEventDelegate Handler; internal static ConsoleEventDelegate? Handler;
[DllImport("wininet.dll")] [DllImport("wininet.dll")]
internal static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, internal static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer,
......
...@@ -211,12 +211,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -211,12 +211,7 @@ namespace Titanium.Web.Proxy.Helpers
if (protocolType.HasValue) if (protocolType.HasValue)
{ {
var endPointParts = tmp.Substring(equalsIndex + 1).Split(':'); var endPointParts = tmp.Substring(equalsIndex + 1).Split(':');
return new HttpSystemProxyValue return new HttpSystemProxyValue(endPointParts[0], int.Parse(endPointParts[1]), protocolType.Value);
{
HostName = endPointParts[0],
Port = int.Parse(endPointParts[1]),
ProtocolType = protocolType.Value
};
} }
} }
......
...@@ -9,11 +9,18 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -9,11 +9,18 @@ namespace Titanium.Web.Proxy.Helpers
{ {
internal class HttpSystemProxyValue internal class HttpSystemProxyValue
{ {
internal string HostName { get; set; } internal string HostName { get; }
internal int Port { get; set; } internal int Port { get; }
internal ProxyProtocolType ProtocolType { get; set; } internal ProxyProtocolType ProtocolType { get; }
public HttpSystemProxyValue(string hostName, int port, ProxyProtocolType protocolType)
{
HostName = hostName;
Port = port;
ProtocolType = protocolType;
}
public override string ToString() public override string ToString()
{ {
...@@ -56,7 +63,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -56,7 +63,7 @@ namespace Titanium.Web.Proxy.Helpers
AppDomain.CurrentDomain.ProcessExit += (o, args) => RestoreOriginalSettings(); AppDomain.CurrentDomain.ProcessExit += (o, args) => RestoreOriginalSettings();
if (Environment.UserInteractive && NativeMethods.GetConsoleWindow() != IntPtr.Zero) if (Environment.UserInteractive && NativeMethods.GetConsoleWindow() != IntPtr.Zero)
{ {
NativeMethods.Handler = eventType => var handler = new NativeMethods.ConsoleEventDelegate(eventType =>
{ {
if (eventType != 2) if (eventType != 2)
{ {
...@@ -65,10 +72,11 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -65,10 +72,11 @@ namespace Titanium.Web.Proxy.Helpers
RestoreOriginalSettings(); RestoreOriginalSettings();
return false; return false;
}; });
NativeMethods.Handler = handler;
// On Console exit make sure we also exit the proxy // On Console exit make sure we also exit the proxy
NativeMethods.SetConsoleCtrlHandler(NativeMethods.Handler, true); NativeMethods.SetConsoleCtrlHandler(handler, true);
} }
} }
...@@ -95,22 +103,12 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -95,22 +103,12 @@ namespace Titanium.Web.Proxy.Helpers
existingSystemProxyValues.RemoveAll(x => (protocolType & x.ProtocolType) != 0); existingSystemProxyValues.RemoveAll(x => (protocolType & x.ProtocolType) != 0);
if ((protocolType & ProxyProtocolType.Http) != 0) if ((protocolType & ProxyProtocolType.Http) != 0)
{ {
existingSystemProxyValues.Add(new HttpSystemProxyValue existingSystemProxyValues.Add(new HttpSystemProxyValue(hostname, port, ProxyProtocolType.Http));
{
HostName = hostname,
ProtocolType = ProxyProtocolType.Http,
Port = port
});
} }
if ((protocolType & ProxyProtocolType.Https) != 0) if ((protocolType & ProxyProtocolType.Https) != 0)
{ {
existingSystemProxyValues.Add(new HttpSystemProxyValue existingSystemProxyValues.Add(new HttpSystemProxyValue(hostname, port, ProxyProtocolType.Https));
{
HostName = hostname,
ProtocolType = ProxyProtocolType.Https,
Port = port
});
} }
reg.DeleteValue(regAutoConfigUrl, false); reg.DeleteValue(regAutoConfigUrl, false);
......
using System; using System;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.StreamExtended; using Titanium.Web.Proxy.StreamExtended;
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
using System.Buffers; using System.Buffers;
using System.IO; using System.IO;
using System.Text; using System.Text;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
......
...@@ -4,7 +4,6 @@ using System.Collections.Generic; ...@@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Linq; using System.Linq;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
......
using System; using System;
using System.IO;
using System.Net; using System.Net;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
......
...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.Http
return String.AsSpan().EqualsIgnoreCase(value); return String.AsSpan().EqualsIgnoreCase(value);
} }
internal bool Equals(string value) internal bool Equals(string? value)
{ {
return String.EqualsIgnoreCase(value); return String.EqualsIgnoreCase(value);
} }
......
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Text;
using Titanium.Web.Proxy.Exceptions; using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
......
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Text;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Text;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http2.Hpack namespace Titanium.Web.Proxy.Http2.Hpack
......
...@@ -141,7 +141,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -141,7 +141,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
} }
Size -= removed.Size; Size -= removed.Size;
headerFields[tail++] = null; headerFields[tail++] = null!;
if (tail == headerFields.Length) if (tail == headerFields.Length)
{ {
tail = 0; tail = 0;
...@@ -157,7 +157,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -157,7 +157,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
{ {
while (tail != head) while (tail != head)
{ {
headerFields[tail++] = null; headerFields[tail++] = null!;
if (tail == headerFields.Length) if (tail == headerFields.Length)
{ {
tail = 0; tail = 0;
......
 #if NETSTANDARD2_1
using Titanium.Web.Proxy.Extensions;
#if NETSTANDARD2_1
/* /*
* Copyright 2014 Twitter, Inc * Copyright 2014 Twitter, Inc
* This file is a derivative work modified by Ringo Leese * This file is a derivative work modified by Ringo Leese
...@@ -20,7 +17,6 @@ using Titanium.Web.Proxy.Extensions; ...@@ -20,7 +17,6 @@ using Titanium.Web.Proxy.Extensions;
*/ */
using System; using System;
using System.IO; using System.IO;
using System.Text;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http2.Hpack namespace Titanium.Web.Proxy.Http2.Hpack
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Text;
namespace Titanium.Web.Proxy.Http2.Hpack namespace Titanium.Web.Proxy.Http2.Hpack
{ {
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http2.Hpack namespace Titanium.Web.Proxy.Http2.Hpack
......
...@@ -3,7 +3,6 @@ using Titanium.Web.Proxy.Extensions; ...@@ -3,7 +3,6 @@ using Titanium.Web.Proxy.Extensions;
#if NETSTANDARD2_1 #if NETSTANDARD2_1
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Net; using System.Net;
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
using System.Net; using System.Net;
using System.Text; using System.Text;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Models namespace Titanium.Web.Proxy.Models
......
...@@ -16,6 +16,8 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -16,6 +16,8 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary> /// </summary>
internal class TcpClientConnection : IDisposable internal class TcpClientConnection : IDisposable
{ {
public object ClientUserData { get; set; }
internal TcpClientConnection(ProxyServer proxyServer, TcpClient tcpClient) internal TcpClientConnection(ProxyServer proxyServer, TcpClient tcpClient)
{ {
this.tcpClient = tcpClient; this.tcpClient = tcpClient;
......
...@@ -11,12 +11,10 @@ using System.Text; ...@@ -11,12 +11,10 @@ using System.Text;
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.Exceptions;
using Titanium.Web.Proxy.Extensions; 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.StreamExtended.Network;
namespace Titanium.Web.Proxy.Network.Tcp namespace Titanium.Web.Proxy.Network.Tcp
{ {
...@@ -139,14 +137,14 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -139,14 +137,14 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary> /// <summary>
/// Create a server connection. /// Create a server connection.
/// </summary> /// </summary>
/// <param name="server">The proxy server.</param> /// <param name="proxyServer">The proxy server.</param>
/// <param name="session">The session event arguments.</param> /// <param name="session">The session event arguments.</param>
/// <param name="isConnect">Is this a CONNECT request.</param> /// <param name="isConnect">Is this a CONNECT request.</param>
/// <param name="applicationProtocol"></param> /// <param name="applicationProtocol"></param>
/// <param name="noCache">if set to <c>true</c> [no cache].</param> /// <param name="noCache">if set to <c>true</c> [no cache].</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>
internal Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase session, bool isConnect, internal Task<TcpServerConnection> GetServerConnection(ProxyServer proxyServer, SessionEventArgsBase session, bool isConnect,
SslApplicationProtocol applicationProtocol, bool noCache, CancellationToken cancellationToken) SslApplicationProtocol applicationProtocol, bool noCache, CancellationToken cancellationToken)
{ {
List<SslApplicationProtocol>? applicationProtocols = null; List<SslApplicationProtocol>? applicationProtocols = null;
...@@ -155,28 +153,28 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -155,28 +153,28 @@ namespace Titanium.Web.Proxy.Network.Tcp
applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol }; applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol };
} }
return GetServerConnection(server, session, isConnect, applicationProtocols, noCache, cancellationToken); return GetServerConnection(proxyServer, session, isConnect, applicationProtocols, noCache, cancellationToken);
} }
/// <summary> /// <summary>
/// Create a server connection. /// Create a server connection.
/// </summary> /// </summary>
/// <param name="server">The proxy server.</param> /// <param name="proxyServer">The proxy server.</param>
/// <param name="session">The session event arguments.</param> /// <param name="session">The session event arguments.</param>
/// <param name="isConnect">Is this a CONNECT request.</param> /// <param name="isConnect">Is this a CONNECT request.</param>
/// <param name="applicationProtocols"></param> /// <param name="applicationProtocols"></param>
/// <param name="noCache">if set to <c>true</c> [no cache].</param> /// <param name="noCache">if set to <c>true</c> [no cache].</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>
internal async Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase session, bool isConnect, internal async Task<TcpServerConnection> GetServerConnection(ProxyServer proxyServer, SessionEventArgsBase session, bool isConnect,
List<SslApplicationProtocol>? applicationProtocols, bool noCache, CancellationToken cancellationToken) List<SslApplicationProtocol>? applicationProtocols, bool noCache, CancellationToken cancellationToken)
{ {
IExternalProxy? customUpStreamProxy = null; IExternalProxy? customUpStreamProxy = null;
bool isHttps = session.IsHttps; bool isHttps = session.IsHttps;
if (server.GetCustomUpStreamProxyFunc != null) if (proxyServer.GetCustomUpStreamProxyFunc != null)
{ {
customUpStreamProxy = await server.GetCustomUpStreamProxyFunc(session); customUpStreamProxy = await proxyServer.GetCustomUpStreamProxyFunc(session);
} }
session.CustomUpStreamProxyUsed = customUpStreamProxy; session.CustomUpStreamProxyUsed = customUpStreamProxy;
...@@ -207,37 +205,36 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -207,37 +205,36 @@ namespace Titanium.Web.Proxy.Network.Tcp
} }
return await GetServerConnection( return await GetServerConnection(
host, proxyServer, host, port,
port,
session.HttpClient.Request.HttpVersion, session.HttpClient.Request.HttpVersion,
isHttps, applicationProtocols, isConnect, isHttps, applicationProtocols, isConnect,
server, session, session.HttpClient.UpStreamEndPoint ?? server.UpStreamEndPoint, session, session.HttpClient.UpStreamEndPoint ?? proxyServer.UpStreamEndPoint,
customUpStreamProxy ?? (isHttps ? server.UpStreamHttpsProxy : server.UpStreamHttpProxy), customUpStreamProxy ?? (isHttps ? proxyServer.UpStreamHttpsProxy : proxyServer.UpStreamHttpProxy),
noCache, cancellationToken); noCache, cancellationToken);
} }
/// <summary> /// <summary>
/// Gets a TCP connection to server from connection pool. /// Gets a TCP connection to server from connection pool.
/// </summary> /// </summary>
/// <param name="proxyServer">The current ProxyServer instance.</param>
/// <param name="remoteHostName">The remote hostname.</param> /// <param name="remoteHostName">The remote hostname.</param>
/// <param name="remotePort">The remote port.</param> /// <param name="remotePort">The remote port.</param>
/// <param name="httpVersion">The http version to use.</param> /// <param name="httpVersion">The http version to use.</param>
/// <param name="isHttps">Is this a HTTPS request.</param> /// <param name="isHttps">Is this a HTTPS request.</param>
/// <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="sessionArgs">The session event arguments.</param>
/// <param name="session">The session.</param>
/// <param name="upStreamEndPoint">The local 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="noCache">Not from cache/create new connection.</param> /// <param name="noCache">Not from cache/create new connection.</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>
internal async Task<TcpServerConnection> GetServerConnection(string remoteHostName, int remotePort, internal async Task<TcpServerConnection> GetServerConnection(ProxyServer proxyServer, string remoteHostName, int remotePort,
Version httpVersion, bool isHttps, List<SslApplicationProtocol>? applicationProtocols, bool isConnect, Version httpVersion, bool isHttps, List<SslApplicationProtocol>? applicationProtocols, bool isConnect,
ProxyServer proxyServer, SessionEventArgsBase? session, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy, SessionEventArgsBase sessionArgs, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy,
bool noCache, CancellationToken cancellationToken) bool noCache, CancellationToken cancellationToken)
{ {
var sslProtocol = session?.ClientConnection.SslProtocol ?? SslProtocols.None; var sslProtocol = sessionArgs.ClientConnection.SslProtocol;
var cacheKey = GetConnectionCacheKey(remoteHostName, remotePort, var cacheKey = GetConnectionCacheKey(remoteHostName, remotePort,
isHttps, applicationProtocols, upStreamEndPoint, externalProxy); isHttps, applicationProtocols, upStreamEndPoint, externalProxy);
...@@ -264,7 +261,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -264,7 +261,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
} }
var connection = await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol, var connection = await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol,
applicationProtocols, isConnect, proxyServer, session, upStreamEndPoint, externalProxy, cacheKey, cancellationToken); applicationProtocols, isConnect, proxyServer, sessionArgs, upStreamEndPoint, externalProxy, cacheKey, cancellationToken);
return connection; return connection;
} }
...@@ -280,7 +277,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -280,7 +277,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="session">The http session.</param> /// <param name="sessionArgs">The http session.</param>
/// <param name="upStreamEndPoint">The local 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="cacheKey">The connection cache key</param> /// <param name="cacheKey">The connection cache key</param>
...@@ -288,7 +285,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -288,7 +285,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <returns></returns> /// <returns></returns>
private async Task<TcpServerConnection> createServerConnection(string remoteHostName, int remotePort, private async Task<TcpServerConnection> createServerConnection(string remoteHostName, int remotePort,
Version httpVersion, bool isHttps, SslProtocols sslProtocol, List<SslApplicationProtocol>? applicationProtocols, bool isConnect, Version httpVersion, bool isHttps, SslProtocols sslProtocol, List<SslApplicationProtocol>? applicationProtocols, bool isConnect,
ProxyServer proxyServer, SessionEventArgsBase? session, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy, string cacheKey, ProxyServer proxyServer, SessionEventArgsBase sessionArgs, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy, string cacheKey,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
// deny connection to proxy end points to avoid infinite connection loop. // deny connection to proxy end points to avoid infinite connection loop.
...@@ -346,14 +343,14 @@ retry: ...@@ -346,14 +343,14 @@ retry:
throw new Exception($"Could not resolve the hostname {hostname}"); throw new Exception($"Could not resolve the hostname {hostname}");
} }
if (session != null) if (sessionArgs != null)
{ {
session.TimeLine["Dns Resolved"] = DateTime.Now; sessionArgs.TimeLine["Dns Resolved"] = DateTime.Now;
} }
Array.Sort(ipAddresses, (x, y) => x.AddressFamily.CompareTo(y.AddressFamily)); Array.Sort(ipAddresses, (x, y) => x.AddressFamily.CompareTo(y.AddressFamily));
Exception lastException = null; Exception? lastException = null;
for (int i = 0; i < ipAddresses.Length; i++) for (int i = 0; i < ipAddresses.Length; i++)
{ {
try try
...@@ -427,26 +424,26 @@ retry: ...@@ -427,26 +424,26 @@ retry:
if (tcpClient == null) if (tcpClient == null)
{ {
if (session != null && proxyServer.CustomUpStreamProxyFailureFunc != null) if (sessionArgs != null && proxyServer.CustomUpStreamProxyFailureFunc != null)
{ {
var newUpstreamProxy = await proxyServer.CustomUpStreamProxyFailureFunc(session); var newUpstreamProxy = await proxyServer.CustomUpStreamProxyFailureFunc(sessionArgs);
if (newUpstreamProxy != null) if (newUpstreamProxy != null)
{ {
session.CustomUpStreamProxyUsed = newUpstreamProxy; sessionArgs.CustomUpStreamProxyUsed = newUpstreamProxy;
session.TimeLine["Retrying Upstream Proxy Connection"] = DateTime.Now; sessionArgs.TimeLine["Retrying Upstream Proxy Connection"] = DateTime.Now;
return await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol, applicationProtocols, isConnect, proxyServer, session, upStreamEndPoint, externalProxy, cacheKey, cancellationToken); return await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol, applicationProtocols, isConnect, proxyServer, sessionArgs, upStreamEndPoint, externalProxy, cacheKey, cancellationToken);
} }
} }
throw new Exception($"Could not establish connection to {hostname}", lastException); throw new Exception($"Could not establish connection to {hostname}", lastException);
} }
if (session != null) if (sessionArgs != null)
{ {
session.TimeLine["Connection Established"] = DateTime.Now; sessionArgs.TimeLine["Connection Established"] = DateTime.Now;
} }
await proxyServer.InvokeConnectionCreateEvent(tcpClient, false); await proxyServer.InvokeServerConnectionCreateEvent(tcpClient);
stream = new HttpServerStream(tcpClient.GetStream(), proxyServer.BufferPool); stream = new HttpServerStream(tcpClient.GetStream(), proxyServer.BufferPool);
...@@ -483,8 +480,13 @@ retry: ...@@ -483,8 +480,13 @@ retry:
if (isHttps) if (isHttps)
{ {
var sslStream = new SslStream(stream, false, proxyServer.ValidateServerCertificate, var sslStream = new SslStream(stream, false,
proxyServer.SelectClientCertificate); (sender, certificate, chain, sslPolicyErrors) =>
proxyServer.ValidateServerCertificate(sender, sessionArgs, certificate, chain,
sslPolicyErrors),
(sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) =>
proxyServer.SelectClientCertificate(sender, sessionArgs, targetHost, localCertificates,
remoteCertificate, acceptableIssuers));
stream = new HttpServerStream(sslStream, proxyServer.BufferPool); stream = new HttpServerStream(sslStream, proxyServer.BufferPool);
var options = new SslClientAuthenticationOptions var options = new SslClientAuthenticationOptions
...@@ -500,9 +502,9 @@ retry: ...@@ -500,9 +502,9 @@ retry:
negotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol; negotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol;
#endif #endif
if (session != null) if (sessionArgs != null)
{ {
session.TimeLine["HTTPS Established"] = DateTime.Now; sessionArgs.TimeLine["HTTPS Established"] = DateTime.Now;
} }
} }
} }
......
...@@ -6,7 +6,6 @@ using System.Threading.Tasks; ...@@ -6,7 +6,6 @@ using System.Threading.Tasks;
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.StreamExtended.Network;
namespace Titanium.Web.Proxy.Network.Tcp namespace Titanium.Web.Proxy.Network.Tcp
{ {
......
// http://pinvoke.net/default.aspx/secur32/InitializeSecurityContext.html // http://pinvoke.net/default.aspx/secur32/InitializeSecurityContext.html
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Principal; using System.Security.Principal;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
......
...@@ -4,7 +4,6 @@ using System.Text; ...@@ -4,7 +4,6 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions; using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
......
...@@ -15,7 +15,6 @@ using Titanium.Web.Proxy.Models; ...@@ -15,7 +15,6 @@ using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network; using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended.BufferPool; using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
...@@ -705,7 +704,7 @@ namespace Titanium.Web.Proxy ...@@ -705,7 +704,7 @@ namespace Titanium.Web.Proxy
throw new ArgumentNullException(nameof(endPoint)); throw new ArgumentNullException(nameof(endPoint));
} }
if (ProxyEndPoints.Contains(endPoint) == false) if (!ProxyEndPoints.Contains(endPoint))
{ {
throw new Exception("Cannot set endPoints not added to proxy as system proxy"); throw new Exception("Cannot set endPoints not added to proxy as system proxy");
} }
...@@ -739,7 +738,7 @@ namespace Titanium.Web.Proxy ...@@ -739,7 +738,7 @@ namespace Titanium.Web.Proxy
try try
{ {
// based on end point type call appropriate request handlers // based on end point type call appropriate request handlers
tcpClient = endPoint.Listener.EndAcceptTcpClient(asyn); tcpClient = endPoint.Listener!.EndAcceptTcpClient(asyn);
tcpClient.NoDelay = NoDelay; tcpClient.NoDelay = NoDelay;
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)
...@@ -763,7 +762,7 @@ namespace Titanium.Web.Proxy ...@@ -763,7 +762,7 @@ namespace Titanium.Web.Proxy
} }
// Get the listener that handles the client request. // Get the listener that handles the client request.
endPoint.Listener.BeginAcceptTcpClient(onAcceptConnection, endPoint); endPoint.Listener!.BeginAcceptTcpClient(onAcceptConnection, endPoint);
} }
...@@ -795,7 +794,7 @@ namespace Titanium.Web.Proxy ...@@ -795,7 +794,7 @@ namespace Titanium.Web.Proxy
tcpClient.LingerState = new LingerOption(true, TcpTimeWaitSeconds); tcpClient.LingerState = new LingerOption(true, TcpTimeWaitSeconds);
await InvokeConnectionCreateEvent(tcpClient, true); await InvokeClientConnectionCreateEvent(tcpClient);
using (var clientConnection = new TcpClientConnection(this, tcpClient)) using (var clientConnection = new TcpClientConnection(this, tcpClient))
{ {
...@@ -825,7 +824,7 @@ namespace Titanium.Web.Proxy ...@@ -825,7 +824,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
private void quitListen(ProxyEndPoint endPoint) private void quitListen(ProxyEndPoint endPoint)
{ {
endPoint.Listener.Stop(); endPoint.Listener!.Stop();
endPoint.Listener.Server.Dispose(); endPoint.Listener.Server.Dispose();
} }
...@@ -866,21 +865,28 @@ namespace Titanium.Web.Proxy ...@@ -866,21 +865,28 @@ namespace Titanium.Web.Proxy
} }
/// <summary> /// <summary>
/// Invoke client/server tcp connection events if subscribed by API user. /// Invoke client tcp connection events if subscribed by API user.
/// </summary> /// </summary>
/// <param name="client">The TcpClient object.</param> /// <param name="client">The TcpClient object.</param>
/// <param name="isClientConnection">Is this a client connection created event? If not then we would assume that its a server connection create event.</param>
/// <returns></returns> /// <returns></returns>
internal async Task InvokeConnectionCreateEvent(TcpClient client, bool isClientConnection) internal async Task InvokeClientConnectionCreateEvent(TcpClient client)
{ {
// client connection created // client connection created
if (isClientConnection && OnClientConnectionCreate != null) if (OnClientConnectionCreate != null)
{ {
await OnClientConnectionCreate.InvokeAsync(this, client, ExceptionFunc); await OnClientConnectionCreate.InvokeAsync(this, client, ExceptionFunc);
} }
}
/// <summary>
/// Invoke server tcp connection events if subscribed by API user.
/// </summary>
/// <param name="client">The TcpClient object.</param>
/// <returns></returns>
internal async Task InvokeServerConnectionCreateEvent(TcpClient client)
{
// server connection created // server connection created
if (!isClientConnection && OnServerConnectionCreate != null) if (OnServerConnectionCreate != null)
{ {
await OnServerConnectionCreate.InvokeAsync(this, client, ExceptionFunc); await OnServerConnectionCreate.InvokeAsync(this, client, ExceptionFunc);
} }
......
...@@ -14,7 +14,6 @@ using Titanium.Web.Proxy.Models; ...@@ -14,7 +14,6 @@ using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network; using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
...@@ -29,13 +28,12 @@ namespace Titanium.Web.Proxy ...@@ -29,13 +28,12 @@ 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="clientConnection">The client connection.</param>
/// <param name="clientStream">The client stream.</param> /// <param name="clientStream">The client stream.</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>
/// <param name="connectArgs">The Connect request if this is a HTTPS request from explicit endpoint.</param> /// <param name="connectArgs">The Connect request if this is a HTTPS request from explicit endpoint.</param>
/// <param name="prefetchConnectionTask">Prefetched server connection for current client using Connect/SNI headers.</param> /// <param name="prefetchConnectionTask">Prefetched server connection for current client using Connect/SNI headers.</param>
private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientConnection clientConnection, private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, HttpClientStream clientStream,
HttpClientStream clientStream, CancellationTokenSource cancellationTokenSource, TunnelConnectSessionEventArgs? connectArgs = null, CancellationTokenSource cancellationTokenSource, TunnelConnectSessionEventArgs? connectArgs = null,
Task<TcpServerConnection>? prefetchConnectionTask = null) Task<TcpServerConnection>? prefetchConnectionTask = null)
{ {
var connectRequest = connectArgs?.HttpClient.ConnectRequest; var connectRequest = connectArgs?.HttpClient.ConnectRequest;
...@@ -64,7 +62,7 @@ namespace Titanium.Web.Proxy ...@@ -64,7 +62,7 @@ namespace Titanium.Web.Proxy
return; return;
} }
var args = new SessionEventArgs(this, endPoint, clientConnection, clientStream, connectRequest, cancellationTokenSource) var args = new SessionEventArgs(this, endPoint, clientStream, connectRequest, cancellationTokenSource)
{ {
UserData = connectArgs?.UserData UserData = connectArgs?.UserData
}; };
...@@ -163,7 +161,7 @@ namespace Titanium.Web.Proxy ...@@ -163,7 +161,7 @@ namespace Titanium.Web.Proxy
// or when prefetch task has a unexpectedly different connection. // or when prefetch task has a unexpectedly different connection.
if (connection != null if (connection != null
&& (await tcpConnectionFactory.GetConnectionCacheKey(this, args, && (await tcpConnectionFactory.GetConnectionCacheKey(this, args,
clientConnection.NegotiatedApplicationProtocol) clientStream.Connection.NegotiatedApplicationProtocol)
!= connection.CacheKey)) != connection.CacheKey))
{ {
await tcpConnectionFactory.Release(connection); await tcpConnectionFactory.Release(connection);
...@@ -171,7 +169,7 @@ namespace Titanium.Web.Proxy ...@@ -171,7 +169,7 @@ namespace Titanium.Web.Proxy
} }
var result = await handleHttpSessionRequest(args, connection, var result = await handleHttpSessionRequest(args, connection,
clientConnection.NegotiatedApplicationProtocol, clientStream.Connection.NegotiatedApplicationProtocol,
cancellationToken, cancellationTokenSource); cancellationToken, cancellationTokenSource);
// update connection to latest used // update connection to latest used
......
...@@ -3,7 +3,6 @@ using System.Net; ...@@ -3,7 +3,6 @@ using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Network.WinAuth.Security; using Titanium.Web.Proxy.Network.WinAuth.Security;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
......
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.StreamExtended.Network namespace Titanium.Web.Proxy.StreamExtended.Network
{ {
......
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.StreamExtended.BufferPool; using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Models; using Titanium.Web.Proxy.StreamExtended.Models;
using Titanium.Web.Proxy.StreamExtended.Network; using Titanium.Web.Proxy.StreamExtended.Network;
......
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net.Security; using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
...@@ -12,10 +11,8 @@ using Titanium.Web.Proxy.Exceptions; ...@@ -12,10 +11,8 @@ using Titanium.Web.Proxy.Exceptions;
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;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended; using Titanium.Web.Proxy.StreamExtended;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
...@@ -33,7 +30,7 @@ namespace Titanium.Web.Proxy ...@@ -33,7 +30,7 @@ namespace Titanium.Web.Proxy
var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
var clientStream = new HttpClientStream(clientConnection.GetStream(), BufferPool); var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool);
SslStream? sslStream = null; SslStream? sslStream = null;
...@@ -41,13 +38,11 @@ namespace Titanium.Web.Proxy ...@@ -41,13 +38,11 @@ namespace Titanium.Web.Proxy
{ {
var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken); var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);
string? httpsHostName = null;
if (clientHelloInfo != null) if (clientHelloInfo != null)
{ {
httpsHostName = clientHelloInfo.GetServerName() ?? endPoint.GenericCertificateName; var httpsHostName = clientHelloInfo.GetServerName() ?? endPoint.GenericCertificateName;
var args = new BeforeSslAuthenticateEventArgs(cancellationTokenSource, httpsHostName); var args = new BeforeSslAuthenticateEventArgs(clientConnection, cancellationTokenSource, httpsHostName);
await endPoint.InvokeBeforeSslAuthenticate(this, args, ExceptionFunc); await endPoint.InvokeBeforeSslAuthenticate(this, args, ExceptionFunc);
...@@ -58,7 +53,7 @@ namespace Titanium.Web.Proxy ...@@ -58,7 +53,7 @@ namespace Titanium.Web.Proxy
if (endPoint.DecryptSsl && args.DecryptSsl) if (endPoint.DecryptSsl && args.DecryptSsl)
{ {
clientConnection.SslProtocol = clientHelloInfo.SslProtocol; clientStream.Connection.SslProtocol = clientHelloInfo.SslProtocol;
// do client authentication using certificate // do client authentication using certificate
X509Certificate2? certificate = null; X509Certificate2? certificate = null;
...@@ -74,14 +69,13 @@ namespace Titanium.Web.Proxy ...@@ -74,14 +69,13 @@ namespace Titanium.Web.Proxy
await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false); await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false);
// HTTPS server created - we can now decrypt the client's traffic // HTTPS server created - we can now decrypt the client's traffic
clientStream = new HttpClientStream(sslStream, BufferPool); clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool);
sslStream = null; // clientStream was created, no need to keep SSL stream reference sslStream = null; // clientStream was created, no need to keep SSL stream reference
} }
catch (Exception e) catch (Exception e)
{ {
var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false); var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
var session = new SessionEventArgs(this, endPoint, clientConnection, clientStream, null, var session = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource);
cancellationTokenSource);
throw new ProxyConnectException( throw new ProxyConnectException(
$"Couldn't authenticate host '{httpsHostName}' with certificate '{certName}'.", e, session); $"Couldn't authenticate host '{httpsHostName}' with certificate '{certName}'.", e, session);
} }
...@@ -89,9 +83,10 @@ namespace Titanium.Web.Proxy ...@@ -89,9 +83,10 @@ namespace Titanium.Web.Proxy
} }
else else
{ {
var connection = await tcpConnectionFactory.GetServerConnection(httpsHostName, endPoint.Port, var sessionArgs = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource);
var connection = await tcpConnectionFactory.GetServerConnection(this, httpsHostName, endPoint.Port,
HttpHeader.VersionUnknown, false, null, HttpHeader.VersionUnknown, false, null,
true, this, null, UpStreamEndPoint, true, sessionArgs, UpStreamEndPoint,
UpStreamHttpsProxy, true, cancellationToken); UpStreamHttpsProxy, true, cancellationToken);
try try
...@@ -131,7 +126,7 @@ namespace Titanium.Web.Proxy ...@@ -131,7 +126,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, clientConnection, clientStream, cancellationTokenSource); await handleHttpSessionRequest(endPoint, clientStream, cancellationTokenSource);
} }
catch (ProxyException e) catch (ProxyException e)
{ {
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Titanium.Web.Proxy.StreamExtended.BufferPool; using Titanium.Web.Proxy.StreamExtended.BufferPool;
......
...@@ -2,11 +2,9 @@ ...@@ -2,11 +2,9 @@
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.Exceptions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
......
using System; using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
......
using System.IO; using System.IO;
using System.Text; using System.Text;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.IntegrationTests.Helpers namespace Titanium.Web.Proxy.IntegrationTests.Helpers
{ {
......
using System; using System;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
......
using System; using System;
using System.Collections.Generic;
using System.Net; using System.Net;
using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network; using Titanium.Web.Proxy.Network;
......
using System; using System;
using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Text;
using Titanium.Web.Proxy.IntegrationTests.Helpers; using Titanium.Web.Proxy.IntegrationTests.Helpers;
using Titanium.Web.Proxy.IntegrationTests.Setup; using Titanium.Web.Proxy.IntegrationTests.Setup;
......
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