diff --git a/docs/api/Titanium.Web.Proxy.ProxyServer.html b/docs/api/Titanium.Web.Proxy.ProxyServer.html index 1b0a11ea9..986680694 100644 --- a/docs/api/Titanium.Web.Proxy.ProxyServer.html +++ b/docs/api/Titanium.Web.Proxy.ProxyServer.html @@ -1121,7 +1121,7 @@
Property Value
Improve this Doc - View Source + View Source

ThreadPoolWorkerThread

@@ -1248,7 +1248,7 @@

Methods Improve this Doc - View Source + View Source

AddEndPoint(ProxyEndPoint)

@@ -1282,7 +1282,7 @@
Parameters
Improve this Doc - View Source + View Source

DisableAllSystemProxies()

@@ -1298,7 +1298,7 @@
Declaration
Improve this Doc - View Source + View Source

DisableSystemHttpProxy()

@@ -1314,7 +1314,7 @@
Declaration
Improve this Doc - View Source + View Source

DisableSystemHttpsProxy()

@@ -1330,7 +1330,7 @@
Declaration
Improve this Doc - View Source + View Source

DisableSystemProxy(ProxyProtocolType)

@@ -1363,7 +1363,7 @@
Parameters
Improve this Doc - View Source + View Source

Dispose()

@@ -1378,7 +1378,7 @@
Declaration
Improve this Doc - View Source + View Source

Dispose(Boolean)

@@ -1410,7 +1410,7 @@
Parameters
Improve this Doc - View Source + View Source

Finalize()

@@ -1425,7 +1425,7 @@
Declaration
Improve this Doc - View Source + View Source

RemoveEndPoint(ProxyEndPoint)

@@ -1460,7 +1460,7 @@
Parameters
Improve this Doc - View Source + View Source

RestoreOriginalProxySettings()

@@ -1476,7 +1476,7 @@
Declaration
Improve this Doc - View Source + View Source

SetAsSystemHttpProxy(ExplicitProxyEndPoint)

@@ -1510,7 +1510,7 @@
Parameters
Improve this Doc - View Source + View Source

SetAsSystemHttpsProxy(ExplicitProxyEndPoint)

@@ -1544,7 +1544,7 @@
Parameters
Improve this Doc - View Source + View Source

SetAsSystemProxy(ExplicitProxyEndPoint, ProxyProtocolType)

@@ -1584,7 +1584,7 @@
Parameters
Improve this Doc - View Source + View Source

Start()

@@ -1600,7 +1600,7 @@
Declaration
Improve this Doc - View Source + View Source

Stop()

@@ -1618,7 +1618,7 @@

Events Improve this Doc - View Source + View Source

AfterResponse

Intercept after response event from server.

@@ -1678,7 +1678,7 @@
Event Type
Improve this Doc - View Source + View Source

BeforeResponse

Intercept response event from server.

@@ -1768,7 +1768,7 @@
Event Type
Improve this Doc - View Source + View Source

OnClientConnectionCreate

Customize TcpClient used for client connection upon create.

@@ -1798,7 +1798,7 @@
Event Type
Improve this Doc - View Source + View Source

OnServerConnectionCreate

Customize TcpClient used for server connection upon create.

diff --git a/docs/api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.html b/docs/api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.html index 4e2a4d0c7..8fd1727f1 100644 --- a/docs/api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.html +++ b/docs/api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.html @@ -110,18 +110,18 @@

Methods

| - Improve this Doc + Improve this Doc - View Source + View Source -

CopyBodyAsync(IHttpStreamWriter, Boolean, Int64, Action<Byte[], Int32, Int32>, CancellationToken)

+

CopyBodyAsync(IHttpStreamWriter, Boolean, Int64, Boolean, SessionEventArgs, CancellationToken)

Declaration
-
Task CopyBodyAsync(IHttpStreamWriter writer, bool isChunked, long contentLength, Action<byte[], int, int> onCopy, CancellationToken cancellationToken)
+
Task CopyBodyAsync(IHttpStreamWriter writer, bool isChunked, long contentLength, bool isRequest, SessionEventArgs args, CancellationToken cancellationToken)
Parameters
@@ -149,8 +149,13 @@
Parameters
- - + + + + + + + @@ -180,7 +185,7 @@
Returns
Improve this Doc - View Source + View Source

Read(Byte[], Int32, Int32)

@@ -237,7 +242,7 @@
Returns
Improve this Doc - View Source + View Source

ReadAsync(Byte[], Int32, Int32, CancellationToken)

@@ -305,7 +310,7 @@
Returns
Improve this Doc
  • - View Source + View Source
  • diff --git a/docs/api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.html b/docs/api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.html index fa38d2dfa..2b9a6371b 100644 --- a/docs/api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.html +++ b/docs/api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.html @@ -92,6 +92,38 @@
    Synt
    public interface IHttpStreamWriter
    +

    Properties +

    + + | + Improve this Doc + + + View Source + + +

    IsNetworkStream

    +
    +
    +
    Declaration
    +
    +
    bool IsNetworkStream { get; }
    +
    +
    Property Value
    +
    Action<Byte[], Int32, Int32>onCopyBooleanisRequest
    SessionEventArgsargs
    + + + + + + + + + + + + +
    TypeDescription
    Boolean

    Methods

    @@ -99,7 +131,7 @@

    Methods Improve this Doc - View Source + View Source

    Write(Byte[], Int32, Int32)

    @@ -141,7 +173,7 @@
    Parameters
    Improve this Doc
    - View Source + View Source

    WriteAsync(Byte[], Int32, Int32, CancellationToken)

    @@ -203,7 +235,7 @@
    Returns
    Improve this Doc - View Source + View Source

    WriteLineAsync(String, CancellationToken)

    @@ -255,7 +287,7 @@
    Returns
    Improve this Doc - View Source + View Source

    WriteLineAsync(CancellationToken)

    diff --git a/docs/index.json b/docs/index.json index 5b9581638..fc49c5949 100644 --- a/docs/index.json +++ b/docs/index.json @@ -362,12 +362,12 @@ "api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.html": { "href": "api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.html", "title": "Interface IHttpStreamReader | Titanium Web Proxy", - "keywords": "Interface IHttpStreamReader Inherited Members ILineStream.DataAvailable ILineStream.FillBufferAsync(CancellationToken) ILineStream.ReadByteFromBuffer() ILineStream.ReadLineAsync(CancellationToken) Namespace : Titanium.Web.Proxy.StreamExtended.Network Assembly : Titanium.Web.Proxy.dll Syntax public interface IHttpStreamReader : ILineStream Methods | Improve this Doc View Source CopyBodyAsync(IHttpStreamWriter, Boolean, Int64, Action, CancellationToken) Declaration Task CopyBodyAsync(IHttpStreamWriter writer, bool isChunked, long contentLength, Action onCopy, CancellationToken cancellationToken) Parameters Type Name Description IHttpStreamWriter writer Boolean isChunked Int64 contentLength Action < Byte [], Int32 , Int32 > onCopy CancellationToken cancellationToken Returns Type Description Task | Improve this Doc View Source Read(Byte[], Int32, Int32) Declaration int Read(byte[] buffer, int offset, int count) Parameters Type Name Description Byte [] buffer Int32 offset Int32 count Returns Type Description Int32 | Improve this Doc View Source ReadAsync(Byte[], Int32, Int32, CancellationToken) Declaration Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) Parameters Type Name Description Byte [] buffer Int32 offset Int32 count CancellationToken cancellationToken Returns Type Description Task < Int32 >" + "keywords": "Interface IHttpStreamReader Inherited Members ILineStream.DataAvailable ILineStream.FillBufferAsync(CancellationToken) ILineStream.ReadByteFromBuffer() ILineStream.ReadLineAsync(CancellationToken) Namespace : Titanium.Web.Proxy.StreamExtended.Network Assembly : Titanium.Web.Proxy.dll Syntax public interface IHttpStreamReader : ILineStream Methods | Improve this Doc View Source CopyBodyAsync(IHttpStreamWriter, Boolean, Int64, Boolean, SessionEventArgs, CancellationToken) Declaration Task CopyBodyAsync(IHttpStreamWriter writer, bool isChunked, long contentLength, bool isRequest, SessionEventArgs args, CancellationToken cancellationToken) Parameters Type Name Description IHttpStreamWriter writer Boolean isChunked Int64 contentLength Boolean isRequest SessionEventArgs args CancellationToken cancellationToken Returns Type Description Task | Improve this Doc View Source Read(Byte[], Int32, Int32) Declaration int Read(byte[] buffer, int offset, int count) Parameters Type Name Description Byte [] buffer Int32 offset Int32 count Returns Type Description Int32 | Improve this Doc View Source ReadAsync(Byte[], Int32, Int32, CancellationToken) Declaration Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) Parameters Type Name Description Byte [] buffer Int32 offset Int32 count CancellationToken cancellationToken Returns Type Description Task < Int32 >" }, "api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.html": { "href": "api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.html", "title": "Interface IHttpStreamWriter | Titanium Web Proxy", - "keywords": "Interface IHttpStreamWriter A concrete implementation of this interface is required when calling CopyStream. Namespace : Titanium.Web.Proxy.StreamExtended.Network Assembly : Titanium.Web.Proxy.dll Syntax public interface IHttpStreamWriter Methods | Improve this Doc View Source Write(Byte[], Int32, Int32) Declaration void Write(byte[] buffer, int offset, int count) Parameters Type Name Description Byte [] buffer Int32 offset Int32 count | Improve this Doc View Source WriteAsync(Byte[], Int32, Int32, CancellationToken) Declaration Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) Parameters Type Name Description Byte [] buffer Int32 offset Int32 count CancellationToken cancellationToken Returns Type Description Task | Improve this Doc View Source WriteLineAsync(String, CancellationToken) Declaration ValueTask WriteLineAsync(string value, CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description String value CancellationToken cancellationToken Returns Type Description ValueTask | Improve this Doc View Source WriteLineAsync(CancellationToken) Declaration ValueTask WriteLineAsync(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Returns Type Description ValueTask" + "keywords": "Interface IHttpStreamWriter A concrete implementation of this interface is required when calling CopyStream. Namespace : Titanium.Web.Proxy.StreamExtended.Network Assembly : Titanium.Web.Proxy.dll Syntax public interface IHttpStreamWriter Properties | Improve this Doc View Source IsNetworkStream Declaration bool IsNetworkStream { get; } Property Value Type Description Boolean Methods | Improve this Doc View Source Write(Byte[], Int32, Int32) Declaration void Write(byte[] buffer, int offset, int count) Parameters Type Name Description Byte [] buffer Int32 offset Int32 count | Improve this Doc View Source WriteAsync(Byte[], Int32, Int32, CancellationToken) Declaration Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) Parameters Type Name Description Byte [] buffer Int32 offset Int32 count CancellationToken cancellationToken Returns Type Description Task | Improve this Doc View Source WriteLineAsync(String, CancellationToken) Declaration ValueTask WriteLineAsync(string value, CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description String value CancellationToken cancellationToken Returns Type Description ValueTask | Improve this Doc View Source WriteLineAsync(CancellationToken) Declaration ValueTask WriteLineAsync(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Returns Type Description ValueTask" }, "api/Titanium.Web.Proxy.StreamExtended.Network.ILineStream.html": { "href": "api/Titanium.Web.Proxy.StreamExtended.Network.ILineStream.html", diff --git a/docs/xrefmap.yml b/docs/xrefmap.yml index 0d05fd084..2ce3ccc1e 100644 --- a/docs/xrefmap.yml +++ b/docs/xrefmap.yml @@ -5054,15 +5054,12 @@ references: commentId: T:Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader fullName: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader nameWithType: IHttpStreamReader -- uid: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.CopyBodyAsync(Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter,System.Boolean,System.Int64,System.Action{System.Byte[],System.Int32,System.Int32},System.Threading.CancellationToken) - name: CopyBodyAsync(IHttpStreamWriter, Boolean, Int64, Action, CancellationToken) - href: api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.html#Titanium_Web_Proxy_StreamExtended_Network_IHttpStreamReader_CopyBodyAsync_Titanium_Web_Proxy_StreamExtended_Network_IHttpStreamWriter_System_Boolean_System_Int64_System_Action_System_Byte___System_Int32_System_Int32__System_Threading_CancellationToken_ - commentId: M:Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.CopyBodyAsync(Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter,System.Boolean,System.Int64,System.Action{System.Byte[],System.Int32,System.Int32},System.Threading.CancellationToken) - name.vb: CopyBodyAsync(IHttpStreamWriter, Boolean, Int64, Action(Of Byte(), Int32, Int32), CancellationToken) - fullName: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.CopyBodyAsync(Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter, System.Boolean, System.Int64, System.Action, System.Threading.CancellationToken) - fullName.vb: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.CopyBodyAsync(Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter, System.Boolean, System.Int64, System.Action(Of System.Byte(), System.Int32, System.Int32), System.Threading.CancellationToken) - nameWithType: IHttpStreamReader.CopyBodyAsync(IHttpStreamWriter, Boolean, Int64, Action, CancellationToken) - nameWithType.vb: IHttpStreamReader.CopyBodyAsync(IHttpStreamWriter, Boolean, Int64, Action(Of Byte(), Int32, Int32), CancellationToken) +- uid: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.CopyBodyAsync(Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter,System.Boolean,System.Int64,System.Boolean,Titanium.Web.Proxy.EventArguments.SessionEventArgs,System.Threading.CancellationToken) + name: CopyBodyAsync(IHttpStreamWriter, Boolean, Int64, Boolean, SessionEventArgs, CancellationToken) + href: api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.html#Titanium_Web_Proxy_StreamExtended_Network_IHttpStreamReader_CopyBodyAsync_Titanium_Web_Proxy_StreamExtended_Network_IHttpStreamWriter_System_Boolean_System_Int64_System_Boolean_Titanium_Web_Proxy_EventArguments_SessionEventArgs_System_Threading_CancellationToken_ + commentId: M:Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.CopyBodyAsync(Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter,System.Boolean,System.Int64,System.Boolean,Titanium.Web.Proxy.EventArguments.SessionEventArgs,System.Threading.CancellationToken) + fullName: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.CopyBodyAsync(Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter, System.Boolean, System.Int64, System.Boolean, Titanium.Web.Proxy.EventArguments.SessionEventArgs, System.Threading.CancellationToken) + nameWithType: IHttpStreamReader.CopyBodyAsync(IHttpStreamWriter, Boolean, Int64, Boolean, SessionEventArgs, CancellationToken) - uid: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.CopyBodyAsync* name: CopyBodyAsync href: api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamReader.html#Titanium_Web_Proxy_StreamExtended_Network_IHttpStreamReader_CopyBodyAsync_ @@ -5108,6 +5105,19 @@ references: commentId: T:Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter fullName: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter nameWithType: IHttpStreamWriter +- uid: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.IsNetworkStream + name: IsNetworkStream + href: api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.html#Titanium_Web_Proxy_StreamExtended_Network_IHttpStreamWriter_IsNetworkStream + commentId: P:Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.IsNetworkStream + fullName: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.IsNetworkStream + nameWithType: IHttpStreamWriter.IsNetworkStream +- uid: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.IsNetworkStream* + name: IsNetworkStream + href: api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.html#Titanium_Web_Proxy_StreamExtended_Network_IHttpStreamWriter_IsNetworkStream_ + commentId: Overload:Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.IsNetworkStream + isSpec: "True" + fullName: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.IsNetworkStream + nameWithType: IHttpStreamWriter.IsNetworkStream - uid: Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.Write(System.Byte[],System.Int32,System.Int32) name: Write(Byte[], Int32, Int32) href: api/Titanium.Web.Proxy.StreamExtended.Network.IHttpStreamWriter.html#Titanium_Web_Proxy_StreamExtended_Network_IHttpStreamWriter_Write_System_Byte___System_Int32_System_Int32_ diff --git a/src/Titanium.Web.Proxy/EventArguments/BeforeBodyWriteEventArgs.cs b/src/Titanium.Web.Proxy/EventArguments/BeforeBodyWriteEventArgs.cs new file mode 100644 index 000000000..e0788e934 --- /dev/null +++ b/src/Titanium.Web.Proxy/EventArguments/BeforeBodyWriteEventArgs.cs @@ -0,0 +1,46 @@ +#if DEBUG +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Titanium.Web.Proxy.EventArguments +{ + + public class BeforeBodyWriteEventArgs : ProxyEventArgsBase + { + internal BeforeBodyWriteEventArgs(SessionEventArgs session, byte[] bodyBytes, bool isChunked, bool isLastChunk) : base(session.Server, session.ClientConnection) + { + Session = session; + BodyBytes = bodyBytes; + IsChunked = isChunked; + IsLastChunk = isLastChunk; + } + + + /// + /// The session arguments. + /// + public SessionEventArgs Session { get; } + + /// + /// Indicates whether body is written chunked stream. + /// If this is true, BeforeRequestBodySend or BeforeResponseBodySend will be called until IsLastChunk is false. + /// + public bool IsChunked { get; } + + /// + /// Indicates if this is the last chunk from client or server stream, when request is chunked. + /// Override this property to true if there are more bytes to write. + /// + public bool IsLastChunk { get; set; } + + /// + /// The bytes about to be written. If IsChunked is true, this will be a chunk of the bytes to be written. + /// Override this property with custom bytes if needed, and adjust IsLastChunk accordingly. + /// + public byte[] BodyBytes { get; set; } + } +} +#endif diff --git a/src/Titanium.Web.Proxy/EventArguments/BeforeSslAuthenticateEventArgs.cs b/src/Titanium.Web.Proxy/EventArguments/BeforeSslAuthenticateEventArgs.cs index 3482061db..1e752d1c7 100644 --- a/src/Titanium.Web.Proxy/EventArguments/BeforeSslAuthenticateEventArgs.cs +++ b/src/Titanium.Web.Proxy/EventArguments/BeforeSslAuthenticateEventArgs.cs @@ -10,7 +10,7 @@ public class BeforeSslAuthenticateEventArgs : ProxyEventArgsBase { internal readonly CancellationTokenSource TaskCancellationSource; - internal BeforeSslAuthenticateEventArgs(TcpClientConnection clientConnection, CancellationTokenSource taskCancellationSource, string sniHostName) : base(clientConnection) + internal BeforeSslAuthenticateEventArgs(ProxyServer server, TcpClientConnection clientConnection, CancellationTokenSource taskCancellationSource, string sniHostName) : base(server, clientConnection) { TaskCancellationSource = taskCancellationSource; SniHostName = sniHostName; diff --git a/src/Titanium.Web.Proxy/EventArguments/CertificateSelectionEventArgs.cs b/src/Titanium.Web.Proxy/EventArguments/CertificateSelectionEventArgs.cs index 3da92e710..47dc0023c 100644 --- a/src/Titanium.Web.Proxy/EventArguments/CertificateSelectionEventArgs.cs +++ b/src/Titanium.Web.Proxy/EventArguments/CertificateSelectionEventArgs.cs @@ -8,7 +8,7 @@ namespace Titanium.Web.Proxy.EventArguments public class CertificateSelectionEventArgs : ProxyEventArgsBase { public CertificateSelectionEventArgs(SessionEventArgsBase session, string targetHost, - X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) : base(session.ClientConnection) + X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) : base(session.Server, session.ClientConnection) { Session = session; TargetHost = targetHost; diff --git a/src/Titanium.Web.Proxy/EventArguments/CertificateValidationEventArgs.cs b/src/Titanium.Web.Proxy/EventArguments/CertificateValidationEventArgs.cs index 50d2a7d53..064eb4d7c 100644 --- a/src/Titanium.Web.Proxy/EventArguments/CertificateValidationEventArgs.cs +++ b/src/Titanium.Web.Proxy/EventArguments/CertificateValidationEventArgs.cs @@ -9,7 +9,7 @@ namespace Titanium.Web.Proxy.EventArguments /// public class CertificateValidationEventArgs : ProxyEventArgsBase { - public CertificateValidationEventArgs(SessionEventArgsBase session, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) : base(session.ClientConnection) + public CertificateValidationEventArgs(SessionEventArgsBase session, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) : base(session.Server, session.ClientConnection) { Session = session; Certificate = certificate; diff --git a/src/Titanium.Web.Proxy/EventArguments/EmptyProxyEventArgs.cs b/src/Titanium.Web.Proxy/EventArguments/EmptyProxyEventArgs.cs index 364c61285..67f6bf295 100644 --- a/src/Titanium.Web.Proxy/EventArguments/EmptyProxyEventArgs.cs +++ b/src/Titanium.Web.Proxy/EventArguments/EmptyProxyEventArgs.cs @@ -4,7 +4,7 @@ namespace Titanium.Web.Proxy.EventArguments { public class EmptyProxyEventArgs : ProxyEventArgsBase { - internal EmptyProxyEventArgs(TcpClientConnection clientConnection) : base(clientConnection) + internal EmptyProxyEventArgs(ProxyServer server, TcpClientConnection clientConnection) : base(server, clientConnection) { } } diff --git a/src/Titanium.Web.Proxy/EventArguments/MultipartRequestPartSentEventArgs.cs b/src/Titanium.Web.Proxy/EventArguments/MultipartRequestPartSentEventArgs.cs index 22d4ead8a..bd8b174e6 100644 --- a/src/Titanium.Web.Proxy/EventArguments/MultipartRequestPartSentEventArgs.cs +++ b/src/Titanium.Web.Proxy/EventArguments/MultipartRequestPartSentEventArgs.cs @@ -7,7 +7,7 @@ namespace Titanium.Web.Proxy.EventArguments /// public class MultipartRequestPartSentEventArgs : ProxyEventArgsBase { - internal MultipartRequestPartSentEventArgs(SessionEventArgs session, string boundary, HeaderCollection headers) : base(session.ClientConnection) + internal MultipartRequestPartSentEventArgs(SessionEventArgs session, string boundary, HeaderCollection headers) : base(session.Server, session.ClientConnection) { Session = session; Boundary = boundary; diff --git a/src/Titanium.Web.Proxy/EventArguments/ProxyEventArgsBase.cs b/src/Titanium.Web.Proxy/EventArguments/ProxyEventArgsBase.cs index f115896f1..42bad2d4c 100644 --- a/src/Titanium.Web.Proxy/EventArguments/ProxyEventArgsBase.cs +++ b/src/Titanium.Web.Proxy/EventArguments/ProxyEventArgsBase.cs @@ -10,16 +10,17 @@ namespace Titanium.Web.Proxy.EventArguments public abstract class ProxyEventArgsBase : EventArgs { private readonly TcpClientConnection clientConnection; - + internal readonly ProxyServer Server; public object ClientUserData { get => clientConnection.ClientUserData; set => clientConnection.ClientUserData = value; } - internal ProxyEventArgsBase(TcpClientConnection clientConnection) + internal ProxyEventArgsBase(ProxyServer server, TcpClientConnection clientConnection) { this.clientConnection = clientConnection; + this.Server = server; } } } diff --git a/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs b/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs index 7a47e6fdc..f13ba0453 100644 --- a/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs +++ b/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs @@ -197,7 +197,7 @@ private async Task readResponseBodyAsync(CancellationToken cancellationToken) private async Task readBodyAsync(bool isRequest, CancellationToken cancellationToken) { using var bodyStream = new MemoryStream(); - using var writer = new HttpStream(bodyStream, BufferPool, cancellationToken); + using var writer = new HttpStream(Server, bodyStream, BufferPool, cancellationToken); if (isRequest) { @@ -228,7 +228,7 @@ internal async Task SyphonOutBodyAsync(bool isRequest, CancellationToken cancell var reader = isRequest ? (HttpStream)ClientStream : HttpClient.Connection.Stream; - await reader.CopyBodyAsync(requestResponse, true, NullWriter.Instance, TransformationMode.None, null, cancellationToken); + await reader.CopyBodyAsync(requestResponse, true, NullWriter.Instance, TransformationMode.None, isRequest, this, cancellationToken); } /// @@ -270,13 +270,13 @@ internal async Task CopyRequestBodyAsync(IHttpStreamWriter writer, Transformatio } else { - await reader.CopyBodyAsync(request, false, writer, transformation, OnDataSent, cancellationToken); + await reader.CopyBodyAsync(request, false, writer, transformation, true, this, cancellationToken); } } private async Task copyResponseBodyAsync(IHttpStreamWriter writer, TransformationMode transformation, CancellationToken cancellationToken) { - await HttpClient.Connection.Stream.CopyBodyAsync(HttpClient.Response, false, writer, transformation, OnDataReceived, cancellationToken); + await HttpClient.Connection.Stream.CopyBodyAsync(HttpClient.Response, false, writer, transformation, false, this, cancellationToken); } /// diff --git a/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs b/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs index 33f65c846..8828999c8 100644 --- a/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs +++ b/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs @@ -49,7 +49,7 @@ public abstract class SessionEventArgsBase : ProxyEventArgsBase, IDisposable /// Initializes a new instance of the class. /// private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, - HttpClientStream clientStream, ConnectRequest? connectRequest, Request request, CancellationTokenSource cancellationTokenSource) : base(clientStream.Connection) + HttpClientStream clientStream, ConnectRequest? connectRequest, Request request, CancellationTokenSource cancellationTokenSource) : base(server, clientStream.Connection) { BufferPool = server.BufferPool; ExceptionFunc = server.ExceptionFunc; diff --git a/src/Titanium.Web.Proxy/ExplicitClientHandler.cs b/src/Titanium.Web.Proxy/ExplicitClientHandler.cs index fb58a6c47..b40e80e2f 100644 --- a/src/Titanium.Web.Proxy/ExplicitClientHandler.cs +++ b/src/Titanium.Web.Proxy/ExplicitClientHandler.cs @@ -33,7 +33,7 @@ private async Task handleClient(ExplicitProxyEndPoint endPoint, TcpClientConnect var cancellationTokenSource = new CancellationTokenSource(); var cancellationToken = cancellationTokenSource.Token; - var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken); + var clientStream = new HttpClientStream(this, clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken); Task? prefetchConnectionTask = null; bool closeServerConnection = false; @@ -211,7 +211,7 @@ private async Task handleClient(ExplicitProxyEndPoint endPoint, TcpClientConnect #endif // HTTPS server created - we can now decrypt the client's traffic - clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool, cancellationToken); + clientStream = new HttpClientStream(this, clientStream.Connection, sslStream, BufferPool, cancellationToken); sslStream = null; // clientStream was created, no need to keep SSL stream reference clientStream.DataRead += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count); diff --git a/src/Titanium.Web.Proxy/Helpers/HttpClientStream.cs b/src/Titanium.Web.Proxy/Helpers/HttpClientStream.cs index 7a13157e8..57dc88d0a 100644 --- a/src/Titanium.Web.Proxy/Helpers/HttpClientStream.cs +++ b/src/Titanium.Web.Proxy/Helpers/HttpClientStream.cs @@ -11,8 +11,8 @@ internal sealed class HttpClientStream : HttpStream { public TcpClientConnection Connection { get; } - internal HttpClientStream(TcpClientConnection connection, Stream stream, IBufferPool bufferPool, CancellationToken cancellationToken) - : base(stream, bufferPool, cancellationToken) + internal HttpClientStream(ProxyServer server, TcpClientConnection connection, Stream stream, IBufferPool bufferPool, CancellationToken cancellationToken) + : base(server, stream, bufferPool, cancellationToken) { Connection = connection; } diff --git a/src/Titanium.Web.Proxy/Helpers/HttpServerStream.cs b/src/Titanium.Web.Proxy/Helpers/HttpServerStream.cs index 8376f19fe..5b95e9c1c 100644 --- a/src/Titanium.Web.Proxy/Helpers/HttpServerStream.cs +++ b/src/Titanium.Web.Proxy/Helpers/HttpServerStream.cs @@ -10,8 +10,8 @@ namespace Titanium.Web.Proxy.Helpers { internal sealed class HttpServerStream : HttpStream { - internal HttpServerStream(Stream stream, IBufferPool bufferPool, CancellationToken cancellationToken) - : base(stream, bufferPool, cancellationToken) + internal HttpServerStream(ProxyServer server, Stream stream, IBufferPool bufferPool, CancellationToken cancellationToken) + : base(server, stream, bufferPool, cancellationToken) { } diff --git a/src/Titanium.Web.Proxy/Helpers/HttpStream.cs b/src/Titanium.Web.Proxy/Helpers/HttpStream.cs index 06c7aa844..3f4e2f75b 100644 --- a/src/Titanium.Web.Proxy/Helpers/HttpStream.cs +++ b/src/Titanium.Web.Proxy/Helpers/HttpStream.cs @@ -41,6 +41,8 @@ internal class HttpStream : Stream, IHttpStreamWriter, IHttpStreamReader, IPeekS private readonly IBufferPool bufferPool; private readonly CancellationToken cancellationToken; + public bool IsNetworkStream => isNetworkStream; + public event EventHandler? DataRead; public event EventHandler? DataWrite; @@ -68,7 +70,7 @@ static HttpStream() } private static readonly byte[] newLine = ProxyConstants.NewLineBytes; - + private readonly ProxyServer server; /// /// Initializes a new instance of the class. /// @@ -76,8 +78,10 @@ static HttpStream() /// Bufferpool. /// The cancellation token. /// to leave the stream open after disposing the object; otherwise, . - internal HttpStream(Stream baseStream, IBufferPool bufferPool, CancellationToken cancellationToken, bool leaveOpen = false) + internal HttpStream(ProxyServer server, Stream baseStream, IBufferPool bufferPool, CancellationToken cancellationToken, bool leaveOpen = false) { + this.server = server; + if (baseStream is NetworkStream) { isNetworkStream = true; @@ -1001,14 +1005,14 @@ internal ValueTask WriteBodyAsync(byte[] data, bool isChunked, CancellationToken return WriteAsync(data, cancellationToken: cancellationToken); } - public async Task CopyBodyAsync(RequestResponseBase requestResponse, bool useOriginalHeaderValues, IHttpStreamWriter writer, TransformationMode transformation, Action? onCopy, CancellationToken cancellationToken) + public async Task CopyBodyAsync(RequestResponseBase requestResponse, bool useOriginalHeaderValues, IHttpStreamWriter writer, TransformationMode transformation, bool isRequest, SessionEventArgs args, CancellationToken cancellationToken) { bool isChunked = useOriginalHeaderValues ? requestResponse.OriginalIsChunked : requestResponse.IsChunked; long contentLength = useOriginalHeaderValues ? requestResponse.OriginalContentLength : requestResponse.ContentLength; if (transformation == TransformationMode.None) { - await CopyBodyAsync(writer, isChunked, contentLength, onCopy, cancellationToken); + await CopyBodyAsync(writer, isChunked, contentLength, isRequest, args, cancellationToken); return; } @@ -1026,8 +1030,8 @@ public async Task CopyBodyAsync(RequestResponseBase requestResponse, bool useOri try { - var http = new HttpStream(s, bufferPool, cancellationToken, true); - await http.CopyBodyAsync(writer, false, -1, onCopy, cancellationToken); + var http = new HttpStream(server, s, bufferPool, cancellationToken, true); + await http.CopyBodyAsync(writer, false, -1, isRequest, args, cancellationToken); } finally { @@ -1049,12 +1053,24 @@ public async Task CopyBodyAsync(RequestResponseBase requestResponse, bool useOri /// /// public Task CopyBodyAsync(IHttpStreamWriter writer, bool isChunked, long contentLength, - Action? onCopy, CancellationToken cancellationToken) + bool isRequest, + SessionEventArgs args, CancellationToken cancellationToken) { + +#if DEBUG + var isResponse = !isRequest; + + if (isNetworkStream && writer.IsNetworkStream && + (isRequest && args.HttpClient.Request.OriginalHasBody && !args.HttpClient.Request.IsBodyRead && server.ShouldCallBeforeRequestBodyWrite()) || + (isResponse && args.HttpClient.Response.OriginalHasBody && !args.HttpClient.Response.IsBodyRead && server.ShouldCallBeforeResponseBodyWrite())) + { + return handleBodyWrite(writer, isChunked, contentLength, isRequest, args, cancellationToken); + } +#endif // For chunked request we need to read data as they arrive, until we reach a chunk end symbol if (isChunked) { - return copyBodyChunkedAsync(writer, onCopy, cancellationToken); + return copyBodyChunkedAsync(writer, isRequest, args, cancellationToken); } // http 1.0 or the stream reader limits the stream @@ -1064,7 +1080,27 @@ public Task CopyBodyAsync(IHttpStreamWriter writer, bool isChunked, long content } // If not chunked then its easy just read the amount of bytes mentioned in content length header - return copyBytesToStream(writer, contentLength, onCopy, cancellationToken); + return copyBytesToStream(writer, contentLength, isRequest, args, cancellationToken); + } + + private Task handleBodyWrite(IHttpStreamWriter writer, bool isChunked, long contentLength, + bool isRequest, SessionEventArgs args, CancellationToken cancellationToken) + { + var originalContentLength = isRequest ? args.HttpClient.Request.OriginalContentLength : args.HttpClient.Response.OriginalContentLength; + var originalIsChunked = isRequest ? args.HttpClient.Request.OriginalIsChunked : args.HttpClient.Response.OriginalIsChunked; + + //TODO + //create a new decompression stream to wrap this source HttpStream based on original content encoding if needed. + //create a new compression stream to wrap target writer stream based on content encoding if needed. + + //1. Begin while(true) loop + //2. Parse chunk if chunked, and read bytes from original stream. Max length of bytes read will be equal to bufferPool.BufferSize. + //3. Call BeforeBodyWrite event handler with BeforeBodyWriteEventArgs.BodyBytes set to the bytes read from original stream (pass null if original stream reached its end). + //4. Write BeforeBodyWriteEventArgs.BodyBytes to the target stream when BeforeBodyWriteEventArgs.BodyBytes is not null or empty. + //5. Stop writing to target stream when 'long contentLength' parameter number of bytes are written (when not chunked) or + //when BeforeBodyWriteEventArgs.IsLastChunk is true after callback (when chunked). + //6. Exit loop when original stream reaches its end AND when writing in step 5 has stopped. + throw new NotImplementedException(); } /// @@ -1093,7 +1129,7 @@ private async ValueTask writeBodyChunkedAsync(byte[] data, CancellationToken can /// /// /// - private async Task copyBodyChunkedAsync(IHttpStreamWriter writer, Action? onCopy, CancellationToken cancellationToken) + private async Task copyBodyChunkedAsync(IHttpStreamWriter writer, bool isRequest, SessionEventArgs args, CancellationToken cancellationToken) { while (true) { @@ -1118,7 +1154,7 @@ private async Task copyBodyChunkedAsync(IHttpStreamWriter writer, Action /// /// - private async Task copyBytesToStream(IHttpStreamWriter writer, long count, Action? onCopy, + private async Task copyBytesToStream(IHttpStreamWriter writer, long count, bool isRequest, SessionEventArgs args, CancellationToken cancellationToken) { var buffer = bufferPool.GetBuffer(); @@ -1168,7 +1204,10 @@ private async Task copyBytesToStream(IHttpStreamWriter writer, long count, Actio await writer.WriteAsync(buffer, 0, bytesRead, cancellationToken); - onCopy?.Invoke(buffer, 0, bytesRead); + if (isRequest) + args.OnDataSent(buffer, 0, bytesRead); + else + args.OnDataReceived(buffer, 0, bytesRead); } } finally diff --git a/src/Titanium.Web.Proxy/Helpers/NullWriter.cs b/src/Titanium.Web.Proxy/Helpers/NullWriter.cs index b71892846..c3ef9dc82 100644 --- a/src/Titanium.Web.Proxy/Helpers/NullWriter.cs +++ b/src/Titanium.Web.Proxy/Helpers/NullWriter.cs @@ -8,6 +8,8 @@ internal class NullWriter : IHttpStreamWriter { public static NullWriter Instance { get; } = new NullWriter(); + public bool IsNetworkStream => false; + private NullWriter() { } diff --git a/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs b/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs index 0277b01a1..7d7f5f30a 100644 --- a/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs +++ b/src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs @@ -513,7 +513,7 @@ internal Task GetServerConnection(ProxyServer proxyServer, await proxyServer.InvokeServerConnectionCreateEvent(tcpServerSocket); - stream = new HttpServerStream(new NetworkStream(tcpServerSocket, true), proxyServer.BufferPool, cancellationToken); + stream = new HttpServerStream(proxyServer, new NetworkStream(tcpServerSocket, true), proxyServer.BufferPool, cancellationToken); if (externalProxy != null && externalProxy.ProxyType == ExternalProxyType.Http && (isConnect || isHttps)) { @@ -555,7 +555,7 @@ internal Task GetServerConnection(ProxyServer proxyServer, (sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) => proxyServer.SelectClientCertificate(sender, sessionArgs, targetHost, localCertificates, remoteCertificate, acceptableIssuers)); - stream = new HttpServerStream(sslStream, proxyServer.BufferPool, cancellationToken); + stream = new HttpServerStream(proxyServer, sslStream, proxyServer.BufferPool, cancellationToken); var options = new SslClientAuthenticationOptions { diff --git a/src/Titanium.Web.Proxy/ProxyServer.cs b/src/Titanium.Web.Proxy/ProxyServer.cs index d7ee15b85..f4a8a3c5d 100644 --- a/src/Titanium.Web.Proxy/ProxyServer.cs +++ b/src/Titanium.Web.Proxy/ProxyServer.cs @@ -350,11 +350,23 @@ public ExceptionHandler ExceptionFunc /// public event AsyncEventHandler? BeforeRequest; +#if DEBUG + /// + /// Intercept request body send event to server. + /// + public event AsyncEventHandler? OnRequestBodyWrite; +#endif /// /// Intercept response event from server. /// public event AsyncEventHandler? BeforeResponse; +#if DEBUG + /// + /// Intercept request body send event to client. + /// + public event AsyncEventHandler? OnResponseBodyWrite; +#endif /// /// Intercept after response event from server. /// @@ -765,8 +777,19 @@ private void onAcceptConnection(IAsyncResult asyn) }); } - // Get the listener that handles the client request. - endPoint.Listener!.BeginAcceptSocket(onAcceptConnection, endPoint); + try + { + // based on end point type call appropriate request handlers + // Get the listener that handles the client request. + endPoint.Listener!.BeginAcceptSocket(onAcceptConnection, endPoint); + } + catch (Exception ex) when (ex is ObjectDisposedException || ex is InvalidOperationException) + { + // The listener was Stop()'d, disposing the underlying socket and + // triggering the completion of the callback. We're already exiting, + // so just return. + return; + } } diff --git a/src/Titanium.Web.Proxy/RequestHandler.cs b/src/Titanium.Web.Proxy/RequestHandler.cs index 1565e0121..103f309f9 100644 --- a/src/Titanium.Web.Proxy/RequestHandler.cs +++ b/src/Titanium.Web.Proxy/RequestHandler.cs @@ -400,5 +400,25 @@ private async Task onBeforeRequest(SessionEventArgs args) await BeforeRequest.InvokeAsync(this, args, ExceptionFunc); } } + +#if DEBUG + internal bool ShouldCallBeforeRequestBodyWrite() + { + if (OnRequestBodyWrite != null) + { + return true; + } + + return false; + } + + internal async Task OnBeforeRequestBodyWrite(BeforeBodyWriteEventArgs args) + { + if (OnRequestBodyWrite != null) + { + await OnRequestBodyWrite.InvokeAsync(this, args, ExceptionFunc); + } + } +#endif } } diff --git a/src/Titanium.Web.Proxy/ResponseHandler.cs b/src/Titanium.Web.Proxy/ResponseHandler.cs index 95a782f71..0d07c9d3b 100644 --- a/src/Titanium.Web.Proxy/ResponseHandler.cs +++ b/src/Titanium.Web.Proxy/ResponseHandler.cs @@ -118,7 +118,7 @@ await handleHttpSessionRequest(args, null, args.ClientConnection.NegotiatedAppli // Copy body if exists var serverStream = args.HttpClient.Connection.Stream; await serverStream.CopyBodyAsync(response, false, clientStream, TransformationMode.None, - args.OnDataReceived, cancellationToken); + false, args, cancellationToken); } } @@ -150,5 +150,24 @@ private async Task onAfterResponse(SessionEventArgs args) await AfterResponse.InvokeAsync(this, args, ExceptionFunc); } } +#if DEBUG + internal bool ShouldCallBeforeResponseBodyWrite() + { + if (OnResponseBodyWrite != null) + { + return true; + } + + return false; + } + + internal async Task OnBeforeResponseBodyWrite(BeforeBodyWriteEventArgs args) + { + if (OnResponseBodyWrite != null) + { + await OnResponseBodyWrite.InvokeAsync(this, args, ExceptionFunc); + } + } +#endif } } diff --git a/src/Titanium.Web.Proxy/StreamExtended/Network/IHttpStreamReader.cs b/src/Titanium.Web.Proxy/StreamExtended/Network/IHttpStreamReader.cs index 3bb6eed21..bcee2686b 100644 --- a/src/Titanium.Web.Proxy/StreamExtended/Network/IHttpStreamReader.cs +++ b/src/Titanium.Web.Proxy/StreamExtended/Network/IHttpStreamReader.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using Titanium.Web.Proxy.EventArguments; namespace Titanium.Web.Proxy.StreamExtended.Network { @@ -11,6 +12,6 @@ public interface IHttpStreamReader : ILineStream Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken); Task CopyBodyAsync(IHttpStreamWriter writer, bool isChunked, long contentLength, - Action? onCopy, CancellationToken cancellationToken); + bool isRequest, SessionEventArgs args, CancellationToken cancellationToken); } } diff --git a/src/Titanium.Web.Proxy/StreamExtended/Network/IHttpStreamWriter.cs b/src/Titanium.Web.Proxy/StreamExtended/Network/IHttpStreamWriter.cs index 6cfd89c40..1457c8dee 100644 --- a/src/Titanium.Web.Proxy/StreamExtended/Network/IHttpStreamWriter.cs +++ b/src/Titanium.Web.Proxy/StreamExtended/Network/IHttpStreamWriter.cs @@ -8,6 +8,8 @@ namespace Titanium.Web.Proxy.StreamExtended.Network /// public interface IHttpStreamWriter { + bool IsNetworkStream { get; } + void Write(byte[] buffer, int offset, int count); Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken); diff --git a/src/Titanium.Web.Proxy/TransparentClientHandler.cs b/src/Titanium.Web.Proxy/TransparentClientHandler.cs index ce8d3ff8e..17e6e28c5 100644 --- a/src/Titanium.Web.Proxy/TransparentClientHandler.cs +++ b/src/Titanium.Web.Proxy/TransparentClientHandler.cs @@ -36,7 +36,7 @@ private async Task handleClient(TransparentBaseProxyEndPoint endPoint, TcpClient int port, CancellationTokenSource cancellationTokenSource, CancellationToken cancellationToken) { bool isHttps = false; - var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken); + var clientStream = new HttpClientStream(this, clientConnection, clientConnection.GetStream(), BufferPool, cancellationToken); try { @@ -46,7 +46,7 @@ private async Task handleClient(TransparentBaseProxyEndPoint endPoint, TcpClient { var httpsHostName = clientHelloInfo.GetServerName() ?? endPoint.GenericCertificateName; - var args = new BeforeSslAuthenticateEventArgs(clientConnection, cancellationTokenSource, httpsHostName); + var args = new BeforeSslAuthenticateEventArgs(this, clientConnection, cancellationTokenSource, httpsHostName); await endPoint.InvokeBeforeSslAuthenticate(this, args, ExceptionFunc); @@ -74,7 +74,7 @@ private async Task handleClient(TransparentBaseProxyEndPoint endPoint, TcpClient await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls12, false); // HTTPS server created - we can now decrypt the client's traffic - clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool, cancellationToken); + clientStream = new HttpClientStream(this, clientStream.Connection, sslStream, BufferPool, cancellationToken); sslStream = null; // clientStream was created, no need to keep SSL stream reference isHttps = true; }