Unverified Commit d8df61ba authored by honfika's avatar honfika Committed by GitHub

Merge pull request #659 from justcoding121/beta

Beta
parents 4a7ccfac 6923f8aa
...@@ -29,7 +29,7 @@ if($Branch -eq "beta" ) { $Version = "$Version-beta" } ...@@ -29,7 +29,7 @@ if($Branch -eq "beta" ) { $Version = "$Version-beta" }
$NuGet = Join-Path $RepoRoot ".nuget\nuget.exe" $NuGet = Join-Path $RepoRoot ".nuget\nuget.exe"
$MSBuild = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe" $MSBuild = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\msbuild.exe"
$MSBuild -replace ' ', '` ' $MSBuild -replace ' ', '` '
FormatTaskName (("-"*25) + "[{0}]" + ("-"*25)) FormatTaskName (("-"*25) + "[{0}]" + ("-"*25))
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# version format # version format
version: 3.1.{build} version: 3.1.{build}
image: Visual Studio 2017 image: Visual Studio 2019
shallow_clone: false shallow_clone: false
......
...@@ -102,9 +102,6 @@ or when server terminates connection from proxy.</p> ...@@ -102,9 +102,6 @@ or when server terminates connection from proxy.</p>
</div> </div>
<div class="inheritedMembers"> <div class="inheritedMembers">
<h5>Inherited Members</h5> <h5>Inherited Members</h5>
<div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize">SessionEventArgsBase.BufferSize</a>
</div>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferPool">SessionEventArgsBase.BufferPool</a> <a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferPool">SessionEventArgsBase.BufferPool</a>
</div> </div>
...@@ -301,7 +298,7 @@ or when server terminates connection from proxy.</p> ...@@ -301,7 +298,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Dispose.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Dispose%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Dispose.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Dispose%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L665">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L663">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Dispose_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Dispose*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Dispose_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Dispose*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Dispose" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Dispose">Dispose()</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Dispose" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Dispose">Dispose()</h4>
...@@ -319,7 +316,7 @@ or when server terminates connection from proxy.</p> ...@@ -319,7 +316,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_Byte___System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.Byte%5B%5D%2CSystem.Net.HttpStatusCode%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_Byte___System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.Byte%5B%5D%2CSystem.Net.HttpStatusCode%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L585">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L583">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_Byte___System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.Byte[],System.Net.HttpStatusCode,System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">GenericResponse(Byte[], HttpStatusCode, Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_Byte___System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.Byte[],System.Net.HttpStatusCode,System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">GenericResponse(Byte[], HttpStatusCode, Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4>
...@@ -372,7 +369,7 @@ the specified status to client. And then ignore the request.</p> ...@@ -372,7 +369,7 @@ the specified status to client. And then ignore the request.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_String_System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.String%2CSystem.Net.HttpStatusCode%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_String_System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.String%2CSystem.Net.HttpStatusCode%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L566">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L564">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_String_System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.String,System.Net.HttpStatusCode,System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">GenericResponse(String, HttpStatusCode, Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_String_System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.String,System.Net.HttpStatusCode,System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">GenericResponse(String, HttpStatusCode, Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4>
...@@ -426,7 +423,7 @@ And then ignore the request. </p> ...@@ -426,7 +423,7 @@ And then ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBody_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBody(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBody_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBody(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L401">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L399">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBody*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBody*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBody_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBody(System.Threading.CancellationToken)">GetRequestBody(CancellationToken)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBody_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBody(System.Threading.CancellationToken)">GetRequestBody(CancellationToken)</h4>
...@@ -476,7 +473,7 @@ And then ignore the request. </p> ...@@ -476,7 +473,7 @@ And then ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBodyAsString_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBodyAsString(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBodyAsString_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBodyAsString(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L416">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L414">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBodyAsString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBodyAsString*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBodyAsString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBodyAsString*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBodyAsString_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBodyAsString(System.Threading.CancellationToken)">GetRequestBodyAsString(CancellationToken)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBodyAsString_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBodyAsString(System.Threading.CancellationToken)">GetRequestBodyAsString(CancellationToken)</h4>
...@@ -526,7 +523,7 @@ And then ignore the request. </p> ...@@ -526,7 +523,7 @@ And then ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBody_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBody(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBody_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBody(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L461">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L459">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBody*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBody*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBody_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBody(System.Threading.CancellationToken)">GetResponseBody(CancellationToken)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBody_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBody(System.Threading.CancellationToken)">GetResponseBody(CancellationToken)</h4>
...@@ -576,7 +573,7 @@ And then ignore the request. </p> ...@@ -576,7 +573,7 @@ And then ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBodyAsString_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBodyAsString(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBodyAsString_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBodyAsString(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L476">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L474">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBodyAsString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBodyAsString*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBodyAsString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBodyAsString*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBodyAsString_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBodyAsString(System.Threading.CancellationToken)">GetResponseBodyAsString(CancellationToken)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBodyAsString_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBodyAsString(System.Threading.CancellationToken)">GetResponseBodyAsString(CancellationToken)</h4>
...@@ -626,7 +623,7 @@ And then ignore the request. </p> ...@@ -626,7 +623,7 @@ And then ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_Byte___System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.Byte%5B%5D%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_Byte___System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.Byte%5B%5D%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L546">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L544">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_Byte___System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.Byte[],System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">Ok(Byte[], Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_Byte___System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.Byte[],System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">Ok(Byte[], Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4>
...@@ -673,7 +670,7 @@ and ignore the request. </p> ...@@ -673,7 +670,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_String_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.String%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_String_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.String%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L524">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L522">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_String_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.String,System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">Ok(String, Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_String_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.String,System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">Ok(String, Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4>
...@@ -720,7 +717,7 @@ and ignore the request. </p> ...@@ -720,7 +717,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Redirect_System_String_System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Redirect(System.String%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Redirect_System_String_System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Redirect(System.String%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L601">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L599">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Redirect_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Redirect*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Redirect_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Redirect*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Redirect_System_String_System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Redirect(System.String,System.Boolean)">Redirect(String, Boolean)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Redirect_System_String_System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Redirect(System.String,System.Boolean)">Redirect(String, Boolean)</h4>
...@@ -760,7 +757,7 @@ and ignore the request. </p> ...@@ -760,7 +757,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Respond_Titanium_Web_Proxy_Http_Response_System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Respond(Titanium.Web.Proxy.Http.Response%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Respond_Titanium_Web_Proxy_Http_Response_System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Respond(Titanium.Web.Proxy.Http.Response%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L616">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L614">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Respond_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Respond*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Respond_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Respond*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Respond_Titanium_Web_Proxy_Http_Response_System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Respond(Titanium.Web.Proxy.Http.Response,System.Boolean)">Respond(Response, Boolean)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Respond_Titanium_Web_Proxy_Http_Response_System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Respond(Titanium.Web.Proxy.Http.Response,System.Boolean)">Respond(Response, Boolean)</h4>
...@@ -800,7 +797,7 @@ and ignore the request. </p> ...@@ -800,7 +797,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBody_System_Byte___.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBody(System.Byte%5B%5D)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBody_System_Byte___.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBody(System.Byte%5B%5D)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L430">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L428">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBody*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBody*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBody_System_Byte___" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBody(System.Byte[])">SetRequestBody(Byte[])</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBody_System_Byte___" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBody(System.Byte[])">SetRequestBody(Byte[])</h4>
...@@ -834,7 +831,7 @@ and ignore the request. </p> ...@@ -834,7 +831,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBodyString_System_String_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBodyString(System.String)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBodyString_System_String_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBodyString(System.String)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L445">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L443">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBodyString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBodyString*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBodyString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBodyString*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBodyString_System_String_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBodyString(System.String)">SetRequestBodyString(String)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBodyString_System_String_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBodyString(System.String)">SetRequestBodyString(String)</h4>
...@@ -868,7 +865,7 @@ and ignore the request. </p> ...@@ -868,7 +865,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBody_System_Byte___.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBody(System.Byte%5B%5D)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBody_System_Byte___.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBody(System.Byte%5B%5D)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L490">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L488">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBody*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBody*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBody_System_Byte___" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBody(System.Byte[])">SetResponseBody(Byte[])</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBody_System_Byte___" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBody(System.Byte[])">SetResponseBody(Byte[])</h4>
...@@ -902,7 +899,7 @@ and ignore the request. </p> ...@@ -902,7 +899,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBodyString_System_String_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBodyString(System.String)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBodyString_System_String_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBodyString(System.String)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L505">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L503">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBodyString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBodyString*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBodyString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBodyString*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBodyString_System_String_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBodyString(System.String)">SetResponseBodyString(String)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBodyString_System_String_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBodyString(System.String)">SetResponseBodyString(String)</h4>
...@@ -936,7 +933,7 @@ and ignore the request. </p> ...@@ -936,7 +933,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_TerminateServerConnection.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.TerminateServerConnection%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_TerminateServerConnection.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.TerminateServerConnection%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L657">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L655">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_TerminateServerConnection_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.TerminateServerConnection*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_TerminateServerConnection_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.TerminateServerConnection*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_TerminateServerConnection" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.TerminateServerConnection">TerminateServerConnection()</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_TerminateServerConnection" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.TerminateServerConnection">TerminateServerConnection()</h4>
......
...@@ -141,7 +141,7 @@ or when server terminates connection from proxy.</p> ...@@ -141,7 +141,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase__ctor_Titanium_Web_Proxy_ProxyServer_Titanium_Web_Proxy_Models_ProxyEndPoint_System_Threading_CancellationTokenSource_Titanium_Web_Proxy_Http_Request_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.%23ctor(Titanium.Web.Proxy.ProxyServer%2CTitanium.Web.Proxy.Models.ProxyEndPoint%2CSystem.Threading.CancellationTokenSource%2CTitanium.Web.Proxy.Http.Request)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase__ctor_Titanium_Web_Proxy_ProxyServer_Titanium_Web_Proxy_Models_ProxyEndPoint_System_Threading_CancellationTokenSource_Titanium_Web_Proxy_Http_Request_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.%23ctor(Titanium.Web.Proxy.ProxyServer%2CTitanium.Web.Proxy.Models.ProxyEndPoint%2CSystem.Threading.CancellationTokenSource%2CTitanium.Web.Proxy.Http.Request)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L48">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L47">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase__ctor_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.#ctor*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase__ctor_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.#ctor*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase__ctor_Titanium_Web_Proxy_ProxyServer_Titanium_Web_Proxy_Models_ProxyEndPoint_System_Threading_CancellationTokenSource_Titanium_Web_Proxy_Http_Request_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.#ctor(Titanium.Web.Proxy.ProxyServer,Titanium.Web.Proxy.Models.ProxyEndPoint,System.Threading.CancellationTokenSource,Titanium.Web.Proxy.Http.Request)">SessionEventArgsBase(ProxyServer, ProxyEndPoint, CancellationTokenSource, Request)</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase__ctor_Titanium_Web_Proxy_ProxyServer_Titanium_Web_Proxy_Models_ProxyEndPoint_System_Threading_CancellationTokenSource_Titanium_Web_Proxy_Http_Request_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.#ctor(Titanium.Web.Proxy.ProxyServer,Titanium.Web.Proxy.Models.ProxyEndPoint,System.Threading.CancellationTokenSource,Titanium.Web.Proxy.Http.Request)">SessionEventArgsBase(ProxyServer, ProxyEndPoint, CancellationTokenSource, Request)</h4>
...@@ -190,7 +190,7 @@ or when server terminates connection from proxy.</p> ...@@ -190,7 +190,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferPool.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferPool.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L28">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L29">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferPool" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool">BufferPool</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferPool" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool">BufferPool</h4>
<div class="markdown level1 summary"></div> <div class="markdown level1 summary"></div>
...@@ -214,41 +214,12 @@ or when server terminates connection from proxy.</p> ...@@ -214,41 +214,12 @@ or when server terminates connection from proxy.</p>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<span class="small pull-right mobile-hide">
<span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferSize%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L27">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferSize">BufferSize</h4>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected readonly int BufferSize</code></pre>
</div>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.int32">Int32</a></td>
<td></td>
</tr>
</tbody>
</table>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<span class="divider">|</span> <span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ExceptionFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ExceptionFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L29">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L30">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ExceptionFunc" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc">ExceptionFunc</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ExceptionFunc" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc">ExceptionFunc</h4>
<div class="markdown level1 summary"></div> <div class="markdown level1 summary"></div>
...@@ -279,7 +250,7 @@ or when server terminates connection from proxy.</p> ...@@ -279,7 +250,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L84">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L83">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint">ClientEndPoint</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint">ClientEndPoint</h4>
...@@ -310,7 +281,7 @@ or when server terminates connection from proxy.</p> ...@@ -310,7 +281,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_CustomUpStreamProxyUsed.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.CustomUpStreamProxyUsed%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_CustomUpStreamProxyUsed.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.CustomUpStreamProxyUsed%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L97">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L96">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_CustomUpStreamProxyUsed_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.CustomUpStreamProxyUsed*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_CustomUpStreamProxyUsed_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.CustomUpStreamProxyUsed*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_CustomUpStreamProxyUsed" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.CustomUpStreamProxyUsed">CustomUpStreamProxyUsed</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_CustomUpStreamProxyUsed" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.CustomUpStreamProxyUsed">CustomUpStreamProxyUsed</h4>
...@@ -341,7 +312,7 @@ or when server terminates connection from proxy.</p> ...@@ -341,7 +312,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Exception.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Exception%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Exception.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Exception%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L112">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L111">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Exception_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Exception*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Exception_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Exception*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Exception" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Exception">Exception</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Exception" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Exception">Exception</h4>
...@@ -372,7 +343,7 @@ or when server terminates connection from proxy.</p> ...@@ -372,7 +343,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_HttpClient.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.HttpClient%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_HttpClient.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.HttpClient%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L89">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L88">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_HttpClient_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.HttpClient*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_HttpClient_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.HttpClient*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_HttpClient" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.HttpClient">HttpClient</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_HttpClient" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.HttpClient">HttpClient</h4>
...@@ -403,7 +374,7 @@ or when server terminates connection from proxy.</p> ...@@ -403,7 +374,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsHttps.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsHttps%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsHttps.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsHttps%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L79">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L78">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsHttps_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsHttps*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsHttps_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsHttps*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsHttps" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsHttps">IsHttps</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsHttps" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsHttps">IsHttps</h4>
...@@ -434,7 +405,7 @@ or when server terminates connection from proxy.</p> ...@@ -434,7 +405,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsTransparent.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsTransparent%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsTransparent.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsTransparent%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L107">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L106">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsTransparent_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsTransparent*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsTransparent_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsTransparent*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsTransparent" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsTransparent">IsTransparent</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsTransparent" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsTransparent">IsTransparent</h4>
...@@ -465,7 +436,7 @@ or when server terminates connection from proxy.</p> ...@@ -465,7 +436,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_LocalEndPoint.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.LocalEndPoint%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_LocalEndPoint.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.LocalEndPoint%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L102">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L101">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_LocalEndPoint_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.LocalEndPoint*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_LocalEndPoint_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.LocalEndPoint*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_LocalEndPoint" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.LocalEndPoint">LocalEndPoint</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_LocalEndPoint" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.LocalEndPoint">LocalEndPoint</h4>
...@@ -496,7 +467,7 @@ or when server terminates connection from proxy.</p> ...@@ -496,7 +467,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TimeLine.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TimeLine%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TimeLine.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TimeLine%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L34">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L35">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TimeLine_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TimeLine*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TimeLine_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TimeLine*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TimeLine" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TimeLine">TimeLine</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TimeLine" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TimeLine">TimeLine</h4>
...@@ -527,7 +498,7 @@ or when server terminates connection from proxy.</p> ...@@ -527,7 +498,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L70">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L69">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData">UserData</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData">UserData</h4>
...@@ -559,7 +530,7 @@ same as the user data of HttpClient.</p> ...@@ -559,7 +530,7 @@ same as the user data of HttpClient.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_WebSession.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.WebSession%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_WebSession.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.WebSession%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L91">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L90">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_WebSession_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.WebSession*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_WebSession_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.WebSession*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_WebSession" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.WebSession">WebSession</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_WebSession" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.WebSession">WebSession</h4>
...@@ -592,7 +563,7 @@ public HttpWebClient WebSession { get; }</code></pre> ...@@ -592,7 +563,7 @@ public HttpWebClient WebSession { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Dispose.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Dispose%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Dispose.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Dispose%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L117">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L116">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Dispose_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Dispose*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Dispose_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Dispose*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Dispose" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Dispose">Dispose()</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Dispose" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Dispose">Dispose()</h4>
...@@ -608,7 +579,7 @@ public HttpWebClient WebSession { get; }</code></pre> ...@@ -608,7 +579,7 @@ public HttpWebClient WebSession { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TerminateSession.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TerminateSession%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TerminateSession.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TerminateSession%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L165">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L164">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TerminateSession_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TerminateSession*"></a> <a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TerminateSession_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TerminateSession*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TerminateSession" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TerminateSession">TerminateSession()</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TerminateSession" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TerminateSession">TerminateSession()</h4>
...@@ -626,7 +597,7 @@ public HttpWebClient WebSession { get; }</code></pre> ...@@ -626,7 +597,7 @@ public HttpWebClient WebSession { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataReceived.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataReceived%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataReceived.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataReceived%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L136">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L135">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataReceived" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataReceived">DataReceived</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataReceived" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataReceived">DataReceived</h4>
<div class="markdown level1 summary"><p>Fired when data is received within this session from client/server.</p> <div class="markdown level1 summary"><p>Fired when data is received within this session from client/server.</p>
...@@ -656,7 +627,7 @@ public HttpWebClient WebSession { get; }</code></pre> ...@@ -656,7 +627,7 @@ public HttpWebClient WebSession { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataSent.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataSent%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataSent.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataSent%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L131">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L130">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataSent" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataSent">DataSent</h4> <h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataSent" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataSent">DataSent</h4>
<div class="markdown level1 summary"><p>Fired when data is sent within this session to server/client.</p> <div class="markdown level1 summary"><p>Fired when data is sent within this session to server/client.</p>
......
...@@ -99,9 +99,6 @@ ...@@ -99,9 +99,6 @@
</div> </div>
<div class="inheritedMembers"> <div class="inheritedMembers">
<h5>Inherited Members</h5> <h5>Inherited Members</h5>
<div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize">SessionEventArgsBase.BufferSize</a>
</div>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferPool">SessionEventArgsBase.BufferPool</a> <a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferPool">SessionEventArgsBase.BufferPool</a>
</div> </div>
...@@ -188,7 +185,7 @@ ...@@ -188,7 +185,7 @@
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptSsl.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptSsl%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptSsl.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptSsl%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs/#L26">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs/#L27">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptSsl_" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptSsl*"></a> <a id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptSsl_" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptSsl*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptSsl" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptSsl">DecryptSsl</h4> <h4 id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptSsl" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptSsl">DecryptSsl</h4>
...@@ -220,7 +217,7 @@ Default is true.</p> ...@@ -220,7 +217,7 @@ Default is true.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DenyConnect.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DenyConnect%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DenyConnect.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DenyConnect%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs/#L31">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs/#L32">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DenyConnect_" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DenyConnect*"></a> <a id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DenyConnect_" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DenyConnect*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DenyConnect" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DenyConnect">DenyConnect</h4> <h4 id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DenyConnect" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DenyConnect">DenyConnect</h4>
...@@ -251,7 +248,7 @@ Default is true.</p> ...@@ -251,7 +248,7 @@ Default is true.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_IsHttpsConnect.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.IsHttpsConnect%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_IsHttpsConnect.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.IsHttpsConnect%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs/#L36">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs/#L37">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_IsHttpsConnect_" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.IsHttpsConnect*"></a> <a id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_IsHttpsConnect_" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.IsHttpsConnect*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_IsHttpsConnect" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.IsHttpsConnect">IsHttpsConnect</h4> <h4 id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_IsHttpsConnect" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.IsHttpsConnect">IsHttpsConnect</h4>
...@@ -277,6 +274,68 @@ Default is true.</p> ...@@ -277,6 +274,68 @@ Default is true.</p>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<h3 id="events">Events
</h3>
<span class="small pull-right mobile-hide">
<span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptedDataReceived.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptedDataReceived%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs/#L53">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptedDataReceived" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptedDataReceived">DecryptedDataReceived</h4>
<div class="markdown level1 summary"><p>Fired when decrypted data is received within this session from client/server.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public event EventHandler&lt;DataEventArgs&gt; DecryptedDataReceived</code></pre>
</div>
<h5 class="eventType">Event Type</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.eventhandler-1">EventHandler</a>&lt;<span class="xref">DataEventArgs</span>&gt;</td>
<td></td>
</tr>
</tbody>
</table>
<span class="small pull-right mobile-hide">
<span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptedDataSent.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptedDataSent%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs/#L48">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptedDataSent" data-uid="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptedDataSent">DecryptedDataSent</h4>
<div class="markdown level1 summary"><p>Fired when decrypted data is sent within this session to server/client.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public event EventHandler&lt;DataEventArgs&gt; DecryptedDataSent</code></pre>
</div>
<h5 class="eventType">Event Type</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.eventhandler-1">EventHandler</a>&lt;<span class="xref">DataEventArgs</span>&gt;</td>
<td></td>
</tr>
</tbody>
</table>
<h3 id="implements">Implements</h3> <h3 id="implements">Implements</h3>
<div> <div>
<a class="xref" href="https://docs.microsoft.com/dotnet/api/system.idisposable">System.IDisposable</a> <a class="xref" href="https://docs.microsoft.com/dotnet/api/system.idisposable">System.IDisposable</a>
...@@ -292,7 +351,7 @@ Default is true.</p> ...@@ -292,7 +351,7 @@ Default is true.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A" class="contribution-link">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A" class="contribution-link">Improve this Doc</a>
</li> </li>
<li> <li>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs/#L11" class="contribution-link">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/TunnelConnectEventArgs.cs/#L12" class="contribution-link">View Source</a>
</li> </li>
</ul> </ul>
</div> </div>
......
...@@ -104,9 +104,6 @@ So client application know that it is communicating with a proxy server.</p> ...@@ -104,9 +104,6 @@ So client application know that it is communicating with a proxy server.</p>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_DecryptSsl">ProxyEndPoint.DecryptSsl</a> <a class="xref" href="Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_DecryptSsl">ProxyEndPoint.DecryptSsl</a>
</div> </div>
<div>
<a class="xref" href="Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_IpV6Enabled">ProxyEndPoint.IpV6Enabled</a>
</div>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_GenericCertificate">ProxyEndPoint.GenericCertificate</a> <a class="xref" href="Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_GenericCertificate">ProxyEndPoint.GenericCertificate</a>
</div> </div>
......
...@@ -206,7 +206,7 @@ ...@@ -206,7 +206,7 @@
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Models_ProxyEndPoint_GenericCertificate.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.ProxyEndPoint.GenericCertificate%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Models_ProxyEndPoint_GenericCertificate.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.ProxyEndPoint.GenericCertificate%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Models/ProxyEndPoint.cs/#L56">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Models/ProxyEndPoint.cs/#L48">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_Models_ProxyEndPoint_GenericCertificate_" data-uid="Titanium.Web.Proxy.Models.ProxyEndPoint.GenericCertificate*"></a> <a id="Titanium_Web_Proxy_Models_ProxyEndPoint_GenericCertificate_" data-uid="Titanium.Web.Proxy.Models.ProxyEndPoint.GenericCertificate*"></a>
<h4 id="Titanium_Web_Proxy_Models_ProxyEndPoint_GenericCertificate" data-uid="Titanium.Web.Proxy.Models.ProxyEndPoint.GenericCertificate">GenericCertificate</h4> <h4 id="Titanium_Web_Proxy_Models_ProxyEndPoint_GenericCertificate" data-uid="Titanium.Web.Proxy.Models.ProxyEndPoint.GenericCertificate">GenericCertificate</h4>
...@@ -263,37 +263,6 @@ ...@@ -263,37 +263,6 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<span class="small pull-right mobile-hide">
<span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Models_ProxyEndPoint_IpV6Enabled.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.ProxyEndPoint.IpV6Enabled%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Models/ProxyEndPoint.cs/#L48">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Models_ProxyEndPoint_IpV6Enabled_" data-uid="Titanium.Web.Proxy.Models.ProxyEndPoint.IpV6Enabled*"></a>
<h4 id="Titanium_Web_Proxy_Models_ProxyEndPoint_IpV6Enabled" data-uid="Titanium.Web.Proxy.Models.ProxyEndPoint.IpV6Enabled">IpV6Enabled</h4>
<div class="markdown level1 summary"><p>Is IPv6 enabled?</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public bool IpV6Enabled { get; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.boolean">Boolean</a></td>
<td></td>
</tr>
</tbody>
</table>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<span class="divider">|</span> <span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Models_ProxyEndPoint_Port.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.ProxyEndPoint.Port%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Models_ProxyEndPoint_Port.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.ProxyEndPoint.Port%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
......
...@@ -104,9 +104,6 @@ Useful when requests are redirected to this proxy end point through port forward ...@@ -104,9 +104,6 @@ Useful when requests are redirected to this proxy end point through port forward
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_DecryptSsl">ProxyEndPoint.DecryptSsl</a> <a class="xref" href="Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_DecryptSsl">ProxyEndPoint.DecryptSsl</a>
</div> </div>
<div>
<a class="xref" href="Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_IpV6Enabled">ProxyEndPoint.IpV6Enabled</a>
</div>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_GenericCertificate">ProxyEndPoint.GenericCertificate</a> <a class="xref" href="Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_GenericCertificate">ProxyEndPoint.GenericCertificate</a>
</div> </div>
......
...@@ -243,7 +243,7 @@ prompting for UAC if required?</p> ...@@ -243,7 +243,7 @@ prompting for UAC if required?</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_BufferPool.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.BufferPool%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_BufferPool.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.BufferPool%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L250">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L239">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_BufferPool_" data-uid="Titanium.Web.Proxy.ProxyServer.BufferPool*"></a> <a id="Titanium_Web_Proxy_ProxyServer_BufferPool_" data-uid="Titanium.Web.Proxy.ProxyServer.BufferPool*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_BufferPool" data-uid="Titanium.Web.Proxy.ProxyServer.BufferPool">BufferPool</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_BufferPool" data-uid="Titanium.Web.Proxy.ProxyServer.BufferPool">BufferPool</h4>
...@@ -271,44 +271,12 @@ By default this uses DefaultBufferPool implementation available in StreamExtende ...@@ -271,44 +271,12 @@ By default this uses DefaultBufferPool implementation available in StreamExtende
</tr> </tr>
</tbody> </tbody>
</table> </table>
<span class="small pull-right mobile-hide">
<span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_BufferSize.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.BufferSize%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L197">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_BufferSize_" data-uid="Titanium.Web.Proxy.ProxyServer.BufferSize*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_BufferSize" data-uid="Titanium.Web.Proxy.ProxyServer.BufferSize">BufferSize</h4>
<div class="markdown level1 summary"><p>Buffer size in bytes used throughout this proxy.
Default value is 8192 bytes.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public int BufferSize { get; set; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.int32">Int32</a></td>
<td></td>
</tr>
</tbody>
</table>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<span class="divider">|</span> <span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_CertificateManager.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.CertificateManager%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_CertificateManager.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.CertificateManager%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L255">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L244">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_CertificateManager_" data-uid="Titanium.Web.Proxy.ProxyServer.CertificateManager*"></a> <a id="Titanium_Web_Proxy_ProxyServer_CertificateManager_" data-uid="Titanium.Web.Proxy.ProxyServer.CertificateManager*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_CertificateManager" data-uid="Titanium.Web.Proxy.ProxyServer.CertificateManager">CertificateManager</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_CertificateManager" data-uid="Titanium.Web.Proxy.ProxyServer.CertificateManager">CertificateManager</h4>
...@@ -339,7 +307,7 @@ Default value is 8192 bytes.</p> ...@@ -339,7 +307,7 @@ Default value is 8192 bytes.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_CheckCertificateRevocation.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.CheckCertificateRevocation%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_CheckCertificateRevocation.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.CheckCertificateRevocation%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L162">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L157">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_CheckCertificateRevocation_" data-uid="Titanium.Web.Proxy.ProxyServer.CheckCertificateRevocation*"></a> <a id="Titanium_Web_Proxy_ProxyServer_CheckCertificateRevocation_" data-uid="Titanium.Web.Proxy.ProxyServer.CheckCertificateRevocation*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_CheckCertificateRevocation" data-uid="Titanium.Web.Proxy.ProxyServer.CheckCertificateRevocation">CheckCertificateRevocation</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_CheckCertificateRevocation" data-uid="Titanium.Web.Proxy.ProxyServer.CheckCertificateRevocation">CheckCertificateRevocation</h4>
...@@ -371,7 +339,7 @@ Note: If enabled can reduce performance. Defaults to false.</p> ...@@ -371,7 +339,7 @@ Note: If enabled can reduce performance. Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ClientConnectionCount.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ClientConnectionCount%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ClientConnectionCount.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ClientConnectionCount%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L228">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L217">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ClientConnectionCount_" data-uid="Titanium.Web.Proxy.ProxyServer.ClientConnectionCount*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ClientConnectionCount_" data-uid="Titanium.Web.Proxy.ProxyServer.ClientConnectionCount*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ClientConnectionCount" data-uid="Titanium.Web.Proxy.ProxyServer.ClientConnectionCount">ClientConnectionCount</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ClientConnectionCount" data-uid="Titanium.Web.Proxy.ProxyServer.ClientConnectionCount">ClientConnectionCount</h4>
...@@ -402,7 +370,7 @@ Note: If enabled can reduce performance. Defaults to false.</p> ...@@ -402,7 +370,7 @@ Note: If enabled can reduce performance. Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ConnectionTimeOutSeconds.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ConnectionTimeOutSeconds%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ConnectionTimeOutSeconds.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ConnectionTimeOutSeconds%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L204">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L193">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ConnectionTimeOutSeconds_" data-uid="Titanium.Web.Proxy.ProxyServer.ConnectionTimeOutSeconds*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ConnectionTimeOutSeconds_" data-uid="Titanium.Web.Proxy.ProxyServer.ConnectionTimeOutSeconds*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ConnectionTimeOutSeconds" data-uid="Titanium.Web.Proxy.ProxyServer.ConnectionTimeOutSeconds">ConnectionTimeOutSeconds</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ConnectionTimeOutSeconds" data-uid="Titanium.Web.Proxy.ProxyServer.ConnectionTimeOutSeconds">ConnectionTimeOutSeconds</h4>
...@@ -435,7 +403,7 @@ Default value is 60 seconds.</p> ...@@ -435,7 +403,7 @@ Default value is 60 seconds.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Enable100ContinueBehaviour.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Enable100ContinueBehaviour%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Enable100ContinueBehaviour.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Enable100ContinueBehaviour%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L169">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L164">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_Enable100ContinueBehaviour_" data-uid="Titanium.Web.Proxy.ProxyServer.Enable100ContinueBehaviour*"></a> <a id="Titanium_Web_Proxy_ProxyServer_Enable100ContinueBehaviour_" data-uid="Titanium.Web.Proxy.ProxyServer.Enable100ContinueBehaviour*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_Enable100ContinueBehaviour" data-uid="Titanium.Web.Proxy.ProxyServer.Enable100ContinueBehaviour">Enable100ContinueBehaviour</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_Enable100ContinueBehaviour" data-uid="Titanium.Web.Proxy.ProxyServer.Enable100ContinueBehaviour">Enable100ContinueBehaviour</h4>
...@@ -468,7 +436,7 @@ Defaults to false.</p> ...@@ -468,7 +436,7 @@ Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_EnableConnectionPool.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableConnectionPool%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_EnableConnectionPool.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableConnectionPool%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L175">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L170">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_EnableConnectionPool_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableConnectionPool*"></a> <a id="Titanium_Web_Proxy_ProxyServer_EnableConnectionPool_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableConnectionPool*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_EnableConnectionPool" data-uid="Titanium.Web.Proxy.ProxyServer.EnableConnectionPool">EnableConnectionPool</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_EnableConnectionPool" data-uid="Titanium.Web.Proxy.ProxyServer.EnableConnectionPool">EnableConnectionPool</h4>
...@@ -500,7 +468,7 @@ Defaults to true.</p> ...@@ -500,7 +468,7 @@ Defaults to true.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_EnableHttp2.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableHttp2%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_EnableHttp2.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableHttp2%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L156">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L151">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_EnableHttp2_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableHttp2*"></a> <a id="Titanium_Web_Proxy_ProxyServer_EnableHttp2_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableHttp2*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_EnableHttp2" data-uid="Titanium.Web.Proxy.ProxyServer.EnableHttp2">EnableHttp2</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_EnableHttp2" data-uid="Titanium.Web.Proxy.ProxyServer.EnableHttp2">EnableHttp2</h4>
...@@ -536,7 +504,7 @@ Warning: HTTP/2 support is very limited</p> ...@@ -536,7 +504,7 @@ Warning: HTTP/2 support is very limited</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_EnableTcpServerConnectionPrefetch.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableTcpServerConnectionPrefetch%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_EnableTcpServerConnectionPrefetch.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableTcpServerConnectionPrefetch%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L185">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L180">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_EnableTcpServerConnectionPrefetch_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableTcpServerConnectionPrefetch*"></a> <a id="Titanium_Web_Proxy_ProxyServer_EnableTcpServerConnectionPrefetch_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableTcpServerConnectionPrefetch*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_EnableTcpServerConnectionPrefetch" data-uid="Titanium.Web.Proxy.ProxyServer.EnableTcpServerConnectionPrefetch">EnableTcpServerConnectionPrefetch</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_EnableTcpServerConnectionPrefetch" data-uid="Titanium.Web.Proxy.ProxyServer.EnableTcpServerConnectionPrefetch">EnableTcpServerConnectionPrefetch</h4>
...@@ -572,7 +540,7 @@ Defaults to true.</p> ...@@ -572,7 +540,7 @@ Defaults to true.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_EnableWinAuth.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableWinAuth%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_EnableWinAuth.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableWinAuth%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L148">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L143">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_EnableWinAuth_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableWinAuth*"></a> <a id="Titanium_Web_Proxy_ProxyServer_EnableWinAuth_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableWinAuth*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_EnableWinAuth" data-uid="Titanium.Web.Proxy.ProxyServer.EnableWinAuth">EnableWinAuth</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_EnableWinAuth" data-uid="Titanium.Web.Proxy.ProxyServer.EnableWinAuth">EnableWinAuth</h4>
...@@ -607,7 +575,7 @@ Defaults to false.</p> ...@@ -607,7 +575,7 @@ Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ExceptionFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ExceptionFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ExceptionFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ExceptionFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L287">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L276">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ExceptionFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.ExceptionFunc*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ExceptionFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.ExceptionFunc*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ExceptionFunc" data-uid="Titanium.Web.Proxy.ProxyServer.ExceptionFunc">ExceptionFunc</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ExceptionFunc" data-uid="Titanium.Web.Proxy.ProxyServer.ExceptionFunc">ExceptionFunc</h4>
...@@ -638,7 +606,7 @@ Defaults to false.</p> ...@@ -638,7 +606,7 @@ Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ForwardToUpstreamGateway.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ForwardToUpstreamGateway%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ForwardToUpstreamGateway.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ForwardToUpstreamGateway%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L139">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L134">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ForwardToUpstreamGateway_" data-uid="Titanium.Web.Proxy.ProxyServer.ForwardToUpstreamGateway*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ForwardToUpstreamGateway_" data-uid="Titanium.Web.Proxy.ProxyServer.ForwardToUpstreamGateway*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ForwardToUpstreamGateway" data-uid="Titanium.Web.Proxy.ProxyServer.ForwardToUpstreamGateway">ForwardToUpstreamGateway</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ForwardToUpstreamGateway" data-uid="Titanium.Web.Proxy.ProxyServer.ForwardToUpstreamGateway">ForwardToUpstreamGateway</h4>
...@@ -670,7 +638,7 @@ Defaults to false.</p> ...@@ -670,7 +638,7 @@ Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_GetCustomUpStreamProxyFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.GetCustomUpStreamProxyFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_GetCustomUpStreamProxyFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.GetCustomUpStreamProxyFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L282">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L271">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_GetCustomUpStreamProxyFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.GetCustomUpStreamProxyFunc*"></a> <a id="Titanium_Web_Proxy_ProxyServer_GetCustomUpStreamProxyFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.GetCustomUpStreamProxyFunc*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_GetCustomUpStreamProxyFunc" data-uid="Titanium.Web.Proxy.ProxyServer.GetCustomUpStreamProxyFunc">GetCustomUpStreamProxyFunc</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_GetCustomUpStreamProxyFunc" data-uid="Titanium.Web.Proxy.ProxyServer.GetCustomUpStreamProxyFunc">GetCustomUpStreamProxyFunc</h4>
...@@ -702,7 +670,7 @@ User should return the ExternalProxy object with valid credentials.</p> ...@@ -702,7 +670,7 @@ User should return the ExternalProxy object with valid credentials.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_MaxCachedConnections.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.MaxCachedConnections%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_MaxCachedConnections.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.MaxCachedConnections%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L211">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L200">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_MaxCachedConnections_" data-uid="Titanium.Web.Proxy.ProxyServer.MaxCachedConnections*"></a> <a id="Titanium_Web_Proxy_ProxyServer_MaxCachedConnections_" data-uid="Titanium.Web.Proxy.ProxyServer.MaxCachedConnections*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_MaxCachedConnections" data-uid="Titanium.Web.Proxy.ProxyServer.MaxCachedConnections">MaxCachedConnections</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_MaxCachedConnections" data-uid="Titanium.Web.Proxy.ProxyServer.MaxCachedConnections">MaxCachedConnections</h4>
...@@ -735,7 +703,7 @@ Default value is 2.</p> ...@@ -735,7 +703,7 @@ Default value is 2.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_NoDelay.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.NoDelay%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_NoDelay.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.NoDelay%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L191">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L186">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_NoDelay_" data-uid="Titanium.Web.Proxy.ProxyServer.NoDelay*"></a> <a id="Titanium_Web_Proxy_ProxyServer_NoDelay_" data-uid="Titanium.Web.Proxy.ProxyServer.NoDelay*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_NoDelay" data-uid="Titanium.Web.Proxy.ProxyServer.NoDelay">NoDelay</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_NoDelay" data-uid="Titanium.Web.Proxy.ProxyServer.NoDelay">NoDelay</h4>
...@@ -767,7 +735,7 @@ Defaults to true, no nagle algorithm is used.</p> ...@@ -767,7 +735,7 @@ Defaults to true, no nagle algorithm is used.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationRealm.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationRealm%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationRealm.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationRealm%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L238">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L227">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationRealm_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationRealm*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationRealm_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationRealm*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationRealm" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationRealm">ProxyAuthenticationRealm</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationRealm" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationRealm">ProxyAuthenticationRealm</h4>
...@@ -798,7 +766,7 @@ Defaults to true, no nagle algorithm is used.</p> ...@@ -798,7 +766,7 @@ Defaults to true, no nagle algorithm is used.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationSchemes.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationSchemes%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationSchemes.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationSchemes%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L315">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L304">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationSchemes_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationSchemes*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationSchemes_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationSchemes*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationSchemes" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationSchemes">ProxyAuthenticationSchemes</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationSchemes" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationSchemes">ProxyAuthenticationSchemes</h4>
...@@ -830,7 +798,7 @@ Works in relation with ProxySchemeAuthenticateFunc.</p> ...@@ -830,7 +798,7 @@ Works in relation with ProxySchemeAuthenticateFunc.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyBasicAuthenticateFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyBasicAuthenticateFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyBasicAuthenticateFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyBasicAuthenticateFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L302">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L291">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxyBasicAuthenticateFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyBasicAuthenticateFunc*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ProxyBasicAuthenticateFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyBasicAuthenticateFunc*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxyBasicAuthenticateFunc" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyBasicAuthenticateFunc">ProxyBasicAuthenticateFunc</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ProxyBasicAuthenticateFunc" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyBasicAuthenticateFunc">ProxyBasicAuthenticateFunc</h4>
...@@ -863,7 +831,7 @@ Should return true for successful authentication.</p> ...@@ -863,7 +831,7 @@ Should return true for successful authentication.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyEndPoints.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyEndPoints%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyEndPoints.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyEndPoints%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L276">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L265">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxyEndPoints_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyEndPoints*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ProxyEndPoints_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyEndPoints*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxyEndPoints" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyEndPoints">ProxyEndPoints</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ProxyEndPoints" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyEndPoints">ProxyEndPoints</h4>
...@@ -894,7 +862,7 @@ Should return true for successful authentication.</p> ...@@ -894,7 +862,7 @@ Should return true for successful authentication.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyRunning.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyRunning%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyRunning.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyRunning%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L133">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L128">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxyRunning_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyRunning*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ProxyRunning_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyRunning*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxyRunning" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyRunning">ProxyRunning</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ProxyRunning" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyRunning">ProxyRunning</h4>
...@@ -925,7 +893,7 @@ Should return true for successful authentication.</p> ...@@ -925,7 +893,7 @@ Should return true for successful authentication.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxySchemeAuthenticateFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxySchemeAuthenticateFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxySchemeAuthenticateFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxySchemeAuthenticateFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L309">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L298">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxySchemeAuthenticateFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxySchemeAuthenticateFunc*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ProxySchemeAuthenticateFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxySchemeAuthenticateFunc*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxySchemeAuthenticateFunc" data-uid="Titanium.Web.Proxy.ProxyServer.ProxySchemeAuthenticateFunc">ProxySchemeAuthenticateFunc</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ProxySchemeAuthenticateFunc" data-uid="Titanium.Web.Proxy.ProxyServer.ProxySchemeAuthenticateFunc">ProxySchemeAuthenticateFunc</h4>
...@@ -958,7 +926,7 @@ Should return success for successful authentication, continuation if the package ...@@ -958,7 +926,7 @@ Should return success for successful authentication, continuation if the package
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ReuseSocket.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ReuseSocket%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ReuseSocket.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ReuseSocket%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L223">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L212">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ReuseSocket_" data-uid="Titanium.Web.Proxy.ProxyServer.ReuseSocket*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ReuseSocket_" data-uid="Titanium.Web.Proxy.ProxyServer.ReuseSocket*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ReuseSocket" data-uid="Titanium.Web.Proxy.ProxyServer.ReuseSocket">ReuseSocket</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ReuseSocket" data-uid="Titanium.Web.Proxy.ProxyServer.ReuseSocket">ReuseSocket</h4>
...@@ -990,7 +958,7 @@ Default is true (disabled for linux/macOS due to bug in .Net core).</p> ...@@ -990,7 +958,7 @@ Default is true (disabled for linux/macOS due to bug in .Net core).</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ServerConnectionCount.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ServerConnectionCount%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ServerConnectionCount.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ServerConnectionCount%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L233">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L222">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ServerConnectionCount_" data-uid="Titanium.Web.Proxy.ProxyServer.ServerConnectionCount*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ServerConnectionCount_" data-uid="Titanium.Web.Proxy.ProxyServer.ServerConnectionCount*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ServerConnectionCount" data-uid="Titanium.Web.Proxy.ProxyServer.ServerConnectionCount">ServerConnectionCount</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ServerConnectionCount" data-uid="Titanium.Web.Proxy.ProxyServer.ServerConnectionCount">ServerConnectionCount</h4>
...@@ -1021,7 +989,7 @@ Default is true (disabled for linux/macOS due to bug in .Net core).</p> ...@@ -1021,7 +989,7 @@ Default is true (disabled for linux/macOS due to bug in .Net core).</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SupportedSslProtocols.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SupportedSslProtocols%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SupportedSslProtocols.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SupportedSslProtocols%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L243">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L232">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_SupportedSslProtocols_" data-uid="Titanium.Web.Proxy.ProxyServer.SupportedSslProtocols*"></a> <a id="Titanium_Web_Proxy_ProxyServer_SupportedSslProtocols_" data-uid="Titanium.Web.Proxy.ProxyServer.SupportedSslProtocols*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_SupportedSslProtocols" data-uid="Titanium.Web.Proxy.ProxyServer.SupportedSslProtocols">SupportedSslProtocols</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_SupportedSslProtocols" data-uid="Titanium.Web.Proxy.ProxyServer.SupportedSslProtocols">SupportedSslProtocols</h4>
...@@ -1052,7 +1020,7 @@ Default is true (disabled for linux/macOS due to bug in .Net core).</p> ...@@ -1052,7 +1020,7 @@ Default is true (disabled for linux/macOS due to bug in .Net core).</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_TcpTimeWaitSeconds.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.TcpTimeWaitSeconds%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_TcpTimeWaitSeconds.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.TcpTimeWaitSeconds%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L217">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L206">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_TcpTimeWaitSeconds_" data-uid="Titanium.Web.Proxy.ProxyServer.TcpTimeWaitSeconds*"></a> <a id="Titanium_Web_Proxy_ProxyServer_TcpTimeWaitSeconds_" data-uid="Titanium.Web.Proxy.ProxyServer.TcpTimeWaitSeconds*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_TcpTimeWaitSeconds" data-uid="Titanium.Web.Proxy.ProxyServer.TcpTimeWaitSeconds">TcpTimeWaitSeconds</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_TcpTimeWaitSeconds" data-uid="Titanium.Web.Proxy.ProxyServer.TcpTimeWaitSeconds">TcpTimeWaitSeconds</h4>
...@@ -1084,7 +1052,7 @@ Default value is 30.</p> ...@@ -1084,7 +1052,7 @@ Default value is 30.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ThreadPoolWorkerThread.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ThreadPoolWorkerThread.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L365">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L354">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_ThreadPoolWorkerThread_" data-uid="Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread*"></a> <a id="Titanium_Web_Proxy_ProxyServer_ThreadPoolWorkerThread_" data-uid="Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ThreadPoolWorkerThread" data-uid="Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread">ThreadPoolWorkerThread</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ThreadPoolWorkerThread" data-uid="Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread">ThreadPoolWorkerThread</h4>
...@@ -1115,7 +1083,7 @@ Default value is 30.</p> ...@@ -1115,7 +1083,7 @@ Default value is 30.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_UpStreamEndPoint.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.UpStreamEndPoint%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_UpStreamEndPoint.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.UpStreamEndPoint%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L271">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L260">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_UpStreamEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamEndPoint*"></a> <a id="Titanium_Web_Proxy_ProxyServer_UpStreamEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamEndPoint*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_UpStreamEndPoint" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamEndPoint">UpStreamEndPoint</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_UpStreamEndPoint" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamEndPoint">UpStreamEndPoint</h4>
...@@ -1147,7 +1115,7 @@ Defaults via any IP addresses of this machine.</p> ...@@ -1147,7 +1115,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_UpStreamHttpProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.UpStreamHttpProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_UpStreamHttpProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.UpStreamHttpProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L260">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L249">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpProxy*"></a> <a id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpProxy" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpProxy">UpStreamHttpProxy</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpProxy" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpProxy">UpStreamHttpProxy</h4>
...@@ -1178,7 +1146,7 @@ Defaults via any IP addresses of this machine.</p> ...@@ -1178,7 +1146,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_UpStreamHttpsProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.UpStreamHttpsProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_UpStreamHttpsProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.UpStreamHttpsProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L265">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L254">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpsProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpsProxy*"></a> <a id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpsProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpsProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpsProxy" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpsProxy">UpStreamHttpsProxy</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpsProxy" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpsProxy">UpStreamHttpsProxy</h4>
...@@ -1211,7 +1179,7 @@ Defaults via any IP addresses of this machine.</p> ...@@ -1211,7 +1179,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_AddEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.AddEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_AddEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.AddEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L371">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L360">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_AddEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.AddEndPoint*"></a> <a id="Titanium_Web_Proxy_ProxyServer_AddEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.AddEndPoint*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_AddEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.AddEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)">AddEndPoint(ProxyEndPoint)</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_AddEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.AddEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)">AddEndPoint(ProxyEndPoint)</h4>
...@@ -1245,7 +1213,7 @@ Defaults via any IP addresses of this machine.</p> ...@@ -1245,7 +1213,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableAllSystemProxies.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableAllSystemProxies%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableAllSystemProxies.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableAllSystemProxies%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L552">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L541">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_DisableAllSystemProxies_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableAllSystemProxies*"></a> <a id="Titanium_Web_Proxy_ProxyServer_DisableAllSystemProxies_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableAllSystemProxies*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_DisableAllSystemProxies" data-uid="Titanium.Web.Proxy.ProxyServer.DisableAllSystemProxies">DisableAllSystemProxies()</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_DisableAllSystemProxies" data-uid="Titanium.Web.Proxy.ProxyServer.DisableAllSystemProxies">DisableAllSystemProxies()</h4>
...@@ -1261,7 +1229,7 @@ Defaults via any IP addresses of this machine.</p> ...@@ -1261,7 +1229,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableSystemHttpProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableSystemHttpProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableSystemHttpProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableSystemHttpProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L508">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L497">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpProxy*"></a> <a id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpProxy" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpProxy">DisableSystemHttpProxy()</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpProxy" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpProxy">DisableSystemHttpProxy()</h4>
...@@ -1277,7 +1245,7 @@ Defaults via any IP addresses of this machine.</p> ...@@ -1277,7 +1245,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableSystemHttpsProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableSystemHttpsProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableSystemHttpsProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableSystemHttpsProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L516">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L505">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpsProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpsProxy*"></a> <a id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpsProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpsProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpsProxy" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpsProxy">DisableSystemHttpsProxy()</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpsProxy" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpsProxy">DisableSystemHttpsProxy()</h4>
...@@ -1293,7 +1261,7 @@ Defaults via any IP addresses of this machine.</p> ...@@ -1293,7 +1261,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableSystemProxy_Titanium_Web_Proxy_Models_ProxyProtocolType_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableSystemProxy(Titanium.Web.Proxy.Models.ProxyProtocolType)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableSystemProxy_Titanium_Web_Proxy_Models_ProxyProtocolType_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableSystemProxy(Titanium.Web.Proxy.Models.ProxyProtocolType)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L538">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L527">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_DisableSystemProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemProxy*"></a> <a id="Titanium_Web_Proxy_ProxyServer_DisableSystemProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_DisableSystemProxy_Titanium_Web_Proxy_Models_ProxyProtocolType_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemProxy(Titanium.Web.Proxy.Models.ProxyProtocolType)">DisableSystemProxy(ProxyProtocolType)</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_DisableSystemProxy_Titanium_Web_Proxy_Models_ProxyProtocolType_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemProxy(Titanium.Web.Proxy.Models.ProxyProtocolType)">DisableSystemProxy(ProxyProtocolType)</h4>
...@@ -1326,7 +1294,7 @@ Defaults via any IP addresses of this machine.</p> ...@@ -1326,7 +1294,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Dispose.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Dispose%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Dispose.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Dispose%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L900">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L889">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_Dispose_" data-uid="Titanium.Web.Proxy.ProxyServer.Dispose*"></a> <a id="Titanium_Web_Proxy_ProxyServer_Dispose_" data-uid="Titanium.Web.Proxy.ProxyServer.Dispose*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_Dispose" data-uid="Titanium.Web.Proxy.ProxyServer.Dispose">Dispose()</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_Dispose" data-uid="Titanium.Web.Proxy.ProxyServer.Dispose">Dispose()</h4>
...@@ -1342,7 +1310,7 @@ Defaults via any IP addresses of this machine.</p> ...@@ -1342,7 +1310,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_RemoveEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.RemoveEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_RemoveEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.RemoveEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L392">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L381">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_RemoveEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.RemoveEndPoint*"></a> <a id="Titanium_Web_Proxy_ProxyServer_RemoveEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.RemoveEndPoint*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_RemoveEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.RemoveEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)">RemoveEndPoint(ProxyEndPoint)</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_RemoveEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.RemoveEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)">RemoveEndPoint(ProxyEndPoint)</h4>
...@@ -1377,7 +1345,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1377,7 +1345,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_RestoreOriginalProxySettings.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.RestoreOriginalProxySettings%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_RestoreOriginalProxySettings.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.RestoreOriginalProxySettings%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L524">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L513">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_RestoreOriginalProxySettings_" data-uid="Titanium.Web.Proxy.ProxyServer.RestoreOriginalProxySettings*"></a> <a id="Titanium_Web_Proxy_ProxyServer_RestoreOriginalProxySettings_" data-uid="Titanium.Web.Proxy.ProxyServer.RestoreOriginalProxySettings*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_RestoreOriginalProxySettings" data-uid="Titanium.Web.Proxy.ProxyServer.RestoreOriginalProxySettings">RestoreOriginalProxySettings()</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_RestoreOriginalProxySettings" data-uid="Titanium.Web.Proxy.ProxyServer.RestoreOriginalProxySettings">RestoreOriginalProxySettings()</h4>
...@@ -1393,7 +1361,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1393,7 +1361,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L411">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L400">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpProxy*"></a> <a id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)">SetAsSystemHttpProxy(ExplicitProxyEndPoint)</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)">SetAsSystemHttpProxy(ExplicitProxyEndPoint)</h4>
...@@ -1427,7 +1395,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1427,7 +1395,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpsProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpsProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpsProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpsProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L420">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L409">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpsProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpsProxy*"></a> <a id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpsProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpsProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpsProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpsProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)">SetAsSystemHttpsProxy(ExplicitProxyEndPoint)</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpsProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpsProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)">SetAsSystemHttpsProxy(ExplicitProxyEndPoint)</h4>
...@@ -1461,7 +1429,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1461,7 +1429,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SetAsSystemProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_Titanium_Web_Proxy_Models_ProxyProtocolType_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SetAsSystemProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint%2CTitanium.Web.Proxy.Models.ProxyProtocolType)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SetAsSystemProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_Titanium_Web_Proxy_Models_ProxyProtocolType_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SetAsSystemProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint%2CTitanium.Web.Proxy.Models.ProxyProtocolType)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L430">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L419">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_SetAsSystemProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemProxy*"></a> <a id="Titanium_Web_Proxy_ProxyServer_SetAsSystemProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_SetAsSystemProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_Titanium_Web_Proxy_Models_ProxyProtocolType_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint,Titanium.Web.Proxy.Models.ProxyProtocolType)">SetAsSystemProxy(ExplicitProxyEndPoint, ProxyProtocolType)</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_SetAsSystemProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_Titanium_Web_Proxy_Models_ProxyProtocolType_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint,Titanium.Web.Proxy.Models.ProxyProtocolType)">SetAsSystemProxy(ExplicitProxyEndPoint, ProxyProtocolType)</h4>
...@@ -1501,7 +1469,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1501,7 +1469,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Start.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Start%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Start.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Start%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L566">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L555">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_Start_" data-uid="Titanium.Web.Proxy.ProxyServer.Start*"></a> <a id="Titanium_Web_Proxy_ProxyServer_Start_" data-uid="Titanium.Web.Proxy.ProxyServer.Start*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_Start" data-uid="Titanium.Web.Proxy.ProxyServer.Start">Start()</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_Start" data-uid="Titanium.Web.Proxy.ProxyServer.Start">Start()</h4>
...@@ -1517,7 +1485,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1517,7 +1485,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Stop.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Stop%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Stop.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Stop%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L626">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L615">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_ProxyServer_Stop_" data-uid="Titanium.Web.Proxy.ProxyServer.Stop*"></a> <a id="Titanium_Web_Proxy_ProxyServer_Stop_" data-uid="Titanium.Web.Proxy.ProxyServer.Stop*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_Stop" data-uid="Titanium.Web.Proxy.ProxyServer.Stop">Stop()</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_Stop" data-uid="Titanium.Web.Proxy.ProxyServer.Stop">Stop()</h4>
...@@ -1535,7 +1503,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1535,7 +1503,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_AfterResponse.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.AfterResponse%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_AfterResponse.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.AfterResponse%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L350">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L339">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_ProxyServer_AfterResponse" data-uid="Titanium.Web.Proxy.ProxyServer.AfterResponse">AfterResponse</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_AfterResponse" data-uid="Titanium.Web.Proxy.ProxyServer.AfterResponse">AfterResponse</h4>
<div class="markdown level1 summary"><p>Intercept after response event from server.</p> <div class="markdown level1 summary"><p>Intercept after response event from server.</p>
...@@ -1565,7 +1533,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1565,7 +1533,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_BeforeRequest.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.BeforeRequest%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_BeforeRequest.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.BeforeRequest%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L340">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L329">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_ProxyServer_BeforeRequest" data-uid="Titanium.Web.Proxy.ProxyServer.BeforeRequest">BeforeRequest</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_BeforeRequest" data-uid="Titanium.Web.Proxy.ProxyServer.BeforeRequest">BeforeRequest</h4>
<div class="markdown level1 summary"><p>Intercept request event to server.</p> <div class="markdown level1 summary"><p>Intercept request event to server.</p>
...@@ -1595,7 +1563,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1595,7 +1563,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_BeforeResponse.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.BeforeResponse%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_BeforeResponse.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.BeforeResponse%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L345">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L334">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_ProxyServer_BeforeResponse" data-uid="Titanium.Web.Proxy.ProxyServer.BeforeResponse">BeforeResponse</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_BeforeResponse" data-uid="Titanium.Web.Proxy.ProxyServer.BeforeResponse">BeforeResponse</h4>
<div class="markdown level1 summary"><p>Intercept response event from server.</p> <div class="markdown level1 summary"><p>Intercept response event from server.</p>
...@@ -1625,7 +1593,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1625,7 +1593,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ClientCertificateSelectionCallback.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ClientCertificateSelectionCallback%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ClientCertificateSelectionCallback.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ClientCertificateSelectionCallback%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L335">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L324">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_ProxyServer_ClientCertificateSelectionCallback" data-uid="Titanium.Web.Proxy.ProxyServer.ClientCertificateSelectionCallback">ClientCertificateSelectionCallback</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ClientCertificateSelectionCallback" data-uid="Titanium.Web.Proxy.ProxyServer.ClientCertificateSelectionCallback">ClientCertificateSelectionCallback</h4>
<div class="markdown level1 summary"><p>Event to override client certificate selection during mutual SSL authentication.</p> <div class="markdown level1 summary"><p>Event to override client certificate selection during mutual SSL authentication.</p>
...@@ -1655,7 +1623,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1655,7 +1623,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ClientConnectionCountChanged.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ClientConnectionCountChanged%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ClientConnectionCountChanged.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ClientConnectionCountChanged%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L320">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L309">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_ProxyServer_ClientConnectionCountChanged" data-uid="Titanium.Web.Proxy.ProxyServer.ClientConnectionCountChanged">ClientConnectionCountChanged</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ClientConnectionCountChanged" data-uid="Titanium.Web.Proxy.ProxyServer.ClientConnectionCountChanged">ClientConnectionCountChanged</h4>
<div class="markdown level1 summary"><p>Event occurs when client connection count changed.</p> <div class="markdown level1 summary"><p>Event occurs when client connection count changed.</p>
...@@ -1685,7 +1653,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1685,7 +1653,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_OnClientConnectionCreate.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.OnClientConnectionCreate%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_OnClientConnectionCreate.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.OnClientConnectionCreate%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L355">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L344">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_ProxyServer_OnClientConnectionCreate" data-uid="Titanium.Web.Proxy.ProxyServer.OnClientConnectionCreate">OnClientConnectionCreate</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_OnClientConnectionCreate" data-uid="Titanium.Web.Proxy.ProxyServer.OnClientConnectionCreate">OnClientConnectionCreate</h4>
<div class="markdown level1 summary"><p>Customize TcpClient used for client connection upon create.</p> <div class="markdown level1 summary"><p>Customize TcpClient used for client connection upon create.</p>
...@@ -1715,7 +1683,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1715,7 +1683,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_OnServerConnectionCreate.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.OnServerConnectionCreate%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_OnServerConnectionCreate.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.OnServerConnectionCreate%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L360">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L349">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_ProxyServer_OnServerConnectionCreate" data-uid="Titanium.Web.Proxy.ProxyServer.OnServerConnectionCreate">OnServerConnectionCreate</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_OnServerConnectionCreate" data-uid="Titanium.Web.Proxy.ProxyServer.OnServerConnectionCreate">OnServerConnectionCreate</h4>
<div class="markdown level1 summary"><p>Customize TcpClient used for server connection upon create.</p> <div class="markdown level1 summary"><p>Customize TcpClient used for server connection upon create.</p>
...@@ -1745,7 +1713,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1745,7 +1713,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ServerCertificateValidationCallback.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ServerCertificateValidationCallback%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ServerCertificateValidationCallback.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ServerCertificateValidationCallback%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L330">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L319">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_ProxyServer_ServerCertificateValidationCallback" data-uid="Titanium.Web.Proxy.ProxyServer.ServerCertificateValidationCallback">ServerCertificateValidationCallback</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ServerCertificateValidationCallback" data-uid="Titanium.Web.Proxy.ProxyServer.ServerCertificateValidationCallback">ServerCertificateValidationCallback</h4>
<div class="markdown level1 summary"><p>Event to override the default verification logic of remote SSL certificate received during authentication.</p> <div class="markdown level1 summary"><p>Event to override the default verification logic of remote SSL certificate received during authentication.</p>
...@@ -1775,7 +1743,7 @@ Will throw error if the end point doesn&apos;t exist.</p> ...@@ -1775,7 +1743,7 @@ Will throw error if the end point doesn&apos;t exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ServerConnectionCountChanged.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ServerConnectionCountChanged%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ServerConnectionCountChanged.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ServerConnectionCountChanged%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L325">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L314">View Source</a>
</span> </span>
<h4 id="Titanium_Web_Proxy_ProxyServer_ServerConnectionCountChanged" data-uid="Titanium.Web.Proxy.ProxyServer.ServerConnectionCountChanged">ServerConnectionCountChanged</h4> <h4 id="Titanium_Web_Proxy_ProxyServer_ServerConnectionCountChanged" data-uid="Titanium.Web.Proxy.ProxyServer.ServerConnectionCountChanged">ServerConnectionCountChanged</h4>
<div class="markdown level1 summary"><p>Event occurs when server connection count changed.</p> <div class="markdown level1 summary"><p>Event occurs when server connection count changed.</p>
......
...@@ -32,17 +32,17 @@ ...@@ -32,17 +32,17 @@
"api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html": { "api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html": {
"href": "api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html", "href": "api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html",
"title": "Class SessionEventArgs | Titanium Web Proxy", "title": "Class SessionEventArgs | Titanium Web Proxy",
"keywords": "Class SessionEventArgs Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. Inheritance Object EventArgs SessionEventArgsBase SessionEventArgs Implements IDisposable Inherited Members SessionEventArgsBase.BufferSize SessionEventArgsBase.BufferPool SessionEventArgsBase.ExceptionFunc SessionEventArgsBase.TimeLine SessionEventArgsBase.UserData SessionEventArgsBase.IsHttps SessionEventArgsBase.ClientEndPoint SessionEventArgsBase.HttpClient SessionEventArgsBase.WebSession SessionEventArgsBase.CustomUpStreamProxyUsed SessionEventArgsBase.LocalEndPoint SessionEventArgsBase.IsTransparent SessionEventArgsBase.Exception SessionEventArgsBase.DataSent SessionEventArgsBase.DataReceived SessionEventArgsBase.TerminateSession() EventArgs.Empty Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public class SessionEventArgs : SessionEventArgsBase, IDisposable Constructors | Improve this Doc View Source SessionEventArgs(ProxyServer, ProxyEndPoint, Request, CancellationTokenSource) Declaration protected SessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, Request request, CancellationTokenSource cancellationTokenSource) Parameters Type Name Description ProxyServer server ProxyEndPoint endPoint Request request CancellationTokenSource cancellationTokenSource Properties | Improve this Doc View Source IsPromise Is this session a HTTP/2 promise? Declaration public bool IsPromise { get; } Property Value Type Description Boolean | Improve this Doc View Source ReRequest Should we send the request again ? Declaration public bool ReRequest { get; set; } Property Value Type Description Boolean Methods | Improve this Doc View Source Dispose() Implement any cleanup here Declaration public override void Dispose() Overrides SessionEventArgsBase.Dispose() | Improve this Doc View Source GenericResponse(Byte[], HttpStatusCode, Dictionary<String, HttpHeader>, Boolean) Before request is made to server respond with the specified byte[], the specified status to client. And then ignore the request. Declaration public void GenericResponse(byte[] result, HttpStatusCode status, Dictionary<string, HttpHeader> headers, bool closeServerConnection = false) Parameters Type Name Description Byte [] result The bytes to sent. HttpStatusCode status The HTTP status code. Dictionary < String , HttpHeader > headers The HTTP headers. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source GenericResponse(String, HttpStatusCode, Dictionary<String, HttpHeader>, Boolean) Before request is made to server respond with the specified HTML string and the specified status to client. And then ignore the request. Declaration public void GenericResponse(string html, HttpStatusCode status, Dictionary<string, HttpHeader> headers = null, bool closeServerConnection = false) Parameters Type Name Description String html The html content. HttpStatusCode status The HTTP status code. Dictionary < String , HttpHeader > headers The HTTP headers. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source GetRequestBody(CancellationToken) Gets the request body as bytes. Declaration public Task<byte[]> GetRequestBody(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < Byte []> The body as bytes. | Improve this Doc View Source GetRequestBodyAsString(CancellationToken) Gets the request body as string. Declaration public Task<string> GetRequestBodyAsString(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < String > The body as string. | Improve this Doc View Source GetResponseBody(CancellationToken) Gets the response body as bytes. Declaration public Task<byte[]> GetResponseBody(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < Byte []> The resulting bytes. | Improve this Doc View Source GetResponseBodyAsString(CancellationToken) Gets the response body as string. Declaration public Task<string> GetResponseBodyAsString(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < String > The string body. | Improve this Doc View Source Ok(Byte[], Dictionary<String, HttpHeader>, Boolean) Before request is made to server respond with the specified byte[] to client and ignore the request. Declaration public void Ok(byte[] result, Dictionary<string, HttpHeader> headers = null, bool closeServerConnection = false) Parameters Type Name Description Byte [] result The html content bytes. Dictionary < String , HttpHeader > headers The HTTP headers. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source Ok(String, Dictionary<String, HttpHeader>, Boolean) Before request is made to server respond with the specified HTML string to client and ignore the request. Declaration public void Ok(string html, Dictionary<string, HttpHeader> headers = null, bool closeServerConnection = false) Parameters Type Name Description String html HTML content to sent. Dictionary < String , HttpHeader > headers HTTP response headers. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source Redirect(String, Boolean) Redirect to provided URL. Declaration public void Redirect(string url, bool closeServerConnection = false) Parameters Type Name Description String url The URL to redirect. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source Respond(Response, Boolean) Respond with given response object to client. Declaration public void Respond(Response response, bool closeServerConnection = false) Parameters Type Name Description Response response The response object. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source SetRequestBody(Byte[]) Sets the request body. Declaration public void SetRequestBody(byte[] body) Parameters Type Name Description Byte [] body The request body bytes. | Improve this Doc View Source SetRequestBodyString(String) Sets the body with the specified string. Declaration public void SetRequestBodyString(string body) Parameters Type Name Description String body The request body string to set. | Improve this Doc View Source SetResponseBody(Byte[]) Set the response body bytes. Declaration public void SetResponseBody(byte[] body) Parameters Type Name Description Byte [] body The body bytes to set. | Improve this Doc View Source SetResponseBodyString(String) Replace the response body with the specified string. Declaration public void SetResponseBodyString(string body) Parameters Type Name Description String body The body string to set. | Improve this Doc View Source TerminateServerConnection() Terminate the connection to server at the end of this HTTP request/response session. Declaration public void TerminateServerConnection() Events | Improve this Doc View Source MultipartRequestPartSent Occurs when multipart request part sent. Declaration public event EventHandler<MultipartRequestPartSentEventArgs> MultipartRequestPartSent Event Type Type Description EventHandler < MultipartRequestPartSentEventArgs > Implements System.IDisposable" "keywords": "Class SessionEventArgs Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. Inheritance Object EventArgs SessionEventArgsBase SessionEventArgs Implements IDisposable Inherited Members SessionEventArgsBase.BufferPool SessionEventArgsBase.ExceptionFunc SessionEventArgsBase.TimeLine SessionEventArgsBase.UserData SessionEventArgsBase.IsHttps SessionEventArgsBase.ClientEndPoint SessionEventArgsBase.HttpClient SessionEventArgsBase.WebSession SessionEventArgsBase.CustomUpStreamProxyUsed SessionEventArgsBase.LocalEndPoint SessionEventArgsBase.IsTransparent SessionEventArgsBase.Exception SessionEventArgsBase.DataSent SessionEventArgsBase.DataReceived SessionEventArgsBase.TerminateSession() EventArgs.Empty Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public class SessionEventArgs : SessionEventArgsBase, IDisposable Constructors | Improve this Doc View Source SessionEventArgs(ProxyServer, ProxyEndPoint, Request, CancellationTokenSource) Declaration protected SessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, Request request, CancellationTokenSource cancellationTokenSource) Parameters Type Name Description ProxyServer server ProxyEndPoint endPoint Request request CancellationTokenSource cancellationTokenSource Properties | Improve this Doc View Source IsPromise Is this session a HTTP/2 promise? Declaration public bool IsPromise { get; } Property Value Type Description Boolean | Improve this Doc View Source ReRequest Should we send the request again ? Declaration public bool ReRequest { get; set; } Property Value Type Description Boolean Methods | Improve this Doc View Source Dispose() Implement any cleanup here Declaration public override void Dispose() Overrides SessionEventArgsBase.Dispose() | Improve this Doc View Source GenericResponse(Byte[], HttpStatusCode, Dictionary<String, HttpHeader>, Boolean) Before request is made to server respond with the specified byte[], the specified status to client. And then ignore the request. Declaration public void GenericResponse(byte[] result, HttpStatusCode status, Dictionary<string, HttpHeader> headers, bool closeServerConnection = false) Parameters Type Name Description Byte [] result The bytes to sent. HttpStatusCode status The HTTP status code. Dictionary < String , HttpHeader > headers The HTTP headers. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source GenericResponse(String, HttpStatusCode, Dictionary<String, HttpHeader>, Boolean) Before request is made to server respond with the specified HTML string and the specified status to client. And then ignore the request. Declaration public void GenericResponse(string html, HttpStatusCode status, Dictionary<string, HttpHeader> headers = null, bool closeServerConnection = false) Parameters Type Name Description String html The html content. HttpStatusCode status The HTTP status code. Dictionary < String , HttpHeader > headers The HTTP headers. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source GetRequestBody(CancellationToken) Gets the request body as bytes. Declaration public Task<byte[]> GetRequestBody(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < Byte []> The body as bytes. | Improve this Doc View Source GetRequestBodyAsString(CancellationToken) Gets the request body as string. Declaration public Task<string> GetRequestBodyAsString(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < String > The body as string. | Improve this Doc View Source GetResponseBody(CancellationToken) Gets the response body as bytes. Declaration public Task<byte[]> GetResponseBody(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < Byte []> The resulting bytes. | Improve this Doc View Source GetResponseBodyAsString(CancellationToken) Gets the response body as string. Declaration public Task<string> GetResponseBodyAsString(CancellationToken cancellationToken = default(CancellationToken)) Parameters Type Name Description CancellationToken cancellationToken Optional cancellation token for this async task. Returns Type Description Task < String > The string body. | Improve this Doc View Source Ok(Byte[], Dictionary<String, HttpHeader>, Boolean) Before request is made to server respond with the specified byte[] to client and ignore the request. Declaration public void Ok(byte[] result, Dictionary<string, HttpHeader> headers = null, bool closeServerConnection = false) Parameters Type Name Description Byte [] result The html content bytes. Dictionary < String , HttpHeader > headers The HTTP headers. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source Ok(String, Dictionary<String, HttpHeader>, Boolean) Before request is made to server respond with the specified HTML string to client and ignore the request. Declaration public void Ok(string html, Dictionary<string, HttpHeader> headers = null, bool closeServerConnection = false) Parameters Type Name Description String html HTML content to sent. Dictionary < String , HttpHeader > headers HTTP response headers. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source Redirect(String, Boolean) Redirect to provided URL. Declaration public void Redirect(string url, bool closeServerConnection = false) Parameters Type Name Description String url The URL to redirect. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source Respond(Response, Boolean) Respond with given response object to client. Declaration public void Respond(Response response, bool closeServerConnection = false) Parameters Type Name Description Response response The response object. Boolean closeServerConnection Close the server connection used by request if any? | Improve this Doc View Source SetRequestBody(Byte[]) Sets the request body. Declaration public void SetRequestBody(byte[] body) Parameters Type Name Description Byte [] body The request body bytes. | Improve this Doc View Source SetRequestBodyString(String) Sets the body with the specified string. Declaration public void SetRequestBodyString(string body) Parameters Type Name Description String body The request body string to set. | Improve this Doc View Source SetResponseBody(Byte[]) Set the response body bytes. Declaration public void SetResponseBody(byte[] body) Parameters Type Name Description Byte [] body The body bytes to set. | Improve this Doc View Source SetResponseBodyString(String) Replace the response body with the specified string. Declaration public void SetResponseBodyString(string body) Parameters Type Name Description String body The body string to set. | Improve this Doc View Source TerminateServerConnection() Terminate the connection to server at the end of this HTTP request/response session. Declaration public void TerminateServerConnection() Events | Improve this Doc View Source MultipartRequestPartSent Occurs when multipart request part sent. Declaration public event EventHandler<MultipartRequestPartSentEventArgs> MultipartRequestPartSent Event Type Type Description EventHandler < MultipartRequestPartSentEventArgs > Implements System.IDisposable"
}, },
"api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html": { "api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html": {
"href": "api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html", "href": "api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html",
"title": "Class SessionEventArgsBase | Titanium Web Proxy", "title": "Class SessionEventArgsBase | Titanium Web Proxy",
"keywords": "Class SessionEventArgsBase Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. Inheritance Object EventArgs SessionEventArgsBase SessionEventArgs TunnelConnectSessionEventArgs Implements IDisposable Inherited Members EventArgs.Empty Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public abstract class SessionEventArgsBase : EventArgs, IDisposable Constructors | Improve this Doc View Source SessionEventArgsBase(ProxyServer, ProxyEndPoint, CancellationTokenSource, Request) Declaration protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, Request request) Parameters Type Name Description ProxyServer server ProxyEndPoint endPoint CancellationTokenSource cancellationTokenSource Request request Fields | Improve this Doc View Source BufferPool Declaration protected readonly IBufferPool BufferPool Field Value Type Description IBufferPool | Improve this Doc View Source BufferSize Declaration protected readonly int BufferSize Field Value Type Description Int32 | Improve this Doc View Source ExceptionFunc Declaration protected readonly ExceptionHandler ExceptionFunc Field Value Type Description ExceptionHandler Properties | Improve this Doc View Source ClientEndPoint Client End Point. Declaration public IPEndPoint ClientEndPoint { get; } Property Value Type Description IPEndPoint | Improve this Doc View Source CustomUpStreamProxyUsed Are we using a custom upstream HTTP(S) proxy? Declaration public ExternalProxy CustomUpStreamProxyUsed { get; } Property Value Type Description ExternalProxy | Improve this Doc View Source Exception The last exception that happened. Declaration public Exception Exception { get; } Property Value Type Description Exception | Improve this Doc View Source HttpClient The web client used to communicate with server for this session. Declaration public HttpWebClient HttpClient { get; } Property Value Type Description HttpWebClient | Improve this Doc View Source IsHttps Does this session uses SSL? Declaration public bool IsHttps { get; } Property Value Type Description Boolean | Improve this Doc View Source IsTransparent Is this a transparent endpoint? Declaration public bool IsTransparent { get; } Property Value Type Description Boolean | Improve this Doc View Source LocalEndPoint Local endpoint via which we make the request. Declaration public ProxyEndPoint LocalEndPoint { get; } Property Value Type Description ProxyEndPoint | Improve this Doc View Source TimeLine Relative milliseconds for various events. Declaration public Dictionary<string, DateTime> TimeLine { get; } Property Value Type Description Dictionary < String , DateTime > | Improve this Doc View Source UserData Returns a user data for this request/response session which is same as the user data of HttpClient. Declaration public object UserData { get; set; } Property Value Type Description Object | Improve this Doc View Source WebSession Declaration [Obsolete(\"Use HttpClient instead.\")] public HttpWebClient WebSession { get; } Property Value Type Description HttpWebClient Methods | Improve this Doc View Source Dispose() Implements cleanup here. Declaration public virtual void Dispose() | Improve this Doc View Source TerminateSession() Terminates the session abruptly by terminating client/server connections. Declaration public void TerminateSession() Events | Improve this Doc View Source DataReceived Fired when data is received within this session from client/server. Declaration public event EventHandler<DataEventArgs> DataReceived Event Type Type Description EventHandler < DataEventArgs > | Improve this Doc View Source DataSent Fired when data is sent within this session to server/client. Declaration public event EventHandler<DataEventArgs> DataSent Event Type Type Description EventHandler < DataEventArgs > Implements System.IDisposable" "keywords": "Class SessionEventArgsBase Holds info related to a single proxy session (single request/response sequence). A proxy session is bounded to a single connection from client. A proxy session ends when client terminates connection to proxy or when server terminates connection from proxy. Inheritance Object EventArgs SessionEventArgsBase SessionEventArgs TunnelConnectSessionEventArgs Implements IDisposable Inherited Members EventArgs.Empty Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public abstract class SessionEventArgsBase : EventArgs, IDisposable Constructors | Improve this Doc View Source SessionEventArgsBase(ProxyServer, ProxyEndPoint, CancellationTokenSource, Request) Declaration protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, CancellationTokenSource cancellationTokenSource, Request request) Parameters Type Name Description ProxyServer server ProxyEndPoint endPoint CancellationTokenSource cancellationTokenSource Request request Fields | Improve this Doc View Source BufferPool Declaration protected readonly IBufferPool BufferPool Field Value Type Description IBufferPool | Improve this Doc View Source ExceptionFunc Declaration protected readonly ExceptionHandler ExceptionFunc Field Value Type Description ExceptionHandler Properties | Improve this Doc View Source ClientEndPoint Client End Point. Declaration public IPEndPoint ClientEndPoint { get; } Property Value Type Description IPEndPoint | Improve this Doc View Source CustomUpStreamProxyUsed Are we using a custom upstream HTTP(S) proxy? Declaration public ExternalProxy CustomUpStreamProxyUsed { get; } Property Value Type Description ExternalProxy | Improve this Doc View Source Exception The last exception that happened. Declaration public Exception Exception { get; } Property Value Type Description Exception | Improve this Doc View Source HttpClient The web client used to communicate with server for this session. Declaration public HttpWebClient HttpClient { get; } Property Value Type Description HttpWebClient | Improve this Doc View Source IsHttps Does this session uses SSL? Declaration public bool IsHttps { get; } Property Value Type Description Boolean | Improve this Doc View Source IsTransparent Is this a transparent endpoint? Declaration public bool IsTransparent { get; } Property Value Type Description Boolean | Improve this Doc View Source LocalEndPoint Local endpoint via which we make the request. Declaration public ProxyEndPoint LocalEndPoint { get; } Property Value Type Description ProxyEndPoint | Improve this Doc View Source TimeLine Relative milliseconds for various events. Declaration public Dictionary<string, DateTime> TimeLine { get; } Property Value Type Description Dictionary < String , DateTime > | Improve this Doc View Source UserData Returns a user data for this request/response session which is same as the user data of HttpClient. Declaration public object UserData { get; set; } Property Value Type Description Object | Improve this Doc View Source WebSession Declaration [Obsolete(\"Use HttpClient instead.\")] public HttpWebClient WebSession { get; } Property Value Type Description HttpWebClient Methods | Improve this Doc View Source Dispose() Implements cleanup here. Declaration public virtual void Dispose() | Improve this Doc View Source TerminateSession() Terminates the session abruptly by terminating client/server connections. Declaration public void TerminateSession() Events | Improve this Doc View Source DataReceived Fired when data is received within this session from client/server. Declaration public event EventHandler<DataEventArgs> DataReceived Event Type Type Description EventHandler < DataEventArgs > | Improve this Doc View Source DataSent Fired when data is sent within this session to server/client. Declaration public event EventHandler<DataEventArgs> DataSent Event Type Type Description EventHandler < DataEventArgs > Implements System.IDisposable"
}, },
"api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html": { "api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html": {
"href": "api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html", "href": "api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html",
"title": "Class TunnelConnectSessionEventArgs | Titanium Web Proxy", "title": "Class TunnelConnectSessionEventArgs | Titanium Web Proxy",
"keywords": "Class TunnelConnectSessionEventArgs A class that wraps the state when a tunnel connect event happen for Explicit endpoints. Inheritance Object EventArgs SessionEventArgsBase TunnelConnectSessionEventArgs Implements IDisposable Inherited Members SessionEventArgsBase.BufferSize SessionEventArgsBase.BufferPool SessionEventArgsBase.ExceptionFunc SessionEventArgsBase.TimeLine SessionEventArgsBase.UserData SessionEventArgsBase.IsHttps SessionEventArgsBase.ClientEndPoint SessionEventArgsBase.HttpClient SessionEventArgsBase.WebSession SessionEventArgsBase.CustomUpStreamProxyUsed SessionEventArgsBase.LocalEndPoint SessionEventArgsBase.IsTransparent SessionEventArgsBase.Exception SessionEventArgsBase.Dispose() SessionEventArgsBase.DataSent SessionEventArgsBase.DataReceived SessionEventArgsBase.TerminateSession() EventArgs.Empty Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public class TunnelConnectSessionEventArgs : SessionEventArgsBase, IDisposable Properties | Improve this Doc View Source DecryptSsl Should we decrypt the Ssl or relay it to server? Default is true. Declaration public bool DecryptSsl { get; set; } Property Value Type Description Boolean | Improve this Doc View Source DenyConnect When set to true it denies the connect request with a Forbidden status. Declaration public bool DenyConnect { get; set; } Property Value Type Description Boolean | Improve this Doc View Source IsHttpsConnect Is this a connect request to secure HTTP server? Or is it to some other protocol. Declaration public bool IsHttpsConnect { get; } Property Value Type Description Boolean Implements System.IDisposable" "keywords": "Class TunnelConnectSessionEventArgs A class that wraps the state when a tunnel connect event happen for Explicit endpoints. Inheritance Object EventArgs SessionEventArgsBase TunnelConnectSessionEventArgs Implements IDisposable Inherited Members SessionEventArgsBase.BufferPool SessionEventArgsBase.ExceptionFunc SessionEventArgsBase.TimeLine SessionEventArgsBase.UserData SessionEventArgsBase.IsHttps SessionEventArgsBase.ClientEndPoint SessionEventArgsBase.HttpClient SessionEventArgsBase.WebSession SessionEventArgsBase.CustomUpStreamProxyUsed SessionEventArgsBase.LocalEndPoint SessionEventArgsBase.IsTransparent SessionEventArgsBase.Exception SessionEventArgsBase.Dispose() SessionEventArgsBase.DataSent SessionEventArgsBase.DataReceived SessionEventArgsBase.TerminateSession() EventArgs.Empty Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.EventArguments Assembly : Titanium.Web.Proxy.dll Syntax public class TunnelConnectSessionEventArgs : SessionEventArgsBase, IDisposable Properties | Improve this Doc View Source DecryptSsl Should we decrypt the Ssl or relay it to server? Default is true. Declaration public bool DecryptSsl { get; set; } Property Value Type Description Boolean | Improve this Doc View Source DenyConnect When set to true it denies the connect request with a Forbidden status. Declaration public bool DenyConnect { get; set; } Property Value Type Description Boolean | Improve this Doc View Source IsHttpsConnect Is this a connect request to secure HTTP server? Or is it to some other protocol. Declaration public bool IsHttpsConnect { get; } Property Value Type Description Boolean Events | Improve this Doc View Source DecryptedDataReceived Fired when decrypted data is received within this session from client/server. Declaration public event EventHandler<DataEventArgs> DecryptedDataReceived Event Type Type Description EventHandler < DataEventArgs > | Improve this Doc View Source DecryptedDataSent Fired when decrypted data is sent within this session to server/client. Declaration public event EventHandler<DataEventArgs> DecryptedDataSent Event Type Type Description EventHandler < DataEventArgs > Implements System.IDisposable"
}, },
"api/Titanium.Web.Proxy.ExceptionHandler.html": { "api/Titanium.Web.Proxy.ExceptionHandler.html": {
"href": "api/Titanium.Web.Proxy.ExceptionHandler.html", "href": "api/Titanium.Web.Proxy.ExceptionHandler.html",
...@@ -217,7 +217,7 @@ ...@@ -217,7 +217,7 @@
"api/Titanium.Web.Proxy.Models.ExplicitProxyEndPoint.html": { "api/Titanium.Web.Proxy.Models.ExplicitProxyEndPoint.html": {
"href": "api/Titanium.Web.Proxy.Models.ExplicitProxyEndPoint.html", "href": "api/Titanium.Web.Proxy.Models.ExplicitProxyEndPoint.html",
"title": "Class ExplicitProxyEndPoint | Titanium Web Proxy", "title": "Class ExplicitProxyEndPoint | Titanium Web Proxy",
"keywords": "Class ExplicitProxyEndPoint A proxy endpoint that the client is aware of. So client application know that it is communicating with a proxy server. Inheritance Object ProxyEndPoint ExplicitProxyEndPoint Inherited Members ProxyEndPoint.IpAddress ProxyEndPoint.Port ProxyEndPoint.DecryptSsl ProxyEndPoint.IpV6Enabled ProxyEndPoint.GenericCertificate Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.Models Assembly : Titanium.Web.Proxy.dll Syntax public class ExplicitProxyEndPoint : ProxyEndPoint Constructors | Improve this Doc View Source ExplicitProxyEndPoint(IPAddress, Int32, Boolean) Constructor. Declaration public ExplicitProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) Parameters Type Name Description IPAddress ipAddress Listening IP address. Int32 port Listening port. Boolean decryptSsl Should we decrypt ssl? Events | Improve this Doc View Source BeforeTunnelConnectRequest Intercept tunnel connect request. Valid only for explicit endpoints. Set the DecryptSsl property to false if this HTTP connect request shouldn't be decrypted and instead be relayed. Declaration public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectRequest Event Type Type Description AsyncEventHandler < TunnelConnectSessionEventArgs > | Improve this Doc View Source BeforeTunnelConnectResponse Intercept tunnel connect response. Valid only for explicit endpoints. Declaration public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectResponse Event Type Type Description AsyncEventHandler < TunnelConnectSessionEventArgs >" "keywords": "Class ExplicitProxyEndPoint A proxy endpoint that the client is aware of. So client application know that it is communicating with a proxy server. Inheritance Object ProxyEndPoint ExplicitProxyEndPoint Inherited Members ProxyEndPoint.IpAddress ProxyEndPoint.Port ProxyEndPoint.DecryptSsl ProxyEndPoint.GenericCertificate Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.Models Assembly : Titanium.Web.Proxy.dll Syntax public class ExplicitProxyEndPoint : ProxyEndPoint Constructors | Improve this Doc View Source ExplicitProxyEndPoint(IPAddress, Int32, Boolean) Constructor. Declaration public ExplicitProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) Parameters Type Name Description IPAddress ipAddress Listening IP address. Int32 port Listening port. Boolean decryptSsl Should we decrypt ssl? Events | Improve this Doc View Source BeforeTunnelConnectRequest Intercept tunnel connect request. Valid only for explicit endpoints. Set the DecryptSsl property to false if this HTTP connect request shouldn't be decrypted and instead be relayed. Declaration public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectRequest Event Type Type Description AsyncEventHandler < TunnelConnectSessionEventArgs > | Improve this Doc View Source BeforeTunnelConnectResponse Intercept tunnel connect response. Valid only for explicit endpoints. Declaration public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectResponse Event Type Type Description AsyncEventHandler < TunnelConnectSessionEventArgs >"
}, },
"api/Titanium.Web.Proxy.Models.ExternalProxy.html": { "api/Titanium.Web.Proxy.Models.ExternalProxy.html": {
"href": "api/Titanium.Web.Proxy.Models.ExternalProxy.html", "href": "api/Titanium.Web.Proxy.Models.ExternalProxy.html",
...@@ -247,7 +247,7 @@ ...@@ -247,7 +247,7 @@
"api/Titanium.Web.Proxy.Models.ProxyEndPoint.html": { "api/Titanium.Web.Proxy.Models.ProxyEndPoint.html": {
"href": "api/Titanium.Web.Proxy.Models.ProxyEndPoint.html", "href": "api/Titanium.Web.Proxy.Models.ProxyEndPoint.html",
"title": "Class ProxyEndPoint | Titanium Web Proxy", "title": "Class ProxyEndPoint | Titanium Web Proxy",
"keywords": "Class ProxyEndPoint An abstract endpoint where the proxy listens Inheritance Object ProxyEndPoint ExplicitProxyEndPoint TransparentProxyEndPoint Inherited Members Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.Models Assembly : Titanium.Web.Proxy.dll Syntax public abstract class ProxyEndPoint Constructors | Improve this Doc View Source ProxyEndPoint(IPAddress, Int32, Boolean) Constructor. Declaration protected ProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl) Parameters Type Name Description IPAddress ipAddress Int32 port Boolean decryptSsl Properties | Improve this Doc View Source DecryptSsl Enable SSL? Declaration public bool DecryptSsl { get; } Property Value Type Description Boolean | Improve this Doc View Source GenericCertificate Generic certificate to use for SSL decryption. Declaration public X509Certificate2 GenericCertificate { get; set; } Property Value Type Description X509Certificate2 | Improve this Doc View Source IpAddress Ip Address we are listening. Declaration public IPAddress IpAddress { get; } Property Value Type Description IPAddress | Improve this Doc View Source IpV6Enabled Is IPv6 enabled? Declaration public bool IpV6Enabled { get; } Property Value Type Description Boolean | Improve this Doc View Source Port Port we are listening. Declaration public int Port { get; } Property Value Type Description Int32" "keywords": "Class ProxyEndPoint An abstract endpoint where the proxy listens Inheritance Object ProxyEndPoint ExplicitProxyEndPoint TransparentProxyEndPoint Inherited Members Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.Models Assembly : Titanium.Web.Proxy.dll Syntax public abstract class ProxyEndPoint Constructors | Improve this Doc View Source ProxyEndPoint(IPAddress, Int32, Boolean) Constructor. Declaration protected ProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl) Parameters Type Name Description IPAddress ipAddress Int32 port Boolean decryptSsl Properties | Improve this Doc View Source DecryptSsl Enable SSL? Declaration public bool DecryptSsl { get; } Property Value Type Description Boolean | Improve this Doc View Source GenericCertificate Generic certificate to use for SSL decryption. Declaration public X509Certificate2 GenericCertificate { get; set; } Property Value Type Description X509Certificate2 | Improve this Doc View Source IpAddress Ip Address we are listening. Declaration public IPAddress IpAddress { get; } Property Value Type Description IPAddress | Improve this Doc View Source Port Port we are listening. Declaration public int Port { get; } Property Value Type Description Int32"
}, },
"api/Titanium.Web.Proxy.Models.ProxyProtocolType.html": { "api/Titanium.Web.Proxy.Models.ProxyProtocolType.html": {
"href": "api/Titanium.Web.Proxy.Models.ProxyProtocolType.html", "href": "api/Titanium.Web.Proxy.Models.ProxyProtocolType.html",
...@@ -257,7 +257,7 @@ ...@@ -257,7 +257,7 @@
"api/Titanium.Web.Proxy.Models.TransparentProxyEndPoint.html": { "api/Titanium.Web.Proxy.Models.TransparentProxyEndPoint.html": {
"href": "api/Titanium.Web.Proxy.Models.TransparentProxyEndPoint.html", "href": "api/Titanium.Web.Proxy.Models.TransparentProxyEndPoint.html",
"title": "Class TransparentProxyEndPoint | Titanium Web Proxy", "title": "Class TransparentProxyEndPoint | Titanium Web Proxy",
"keywords": "Class TransparentProxyEndPoint A proxy end point client is not aware of. Useful when requests are redirected to this proxy end point through port forwarding via router. Inheritance Object ProxyEndPoint TransparentProxyEndPoint Inherited Members ProxyEndPoint.IpAddress ProxyEndPoint.Port ProxyEndPoint.DecryptSsl ProxyEndPoint.IpV6Enabled ProxyEndPoint.GenericCertificate Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.Models Assembly : Titanium.Web.Proxy.dll Syntax public class TransparentProxyEndPoint : ProxyEndPoint Constructors | Improve this Doc View Source TransparentProxyEndPoint(IPAddress, Int32, Boolean) Initialize a new instance. Declaration public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) Parameters Type Name Description IPAddress ipAddress Listening Ip address. Int32 port Listening port. Boolean decryptSsl Should we decrypt ssl? Properties | Improve this Doc View Source GenericCertificateName Name of the Certificate need to be sent (same as the hostname we want to proxy). This is valid only when UseServerNameIndication is set to false. Declaration public string GenericCertificateName { get; set; } Property Value Type Description String Events | Improve this Doc View Source BeforeSslAuthenticate Before Ssl authentication this event is fired. Declaration public event AsyncEventHandler<BeforeSslAuthenticateEventArgs> BeforeSslAuthenticate Event Type Type Description AsyncEventHandler < BeforeSslAuthenticateEventArgs >" "keywords": "Class TransparentProxyEndPoint A proxy end point client is not aware of. Useful when requests are redirected to this proxy end point through port forwarding via router. Inheritance Object ProxyEndPoint TransparentProxyEndPoint Inherited Members ProxyEndPoint.IpAddress ProxyEndPoint.Port ProxyEndPoint.DecryptSsl ProxyEndPoint.GenericCertificate Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy.Models Assembly : Titanium.Web.Proxy.dll Syntax public class TransparentProxyEndPoint : ProxyEndPoint Constructors | Improve this Doc View Source TransparentProxyEndPoint(IPAddress, Int32, Boolean) Initialize a new instance. Declaration public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool decryptSsl = true) Parameters Type Name Description IPAddress ipAddress Listening Ip address. Int32 port Listening port. Boolean decryptSsl Should we decrypt ssl? Properties | Improve this Doc View Source GenericCertificateName Name of the Certificate need to be sent (same as the hostname we want to proxy). This is valid only when UseServerNameIndication is set to false. Declaration public string GenericCertificateName { get; set; } Property Value Type Description String Events | Improve this Doc View Source BeforeSslAuthenticate Before Ssl authentication this event is fired. Declaration public event AsyncEventHandler<BeforeSslAuthenticateEventArgs> BeforeSslAuthenticate Event Type Type Description AsyncEventHandler < BeforeSslAuthenticateEventArgs >"
}, },
"api/Titanium.Web.Proxy.Network.CertificateEngine.html": { "api/Titanium.Web.Proxy.Network.CertificateEngine.html": {
"href": "api/Titanium.Web.Proxy.Network.CertificateEngine.html", "href": "api/Titanium.Web.Proxy.Network.CertificateEngine.html",
...@@ -277,6 +277,6 @@ ...@@ -277,6 +277,6 @@
"api/Titanium.Web.Proxy.ProxyServer.html": { "api/Titanium.Web.Proxy.ProxyServer.html": {
"href": "api/Titanium.Web.Proxy.ProxyServer.html", "href": "api/Titanium.Web.Proxy.ProxyServer.html",
"title": "Class ProxyServer | Titanium Web Proxy", "title": "Class ProxyServer | Titanium Web Proxy",
"keywords": "Class ProxyServer This class is the backbone of proxy. One can create as many instances as needed. However care should be taken to avoid using the same listening ports across multiple instances. Inheritance Object ProxyServer Implements IDisposable Inherited Members Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy Assembly : Titanium.Web.Proxy.dll Syntax public class ProxyServer : IDisposable Constructors | Improve this Doc View Source ProxyServer(Boolean, Boolean, Boolean) Initializes a new instance of ProxyServer class with provided parameters. Declaration public ProxyServer(bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) Parameters Type Name Description Boolean userTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's user certificate store? Boolean machineTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's certificate store? Boolean trustRootCertificateAsAdmin Should we attempt to trust certificates with elevated permissions by prompting for UAC if required? | Improve this Doc View Source ProxyServer(String, String, Boolean, Boolean, Boolean) Initializes a new instance of ProxyServer class with provided parameters. Declaration public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) Parameters Type Name Description String rootCertificateName Name of the root certificate. String rootCertificateIssuerName Name of the root certificate issuer. Boolean userTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's user certificate store? Boolean machineTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's certificate store? Boolean trustRootCertificateAsAdmin Should we attempt to trust certificates with elevated permissions by prompting for UAC if required? Properties | Improve this Doc View Source BufferPool The buffer pool used throughout this proxy instance. Set custom implementations by implementing this interface. By default this uses DefaultBufferPool implementation available in StreamExtended library package. Declaration public IBufferPool BufferPool { get; set; } Property Value Type Description IBufferPool | Improve this Doc View Source BufferSize Buffer size in bytes used throughout this proxy. Default value is 8192 bytes. Declaration public int BufferSize { get; set; } Property Value Type Description Int32 | Improve this Doc View Source CertificateManager Manages certificates used by this proxy. Declaration public CertificateManager CertificateManager { get; } Property Value Type Description CertificateManager | Improve this Doc View Source CheckCertificateRevocation Should we check for certificate revocation during SSL authentication to servers Note: If enabled can reduce performance. Defaults to false. Declaration public X509RevocationMode CheckCertificateRevocation { get; set; } Property Value Type Description X509RevocationMode | Improve this Doc View Source ClientConnectionCount Total number of active client connections. Declaration public int ClientConnectionCount { get; } Property Value Type Description Int32 | Improve this Doc View Source ConnectionTimeOutSeconds Seconds client/server connection are to be kept alive when waiting for read/write to complete. This will also determine the pool eviction time when connection pool is enabled. Default value is 60 seconds. Declaration public int ConnectionTimeOutSeconds { get; set; } Property Value Type Description Int32 | Improve this Doc View Source Enable100ContinueBehaviour Does this proxy uses the HTTP protocol 100 continue behaviour strictly? Broken 100 continue implementations on server/client may cause problems if enabled. Defaults to false. Declaration public bool Enable100ContinueBehaviour { get; set; } Property Value Type Description Boolean | Improve this Doc View Source EnableConnectionPool Should we enable experimental server connection pool? Defaults to true. Declaration public bool EnableConnectionPool { get; set; } Property Value Type Description Boolean | Improve this Doc View Source EnableHttp2 Enable disable HTTP/2 support. Warning: HTTP/2 support is very limited only enabled when both client and server supports it (no protocol changing in proxy) cannot modify the request/response (e.g header modifications in BeforeRequest/Response events are ignored) Declaration public bool EnableHttp2 { get; set; } Property Value Type Description Boolean | Improve this Doc View Source EnableTcpServerConnectionPrefetch Should we enable tcp server connection prefetching? When enabled, as soon as we receive a client connection we concurrently initiate corresponding server connection process using CONNECT hostname or SNI hostname on a separate task so that after parsing client request we will have the server connection immediately ready or in the process of getting ready. If a server connection is available in cache then this prefetch task will immediately return with the available connection from cache. Defaults to true. Declaration public bool EnableTcpServerConnectionPrefetch { get; set; } Property Value Type Description Boolean | Improve this Doc View Source EnableWinAuth Enable disable Windows Authentication (NTLM/Kerberos). Note: NTLM/Kerberos will always send local credentials of current user running the proxy process. This is because a man in middle attack with Windows domain authentication is not currently supported. Defaults to false. Declaration public bool EnableWinAuth { get; set; } Property Value Type Description Boolean | Improve this Doc View Source ExceptionFunc Callback for error events in this proxy instance. Declaration public ExceptionHandler ExceptionFunc { get; set; } Property Value Type Description ExceptionHandler | Improve this Doc View Source ForwardToUpstreamGateway Gets or sets a value indicating whether requests will be chained to upstream gateway. Defaults to false. Declaration public bool ForwardToUpstreamGateway { get; set; } Property Value Type Description Boolean | Improve this Doc View Source GetCustomUpStreamProxyFunc A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP(S) requests. User should return the ExternalProxy object with valid credentials. Declaration public Func<SessionEventArgsBase, Task<ExternalProxy>> GetCustomUpStreamProxyFunc { get; set; } Property Value Type Description Func < SessionEventArgsBase , Task < ExternalProxy >> | Improve this Doc View Source MaxCachedConnections Maximum number of concurrent connections per remote host in cache. Only valid when connection pooling is enabled. Default value is 2. Declaration public int MaxCachedConnections { get; set; } Property Value Type Description Int32 | Improve this Doc View Source NoDelay Gets or sets a Boolean value that specifies whether server and client stream Sockets are using the Nagle algorithm. Defaults to true, no nagle algorithm is used. Declaration public bool NoDelay { get; set; } Property Value Type Description Boolean | Improve this Doc View Source ProxyAuthenticationRealm Realm used during Proxy Basic Authentication. Declaration public string ProxyAuthenticationRealm { get; set; } Property Value Type Description String | Improve this Doc View Source ProxyAuthenticationSchemes A collection of scheme types, e.g. basic, NTLM, Kerberos, Negotiate, to return if scheme authentication is required. Works in relation with ProxySchemeAuthenticateFunc. Declaration public IEnumerable<string> ProxyAuthenticationSchemes { get; set; } Property Value Type Description IEnumerable < String > | Improve this Doc View Source ProxyBasicAuthenticateFunc A callback to authenticate proxy clients via basic authentication. Parameters are username and password as provided by client. Should return true for successful authentication. Declaration public Func<SessionEventArgsBase, string, string, Task<bool>> ProxyBasicAuthenticateFunc { get; set; } Property Value Type Description Func < SessionEventArgsBase , String , String , Task < Boolean >> | Improve this Doc View Source ProxyEndPoints A list of IpAddress and port this proxy is listening to. Declaration public List<ProxyEndPoint> ProxyEndPoints { get; set; } Property Value Type Description List < ProxyEndPoint > | Improve this Doc View Source ProxyRunning Is the proxy currently running? Declaration public bool ProxyRunning { get; } Property Value Type Description Boolean | Improve this Doc View Source ProxySchemeAuthenticateFunc A pluggable callback to authenticate clients by scheme instead of requiring basic authentication through ProxyBasicAuthenticateFunc. Parameters are current working session, schemeType, and token as provided by a calling client. Should return success for successful authentication, continuation if the package requests, or failure. Declaration public Func<SessionEventArgsBase, string, string, Task<ProxyAuthenticationContext>> ProxySchemeAuthenticateFunc { get; set; } Property Value Type Description Func < SessionEventArgsBase , String , String , Task < ProxyAuthenticationContext >> | Improve this Doc View Source ReuseSocket Should we reuse client/server tcp sockets. Default is true (disabled for linux/macOS due to bug in .Net core). Declaration public bool ReuseSocket { get; set; } Property Value Type Description Boolean | Improve this Doc View Source ServerConnectionCount Total number of active server connections. Declaration public int ServerConnectionCount { get; } Property Value Type Description Int32 | Improve this Doc View Source SupportedSslProtocols List of supported Ssl versions. Declaration public SslProtocols SupportedSslProtocols { get; set; } Property Value Type Description SslProtocols | Improve this Doc View Source TcpTimeWaitSeconds Number of seconds to linger when Tcp connection is in TIME_WAIT state. Default value is 30. Declaration public int TcpTimeWaitSeconds { get; set; } Property Value Type Description Int32 | Improve this Doc View Source ThreadPoolWorkerThread Customize the minimum ThreadPool size (increase it on a server) Declaration public int ThreadPoolWorkerThread { get; set; } Property Value Type Description Int32 | Improve this Doc View Source UpStreamEndPoint Local adapter/NIC endpoint where proxy makes request via. Defaults via any IP addresses of this machine. Declaration public IPEndPoint UpStreamEndPoint { get; set; } Property Value Type Description IPEndPoint | Improve this Doc View Source UpStreamHttpProxy External proxy used for Http requests. Declaration public ExternalProxy UpStreamHttpProxy { get; set; } Property Value Type Description ExternalProxy | Improve this Doc View Source UpStreamHttpsProxy External proxy used for Https requests. Declaration public ExternalProxy UpStreamHttpsProxy { get; set; } Property Value Type Description ExternalProxy Methods | Improve this Doc View Source AddEndPoint(ProxyEndPoint) Add a proxy end point. Declaration public void AddEndPoint(ProxyEndPoint endPoint) Parameters Type Name Description ProxyEndPoint endPoint The proxy endpoint. | Improve this Doc View Source DisableAllSystemProxies() Clear all proxy settings for current machine. Declaration public void DisableAllSystemProxies() | Improve this Doc View Source DisableSystemHttpProxy() Clear HTTP proxy settings of current machine. Declaration public void DisableSystemHttpProxy() | Improve this Doc View Source DisableSystemHttpsProxy() Clear HTTPS proxy settings of current machine. Declaration public void DisableSystemHttpsProxy() | Improve this Doc View Source DisableSystemProxy(ProxyProtocolType) Clear the specified proxy setting for current machine. Declaration public void DisableSystemProxy(ProxyProtocolType protocolType) Parameters Type Name Description ProxyProtocolType protocolType | Improve this Doc View Source Dispose() Dispose the Proxy instance. Declaration public void Dispose() | Improve this Doc View Source RemoveEndPoint(ProxyEndPoint) Remove a proxy end point. Will throw error if the end point doesn't exist. Declaration public void RemoveEndPoint(ProxyEndPoint endPoint) Parameters Type Name Description ProxyEndPoint endPoint The existing endpoint to remove. | Improve this Doc View Source RestoreOriginalProxySettings() Restores the original proxy settings. Declaration public void RestoreOriginalProxySettings() | Improve this Doc View Source SetAsSystemHttpProxy(ExplicitProxyEndPoint) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemHttpProxy(ExplicitProxyEndPoint endPoint) Parameters Type Name Description ExplicitProxyEndPoint endPoint The explicit endpoint. | Improve this Doc View Source SetAsSystemHttpsProxy(ExplicitProxyEndPoint) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint) Parameters Type Name Description ExplicitProxyEndPoint endPoint The explicit endpoint. | Improve this Doc View Source SetAsSystemProxy(ExplicitProxyEndPoint, ProxyProtocolType) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType) Parameters Type Name Description ExplicitProxyEndPoint endPoint The explicit endpoint. ProxyProtocolType protocolType The proxy protocol type. | Improve this Doc View Source Start() Start this proxy server instance. Declaration public void Start() | Improve this Doc View Source Stop() Stop this proxy server instance. Declaration public void Stop() Events | Improve this Doc View Source AfterResponse Intercept after response event from server. Declaration public event AsyncEventHandler<SessionEventArgs> AfterResponse Event Type Type Description AsyncEventHandler < SessionEventArgs > | Improve this Doc View Source BeforeRequest Intercept request event to server. Declaration public event AsyncEventHandler<SessionEventArgs> BeforeRequest Event Type Type Description AsyncEventHandler < SessionEventArgs > | Improve this Doc View Source BeforeResponse Intercept response event from server. Declaration public event AsyncEventHandler<SessionEventArgs> BeforeResponse Event Type Type Description AsyncEventHandler < SessionEventArgs > | Improve this Doc View Source ClientCertificateSelectionCallback Event to override client certificate selection during mutual SSL authentication. Declaration public event AsyncEventHandler<CertificateSelectionEventArgs> ClientCertificateSelectionCallback Event Type Type Description AsyncEventHandler < CertificateSelectionEventArgs > | Improve this Doc View Source ClientConnectionCountChanged Event occurs when client connection count changed. Declaration public event EventHandler ClientConnectionCountChanged Event Type Type Description EventHandler | Improve this Doc View Source OnClientConnectionCreate Customize TcpClient used for client connection upon create. Declaration public event AsyncEventHandler<TcpClient> OnClientConnectionCreate Event Type Type Description AsyncEventHandler < TcpClient > | Improve this Doc View Source OnServerConnectionCreate Customize TcpClient used for server connection upon create. Declaration public event AsyncEventHandler<TcpClient> OnServerConnectionCreate Event Type Type Description AsyncEventHandler < TcpClient > | Improve this Doc View Source ServerCertificateValidationCallback Event to override the default verification logic of remote SSL certificate received during authentication. Declaration public event AsyncEventHandler<CertificateValidationEventArgs> ServerCertificateValidationCallback Event Type Type Description AsyncEventHandler < CertificateValidationEventArgs > | Improve this Doc View Source ServerConnectionCountChanged Event occurs when server connection count changed. Declaration public event EventHandler ServerConnectionCountChanged Event Type Type Description EventHandler Implements System.IDisposable" "keywords": "Class ProxyServer This class is the backbone of proxy. One can create as many instances as needed. However care should be taken to avoid using the same listening ports across multiple instances. Inheritance Object ProxyServer Implements IDisposable Inherited Members Object.Equals(Object) Object.Equals(Object, Object) Object.GetHashCode() Object.GetType() Object.MemberwiseClone() Object.ReferenceEquals(Object, Object) Object.ToString() Namespace : Titanium.Web.Proxy Assembly : Titanium.Web.Proxy.dll Syntax public class ProxyServer : IDisposable Constructors | Improve this Doc View Source ProxyServer(Boolean, Boolean, Boolean) Initializes a new instance of ProxyServer class with provided parameters. Declaration public ProxyServer(bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) Parameters Type Name Description Boolean userTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's user certificate store? Boolean machineTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's certificate store? Boolean trustRootCertificateAsAdmin Should we attempt to trust certificates with elevated permissions by prompting for UAC if required? | Improve this Doc View Source ProxyServer(String, String, Boolean, Boolean, Boolean) Initializes a new instance of ProxyServer class with provided parameters. Declaration public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) Parameters Type Name Description String rootCertificateName Name of the root certificate. String rootCertificateIssuerName Name of the root certificate issuer. Boolean userTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's user certificate store? Boolean machineTrustRootCertificate Should fake HTTPS certificate be trusted by this machine's certificate store? Boolean trustRootCertificateAsAdmin Should we attempt to trust certificates with elevated permissions by prompting for UAC if required? Properties | Improve this Doc View Source BufferPool The buffer pool used throughout this proxy instance. Set custom implementations by implementing this interface. By default this uses DefaultBufferPool implementation available in StreamExtended library package. Declaration public IBufferPool BufferPool { get; set; } Property Value Type Description IBufferPool | Improve this Doc View Source CertificateManager Manages certificates used by this proxy. Declaration public CertificateManager CertificateManager { get; } Property Value Type Description CertificateManager | Improve this Doc View Source CheckCertificateRevocation Should we check for certificate revocation during SSL authentication to servers Note: If enabled can reduce performance. Defaults to false. Declaration public X509RevocationMode CheckCertificateRevocation { get; set; } Property Value Type Description X509RevocationMode | Improve this Doc View Source ClientConnectionCount Total number of active client connections. Declaration public int ClientConnectionCount { get; } Property Value Type Description Int32 | Improve this Doc View Source ConnectionTimeOutSeconds Seconds client/server connection are to be kept alive when waiting for read/write to complete. This will also determine the pool eviction time when connection pool is enabled. Default value is 60 seconds. Declaration public int ConnectionTimeOutSeconds { get; set; } Property Value Type Description Int32 | Improve this Doc View Source Enable100ContinueBehaviour Does this proxy uses the HTTP protocol 100 continue behaviour strictly? Broken 100 continue implementations on server/client may cause problems if enabled. Defaults to false. Declaration public bool Enable100ContinueBehaviour { get; set; } Property Value Type Description Boolean | Improve this Doc View Source EnableConnectionPool Should we enable experimental server connection pool? Defaults to true. Declaration public bool EnableConnectionPool { get; set; } Property Value Type Description Boolean | Improve this Doc View Source EnableHttp2 Enable disable HTTP/2 support. Warning: HTTP/2 support is very limited only enabled when both client and server supports it (no protocol changing in proxy) cannot modify the request/response (e.g header modifications in BeforeRequest/Response events are ignored) Declaration public bool EnableHttp2 { get; set; } Property Value Type Description Boolean | Improve this Doc View Source EnableTcpServerConnectionPrefetch Should we enable tcp server connection prefetching? When enabled, as soon as we receive a client connection we concurrently initiate corresponding server connection process using CONNECT hostname or SNI hostname on a separate task so that after parsing client request we will have the server connection immediately ready or in the process of getting ready. If a server connection is available in cache then this prefetch task will immediately return with the available connection from cache. Defaults to true. Declaration public bool EnableTcpServerConnectionPrefetch { get; set; } Property Value Type Description Boolean | Improve this Doc View Source EnableWinAuth Enable disable Windows Authentication (NTLM/Kerberos). Note: NTLM/Kerberos will always send local credentials of current user running the proxy process. This is because a man in middle attack with Windows domain authentication is not currently supported. Defaults to false. Declaration public bool EnableWinAuth { get; set; } Property Value Type Description Boolean | Improve this Doc View Source ExceptionFunc Callback for error events in this proxy instance. Declaration public ExceptionHandler ExceptionFunc { get; set; } Property Value Type Description ExceptionHandler | Improve this Doc View Source ForwardToUpstreamGateway Gets or sets a value indicating whether requests will be chained to upstream gateway. Defaults to false. Declaration public bool ForwardToUpstreamGateway { get; set; } Property Value Type Description Boolean | Improve this Doc View Source GetCustomUpStreamProxyFunc A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP(S) requests. User should return the ExternalProxy object with valid credentials. Declaration public Func<SessionEventArgsBase, Task<ExternalProxy>> GetCustomUpStreamProxyFunc { get; set; } Property Value Type Description Func < SessionEventArgsBase , Task < ExternalProxy >> | Improve this Doc View Source MaxCachedConnections Maximum number of concurrent connections per remote host in cache. Only valid when connection pooling is enabled. Default value is 2. Declaration public int MaxCachedConnections { get; set; } Property Value Type Description Int32 | Improve this Doc View Source NoDelay Gets or sets a Boolean value that specifies whether server and client stream Sockets are using the Nagle algorithm. Defaults to true, no nagle algorithm is used. Declaration public bool NoDelay { get; set; } Property Value Type Description Boolean | Improve this Doc View Source ProxyAuthenticationRealm Realm used during Proxy Basic Authentication. Declaration public string ProxyAuthenticationRealm { get; set; } Property Value Type Description String | Improve this Doc View Source ProxyAuthenticationSchemes A collection of scheme types, e.g. basic, NTLM, Kerberos, Negotiate, to return if scheme authentication is required. Works in relation with ProxySchemeAuthenticateFunc. Declaration public IEnumerable<string> ProxyAuthenticationSchemes { get; set; } Property Value Type Description IEnumerable < String > | Improve this Doc View Source ProxyBasicAuthenticateFunc A callback to authenticate proxy clients via basic authentication. Parameters are username and password as provided by client. Should return true for successful authentication. Declaration public Func<SessionEventArgsBase, string, string, Task<bool>> ProxyBasicAuthenticateFunc { get; set; } Property Value Type Description Func < SessionEventArgsBase , String , String , Task < Boolean >> | Improve this Doc View Source ProxyEndPoints A list of IpAddress and port this proxy is listening to. Declaration public List<ProxyEndPoint> ProxyEndPoints { get; set; } Property Value Type Description List < ProxyEndPoint > | Improve this Doc View Source ProxyRunning Is the proxy currently running? Declaration public bool ProxyRunning { get; } Property Value Type Description Boolean | Improve this Doc View Source ProxySchemeAuthenticateFunc A pluggable callback to authenticate clients by scheme instead of requiring basic authentication through ProxyBasicAuthenticateFunc. Parameters are current working session, schemeType, and token as provided by a calling client. Should return success for successful authentication, continuation if the package requests, or failure. Declaration public Func<SessionEventArgsBase, string, string, Task<ProxyAuthenticationContext>> ProxySchemeAuthenticateFunc { get; set; } Property Value Type Description Func < SessionEventArgsBase , String , String , Task < ProxyAuthenticationContext >> | Improve this Doc View Source ReuseSocket Should we reuse client/server tcp sockets. Default is true (disabled for linux/macOS due to bug in .Net core). Declaration public bool ReuseSocket { get; set; } Property Value Type Description Boolean | Improve this Doc View Source ServerConnectionCount Total number of active server connections. Declaration public int ServerConnectionCount { get; } Property Value Type Description Int32 | Improve this Doc View Source SupportedSslProtocols List of supported Ssl versions. Declaration public SslProtocols SupportedSslProtocols { get; set; } Property Value Type Description SslProtocols | Improve this Doc View Source TcpTimeWaitSeconds Number of seconds to linger when Tcp connection is in TIME_WAIT state. Default value is 30. Declaration public int TcpTimeWaitSeconds { get; set; } Property Value Type Description Int32 | Improve this Doc View Source ThreadPoolWorkerThread Customize the minimum ThreadPool size (increase it on a server) Declaration public int ThreadPoolWorkerThread { get; set; } Property Value Type Description Int32 | Improve this Doc View Source UpStreamEndPoint Local adapter/NIC endpoint where proxy makes request via. Defaults via any IP addresses of this machine. Declaration public IPEndPoint UpStreamEndPoint { get; set; } Property Value Type Description IPEndPoint | Improve this Doc View Source UpStreamHttpProxy External proxy used for Http requests. Declaration public ExternalProxy UpStreamHttpProxy { get; set; } Property Value Type Description ExternalProxy | Improve this Doc View Source UpStreamHttpsProxy External proxy used for Https requests. Declaration public ExternalProxy UpStreamHttpsProxy { get; set; } Property Value Type Description ExternalProxy Methods | Improve this Doc View Source AddEndPoint(ProxyEndPoint) Add a proxy end point. Declaration public void AddEndPoint(ProxyEndPoint endPoint) Parameters Type Name Description ProxyEndPoint endPoint The proxy endpoint. | Improve this Doc View Source DisableAllSystemProxies() Clear all proxy settings for current machine. Declaration public void DisableAllSystemProxies() | Improve this Doc View Source DisableSystemHttpProxy() Clear HTTP proxy settings of current machine. Declaration public void DisableSystemHttpProxy() | Improve this Doc View Source DisableSystemHttpsProxy() Clear HTTPS proxy settings of current machine. Declaration public void DisableSystemHttpsProxy() | Improve this Doc View Source DisableSystemProxy(ProxyProtocolType) Clear the specified proxy setting for current machine. Declaration public void DisableSystemProxy(ProxyProtocolType protocolType) Parameters Type Name Description ProxyProtocolType protocolType | Improve this Doc View Source Dispose() Dispose the Proxy instance. Declaration public void Dispose() | Improve this Doc View Source RemoveEndPoint(ProxyEndPoint) Remove a proxy end point. Will throw error if the end point doesn't exist. Declaration public void RemoveEndPoint(ProxyEndPoint endPoint) Parameters Type Name Description ProxyEndPoint endPoint The existing endpoint to remove. | Improve this Doc View Source RestoreOriginalProxySettings() Restores the original proxy settings. Declaration public void RestoreOriginalProxySettings() | Improve this Doc View Source SetAsSystemHttpProxy(ExplicitProxyEndPoint) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemHttpProxy(ExplicitProxyEndPoint endPoint) Parameters Type Name Description ExplicitProxyEndPoint endPoint The explicit endpoint. | Improve this Doc View Source SetAsSystemHttpsProxy(ExplicitProxyEndPoint) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint) Parameters Type Name Description ExplicitProxyEndPoint endPoint The explicit endpoint. | Improve this Doc View Source SetAsSystemProxy(ExplicitProxyEndPoint, ProxyProtocolType) Set the given explicit end point as the default proxy server for current machine. Declaration public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType) Parameters Type Name Description ExplicitProxyEndPoint endPoint The explicit endpoint. ProxyProtocolType protocolType The proxy protocol type. | Improve this Doc View Source Start() Start this proxy server instance. Declaration public void Start() | Improve this Doc View Source Stop() Stop this proxy server instance. Declaration public void Stop() Events | Improve this Doc View Source AfterResponse Intercept after response event from server. Declaration public event AsyncEventHandler<SessionEventArgs> AfterResponse Event Type Type Description AsyncEventHandler < SessionEventArgs > | Improve this Doc View Source BeforeRequest Intercept request event to server. Declaration public event AsyncEventHandler<SessionEventArgs> BeforeRequest Event Type Type Description AsyncEventHandler < SessionEventArgs > | Improve this Doc View Source BeforeResponse Intercept response event from server. Declaration public event AsyncEventHandler<SessionEventArgs> BeforeResponse Event Type Type Description AsyncEventHandler < SessionEventArgs > | Improve this Doc View Source ClientCertificateSelectionCallback Event to override client certificate selection during mutual SSL authentication. Declaration public event AsyncEventHandler<CertificateSelectionEventArgs> ClientCertificateSelectionCallback Event Type Type Description AsyncEventHandler < CertificateSelectionEventArgs > | Improve this Doc View Source ClientConnectionCountChanged Event occurs when client connection count changed. Declaration public event EventHandler ClientConnectionCountChanged Event Type Type Description EventHandler | Improve this Doc View Source OnClientConnectionCreate Customize TcpClient used for client connection upon create. Declaration public event AsyncEventHandler<TcpClient> OnClientConnectionCreate Event Type Type Description AsyncEventHandler < TcpClient > | Improve this Doc View Source OnServerConnectionCreate Customize TcpClient used for server connection upon create. Declaration public event AsyncEventHandler<TcpClient> OnServerConnectionCreate Event Type Type Description AsyncEventHandler < TcpClient > | Improve this Doc View Source ServerCertificateValidationCallback Event to override the default verification logic of remote SSL certificate received during authentication. Declaration public event AsyncEventHandler<CertificateValidationEventArgs> ServerCertificateValidationCallback Event Type Type Description AsyncEventHandler < CertificateValidationEventArgs > | Improve this Doc View Source ServerConnectionCountChanged Event occurs when server connection count changed. Declaration public event EventHandler ServerConnectionCountChanged Event Type Type Description EventHandler Implements System.IDisposable"
} }
} }
...@@ -529,12 +529,6 @@ references: ...@@ -529,12 +529,6 @@ references:
commentId: F:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool commentId: F:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool
nameWithType: SessionEventArgsBase.BufferPool nameWithType: SessionEventArgsBase.BufferPool
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferSize
name: BufferSize
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize
commentId: F:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferSize
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferSize
nameWithType: SessionEventArgsBase.BufferSize
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint - uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint
name: ClientEndPoint name: ClientEndPoint
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint
...@@ -715,6 +709,18 @@ references: ...@@ -715,6 +709,18 @@ references:
commentId: T:Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs commentId: T:Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs
fullName: Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs fullName: Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs
nameWithType: TunnelConnectSessionEventArgs nameWithType: TunnelConnectSessionEventArgs
- uid: Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptedDataReceived
name: DecryptedDataReceived
href: api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html#Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptedDataReceived
commentId: E:Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptedDataReceived
fullName: Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptedDataReceived
nameWithType: TunnelConnectSessionEventArgs.DecryptedDataReceived
- uid: Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptedDataSent
name: DecryptedDataSent
href: api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html#Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptedDataSent
commentId: E:Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptedDataSent
fullName: Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptedDataSent
nameWithType: TunnelConnectSessionEventArgs.DecryptedDataSent
- uid: Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptSsl - uid: Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.DecryptSsl
name: DecryptSsl name: DecryptSsl
href: api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html#Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptSsl href: api/Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html#Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptSsl
...@@ -2865,19 +2871,6 @@ references: ...@@ -2865,19 +2871,6 @@ references:
isSpec: "True" isSpec: "True"
fullName: Titanium.Web.Proxy.Models.ProxyEndPoint.IpAddress fullName: Titanium.Web.Proxy.Models.ProxyEndPoint.IpAddress
nameWithType: ProxyEndPoint.IpAddress nameWithType: ProxyEndPoint.IpAddress
- uid: Titanium.Web.Proxy.Models.ProxyEndPoint.IpV6Enabled
name: IpV6Enabled
href: api/Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_IpV6Enabled
commentId: P:Titanium.Web.Proxy.Models.ProxyEndPoint.IpV6Enabled
fullName: Titanium.Web.Proxy.Models.ProxyEndPoint.IpV6Enabled
nameWithType: ProxyEndPoint.IpV6Enabled
- uid: Titanium.Web.Proxy.Models.ProxyEndPoint.IpV6Enabled*
name: IpV6Enabled
href: api/Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_IpV6Enabled_
commentId: Overload:Titanium.Web.Proxy.Models.ProxyEndPoint.IpV6Enabled
isSpec: "True"
fullName: Titanium.Web.Proxy.Models.ProxyEndPoint.IpV6Enabled
nameWithType: ProxyEndPoint.IpV6Enabled
- uid: Titanium.Web.Proxy.Models.ProxyEndPoint.Port - uid: Titanium.Web.Proxy.Models.ProxyEndPoint.Port
name: Port name: Port
href: api/Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_Port href: api/Titanium.Web.Proxy.Models.ProxyEndPoint.html#Titanium_Web_Proxy_Models_ProxyEndPoint_Port
...@@ -3369,19 +3362,6 @@ references: ...@@ -3369,19 +3362,6 @@ references:
isSpec: "True" isSpec: "True"
fullName: Titanium.Web.Proxy.ProxyServer.BufferPool fullName: Titanium.Web.Proxy.ProxyServer.BufferPool
nameWithType: ProxyServer.BufferPool nameWithType: ProxyServer.BufferPool
- uid: Titanium.Web.Proxy.ProxyServer.BufferSize
name: BufferSize
href: api/Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_BufferSize
commentId: P:Titanium.Web.Proxy.ProxyServer.BufferSize
fullName: Titanium.Web.Proxy.ProxyServer.BufferSize
nameWithType: ProxyServer.BufferSize
- uid: Titanium.Web.Proxy.ProxyServer.BufferSize*
name: BufferSize
href: api/Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_BufferSize_
commentId: Overload:Titanium.Web.Proxy.ProxyServer.BufferSize
isSpec: "True"
fullName: Titanium.Web.Proxy.ProxyServer.BufferSize
nameWithType: ProxyServer.BufferSize
- uid: Titanium.Web.Proxy.ProxyServer.CertificateManager - uid: Titanium.Web.Proxy.ProxyServer.CertificateManager
name: CertificateManager name: CertificateManager
href: api/Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_CertificateManager href: api/Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_CertificateManager
......
...@@ -278,7 +278,6 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -278,7 +278,6 @@ namespace Titanium.Web.Proxy.Examples.Basic
} }
@lock.Release(); @lock.Release();
} }
///// <summary> ///// <summary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFrameworks>net461;netcoreapp2.1</TargetFrameworks> <TargetFrameworks>net461;netcoreapp3.0</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<LangVersion>7.1</LangVersion> <LangVersion>7.1</LangVersion>
</PropertyGroup> </PropertyGroup>
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
<GridViewColumn Header="Process" DisplayMemberBinding="{Binding Process}" /> <GridViewColumn Header="Process" DisplayMemberBinding="{Binding Process}" />
<GridViewColumn Header="SentBytes" DisplayMemberBinding="{Binding SentDataCount}" /> <GridViewColumn Header="SentBytes" DisplayMemberBinding="{Binding SentDataCount}" />
<GridViewColumn Header="ReceivedBytes" DisplayMemberBinding="{Binding ReceivedDataCount}" /> <GridViewColumn Header="ReceivedBytes" DisplayMemberBinding="{Binding ReceivedDataCount}" />
<GridViewColumn Header="ClientEndPoint" DisplayMemberBinding="{Binding ClientEndPoint}" />
</GridView> </GridView>
</ListView.View> </ListView.View>
</ListView> </ListView>
......
...@@ -226,39 +226,60 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -226,39 +226,60 @@ namespace Titanium.Web.Proxy.Examples.Wpf
{ {
Number = lastSessionNumber, Number = lastSessionNumber,
HttpClient = e.HttpClient, HttpClient = e.HttpClient,
ClientEndPoint = e.ClientEndPoint,
IsTunnelConnect = isTunnelConnect IsTunnelConnect = isTunnelConnect
}; };
if (isTunnelConnect || e.HttpClient.Request.UpgradeToWebSocket) //if (isTunnelConnect || e.HttpClient.Request.UpgradeToWebSocket)
e.DataReceived += (sender, args) =>
{ {
e.DataReceived += (sender, args) => var session = (SessionEventArgsBase)sender;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{ {
var session = (SessionEventArgsBase)sender; var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li)) if (tunnelType != TunnelType.Unknown)
{ {
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown; li.Protocol = TunnelTypeToString(tunnelType);
if (tunnelType != TunnelType.Unknown) }
{
li.Protocol = TunnelTypeToString(tunnelType); li.ReceivedDataCount += args.Count;
}
AppendTransferLog(session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_received",
args.Buffer, args.Offset, args.Count);
}
};
li.ReceivedDataCount += args.Count; e.DataSent += (sender, args) =>
{
var session = (SessionEventArgsBase)sender;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
if (tunnelType != TunnelType.Unknown)
{
li.Protocol = TunnelTypeToString(tunnelType);
} }
};
e.DataSent += (sender, args) => li.SentDataCount += args.Count;
AppendTransferLog(session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_sent",
args.Buffer, args.Offset, args.Count);
}
};
if (e is TunnelConnectSessionEventArgs te)
{
te.DecryptedDataReceived += (sender, args) =>
{ {
var session = (SessionEventArgsBase)sender; var session = (SessionEventArgsBase)sender;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li)) AppendTransferLog(session.GetHashCode() + "_decrypted_received", args.Buffer, args.Offset,
{ args.Count);
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown; };
if (tunnelType != TunnelType.Unknown)
{
li.Protocol = TunnelTypeToString(tunnelType);
}
li.SentDataCount += args.Count; te.DecryptedDataSent += (sender, args) =>
} {
var session = (SessionEventArgsBase)sender;
AppendTransferLog(session.GetHashCode() + "_decrypted_sent", args.Buffer, args.Offset, args.Count);
}; };
} }
...@@ -266,6 +287,15 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -266,6 +287,15 @@ namespace Titanium.Web.Proxy.Examples.Wpf
return item; return item;
} }
private void AppendTransferLog(string fileName, byte[] buffer, int offset, int count)
{
//string basePath = @"c:\!titanium\";
//using (var fs = new FileStream(basePath + fileName, FileMode.Append, FileAccess.Write, FileShare.Read))
//{
// fs.Write(buffer, offset, count);
//}
}
private string TunnelTypeToString(TunnelType tunnelType) private string TunnelTypeToString(TunnelType tunnelType)
{ {
switch (tunnelType) switch (tunnelType)
......
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Net;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using Titanium.Web.Proxy.Examples.Wpf.Annotations; using Titanium.Web.Proxy.Examples.Wpf.Annotations;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
...@@ -22,6 +23,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -22,6 +23,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf
public HttpWebClient HttpClient { get; set; } public HttpWebClient HttpClient { get; set; }
public IPEndPoint ClientEndPoint { get; set; }
public bool IsTunnelConnect { get; set; } public bool IsTunnelConnect { get; set; }
public string StatusCode public string StatusCode
......
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
<UseWPF>true</UseWPF> <UseWPF>true</UseWPF>
</PropertyGroup> </PropertyGroup>
<!--<ItemGroup> <ItemGroup Condition="'$(TargetFramework)' == 'net461'">
<Reference Include="PresentationCore" /> <Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" /> <Reference Include="PresentationFramework" />
<Reference Include="WindowsBase" /> <Reference Include="WindowsBase" />
</ItemGroup>--> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="Properties\AssemblyInfo.cs" /> <Compile Remove="Properties\AssemblyInfo.cs" />
...@@ -20,23 +20,6 @@ ...@@ -20,23 +20,6 @@
<ProjectReference Include="..\..\src\Titanium.Web.Proxy\Titanium.Web.Proxy.csproj" /> <ProjectReference Include="..\..\src\Titanium.Web.Proxy\Titanium.Web.Proxy.csproj" />
</ItemGroup> </ItemGroup>
<!--<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Update="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Update="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Update="Properties\Resources.Designer.cs"> <Compile Update="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
...@@ -52,16 +35,6 @@ ...@@ -52,16 +35,6 @@
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<None Update="App.xaml"> </ItemGroup>
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
</None>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>-->
</Project> </Project>
\ No newline at end of file
...@@ -68,6 +68,7 @@ Global ...@@ -68,6 +68,7 @@ Global
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Debug|x64.ActiveCfg = Debug|Any CPU {4406CE17-9A39-4F28-8363-6169A4F799C1}.Debug|x64.ActiveCfg = Debug|Any CPU
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Debug|x64.Build.0 = Debug|Any CPU {4406CE17-9A39-4F28-8363-6169A4F799C1}.Debug|x64.Build.0 = Debug|Any CPU
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|Any CPU.ActiveCfg = Release|Any CPU {4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|Any CPU.Build.0 = Release|Any CPU
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|x64.ActiveCfg = Release|Any CPU {4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|x64.ActiveCfg = Release|Any CPU
{4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|x64.Build.0 = Release|Any CPU {4406CE17-9A39-4F28-8363-6169A4F799C1}.Release|x64.Build.0 = Release|Any CPU
{1D053D72-DCB4-4517-ACDD-D35ADC186950}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1D053D72-DCB4-4517-ACDD-D35ADC186950}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
...@@ -89,7 +90,7 @@ Global ...@@ -89,7 +90,7 @@ Global
{1D053D72-DCB4-4517-ACDD-D35ADC186950} = {BC1E0789-D348-49CF-8B67-5E99D50EDF64} {1D053D72-DCB4-4517-ACDD-D35ADC186950} = {BC1E0789-D348-49CF-8B67-5E99D50EDF64}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {625C1EB5-44CF-47DE-A85A-B4C8C40ED90A}
EnterpriseLibraryConfigurationToolBinariesPath = .1.505.2\lib\NET35 EnterpriseLibraryConfigurationToolBinariesPath = .1.505.2\lib\NET35
SolutionGuid = {625C1EB5-44CF-47DE-A85A-B4C8C40ED90A}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal
...@@ -22,15 +22,10 @@ namespace Titanium.Web.Proxy ...@@ -22,15 +22,10 @@ namespace Titanium.Web.Proxy
// 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 var args = new CertificateValidationEventArgs(certificate, chain, sslPolicyErrors);
{
Certificate = certificate,
Chain = chain,
SslPolicyErrors = sslPolicyErrors
};
// why is the sender null? // why is the sender null?
ServerCertificateValidationCallback.InvokeAsync(this, args, exceptionFunc).Wait(); ServerCertificateValidationCallback.InvokeAsync(this, args, ExceptionFunc).Wait();
return args.IsValid; return args.IsValid;
} }
...@@ -53,11 +48,11 @@ namespace Titanium.Web.Proxy ...@@ -53,11 +48,11 @@ namespace Titanium.Web.Proxy
/// <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, string targetHost,
X509CertificateCollection localCertificates, X509CertificateCollection localCertificates,
X509Certificate remoteCertificate, string[] acceptableIssuers) X509Certificate remoteCertificate, string[] acceptableIssuers)
{ {
X509Certificate clientCertificate = null; X509Certificate? clientCertificate = null;
if (acceptableIssuers != null && acceptableIssuers.Length > 0 && localCertificates != null && if (acceptableIssuers != null && acceptableIssuers.Length > 0 && localCertificates != null &&
localCertificates.Count > 0) localCertificates.Count > 0)
...@@ -90,7 +85,7 @@ namespace Titanium.Web.Proxy ...@@ -90,7 +85,7 @@ namespace Titanium.Web.Proxy
}; };
// why is the sender null? // why is the sender null?
ClientCertificateSelectionCallback.InvokeAsync(this, args, exceptionFunc).Wait(); ClientCertificateSelectionCallback.InvokeAsync(this, args, ExceptionFunc).Wait();
return args.ClientCertificate; return args.ClientCertificate;
} }
......
using System; using System;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Compression namespace Titanium.Web.Proxy.Compression
...@@ -11,15 +10,15 @@ namespace Titanium.Web.Proxy.Compression ...@@ -11,15 +10,15 @@ namespace Titanium.Web.Proxy.Compression
/// </summary> /// </summary>
internal static class CompressionFactory internal static class CompressionFactory
{ {
internal static Stream Create(string type, Stream stream, bool leaveOpen = true) internal static Stream Create(HttpCompression type, Stream stream, bool leaveOpen = true)
{ {
switch (type) switch (type)
{ {
case KnownHeaders.ContentEncodingGzip: case HttpCompression.Gzip:
return new GZipStream(stream, CompressionMode.Compress, leaveOpen); return new GZipStream(stream, CompressionMode.Compress, leaveOpen);
case KnownHeaders.ContentEncodingDeflate: case HttpCompression.Deflate:
return new DeflateStream(stream, CompressionMode.Compress, leaveOpen); return new DeflateStream(stream, CompressionMode.Compress, leaveOpen);
case KnownHeaders.ContentEncodingBrotli: case HttpCompression.Brotli:
return new BrotliSharpLib.BrotliStream(stream, CompressionMode.Compress, leaveOpen); return new BrotliSharpLib.BrotliStream(stream, CompressionMode.Compress, leaveOpen);
default: default:
throw new Exception($"Unsupported compression mode: {type}"); throw new Exception($"Unsupported compression mode: {type}");
......
using System;
using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Compression
{
internal static class CompressionUtil
{
public static HttpCompression CompressionNameToEnum(string name)
{
if (KnownHeaders.ContentEncodingGzip.Equals(name))
return HttpCompression.Gzip;
if (KnownHeaders.ContentEncodingDeflate.Equals(name))
return HttpCompression.Deflate;
if (KnownHeaders.ContentEncodingBrotli.Equals(name))
return HttpCompression.Brotli;
return HttpCompression.Unsupported;
}
}
}
using System; using System;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Compression namespace Titanium.Web.Proxy.Compression
...@@ -11,15 +10,15 @@ namespace Titanium.Web.Proxy.Compression ...@@ -11,15 +10,15 @@ namespace Titanium.Web.Proxy.Compression
/// </summary> /// </summary>
internal class DecompressionFactory internal class DecompressionFactory
{ {
internal static Stream Create(string type, Stream stream, bool leaveOpen = true) internal static Stream Create(HttpCompression type, Stream stream, bool leaveOpen = true)
{ {
switch (type) switch (type)
{ {
case KnownHeaders.ContentEncodingGzip: case HttpCompression.Gzip:
return new GZipStream(stream, CompressionMode.Decompress, leaveOpen); return new GZipStream(stream, CompressionMode.Decompress, leaveOpen);
case KnownHeaders.ContentEncodingDeflate: case HttpCompression.Deflate:
return new DeflateStream(stream, CompressionMode.Decompress, leaveOpen); return new DeflateStream(stream, CompressionMode.Decompress, leaveOpen);
case KnownHeaders.ContentEncodingBrotli: case HttpCompression.Brotli:
return new BrotliSharpLib.BrotliStream(stream, CompressionMode.Decompress, leaveOpen); return new BrotliSharpLib.BrotliStream(stream, CompressionMode.Decompress, leaveOpen);
default: default:
throw new Exception($"Unsupported decompression mode: {type}"); throw new Exception($"Unsupported decompression mode: {type}");
......
using System.IO.Compression;
namespace Titanium.Web.Proxy.Compression
{
internal enum HttpCompression
{
Unsupported,
Gzip,
Deflate,
Brotli,
}
}
...@@ -10,16 +10,17 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -10,16 +10,17 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
internal readonly CancellationTokenSource TaskCancellationSource; internal readonly CancellationTokenSource TaskCancellationSource;
internal BeforeSslAuthenticateEventArgs(CancellationTokenSource taskCancellationSource) internal BeforeSslAuthenticateEventArgs(CancellationTokenSource taskCancellationSource, string sniHostName)
{ {
TaskCancellationSource = taskCancellationSource; TaskCancellationSource = taskCancellationSource;
SniHostName = sniHostName;
} }
/// <summary> /// <summary>
/// The server name indication hostname if available. Otherwise the generic certificate hostname of /// The server name indication hostname if available. Otherwise the generic certificate hostname of
/// TransparentEndPoint. /// TransparentEndPoint.
/// </summary> /// </summary>
public string SniHostName { get; internal set; } public string SniHostName { get; }
/// <summary> /// <summary>
/// Should we decrypt the SSL request? /// Should we decrypt the SSL request?
......
...@@ -11,31 +11,31 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -11,31 +11,31 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// The proxy server instance. /// The proxy server instance.
/// </summary> /// </summary>
public object Sender { get; internal set; } public object? Sender { get; internal set; }
/// <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; internal set; }
/// <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; internal set; }
/// <summary> /// <summary>
/// Certificate of the remote server. /// Certificate of the remote server.
/// </summary> /// </summary>
public X509Certificate RemoteCertificate { get; internal set; } public X509Certificate? RemoteCertificate { get; internal set; }
/// <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; internal set; }
/// <summary> /// <summary>
/// Client Certificate we selected. Set this value to override. /// Client Certificate we selected. Set this value to override.
/// </summary> /// </summary>
public X509Certificate ClientCertificate { get; set; } public X509Certificate? ClientCertificate { get; set; }
} }
} }
...@@ -10,20 +10,27 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -10,20 +10,27 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public class CertificateValidationEventArgs : EventArgs public class CertificateValidationEventArgs : EventArgs
{ {
public CertificateValidationEventArgs(X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
Certificate = certificate;
Chain = chain;
SslPolicyErrors = sslPolicyErrors;
}
/// <summary> /// <summary>
/// Server certificate. /// Server certificate.
/// </summary> /// </summary>
public X509Certificate Certificate { get; internal set; } public X509Certificate Certificate { get; }
/// <summary> /// <summary>
/// Certificate chain. /// Certificate chain.
/// </summary> /// </summary>
public X509Chain Chain { get; internal set; } public X509Chain Chain { get; }
/// <summary> /// <summary>
/// SSL policy errors. /// SSL policy errors.
/// </summary> /// </summary>
public SslPolicyErrors SslPolicyErrors { get; internal set; } public SslPolicyErrors SslPolicyErrors { get; }
/// <summary> /// <summary>
/// Is the given server certificate valid? /// Is the given server certificate valid?
......
...@@ -11,13 +11,13 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -11,13 +11,13 @@ namespace Titanium.Web.Proxy.EventArguments
internal class LimitedStream : Stream internal class LimitedStream : Stream
{ {
private readonly IBufferPool bufferPool; private readonly IBufferPool bufferPool;
private readonly ICustomStreamReader baseStream; private readonly CustomBufferedStream baseStream;
private readonly bool isChunked; private readonly bool isChunked;
private long bytesRemaining; private long bytesRemaining;
private bool readChunkTrail; private bool readChunkTrail;
internal LimitedStream(ICustomStreamReader baseStream, IBufferPool bufferPool, bool isChunked, internal LimitedStream(CustomBufferedStream baseStream, IBufferPool bufferPool, bool isChunked,
long contentLength) long contentLength)
{ {
this.baseStream = baseStream; this.baseStream = baseStream;
...@@ -49,12 +49,12 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -49,12 +49,12 @@ namespace Titanium.Web.Proxy.EventArguments
if (readChunkTrail) if (readChunkTrail)
{ {
// read the chunk trail of the previous chunk // read the chunk trail of the previous chunk
string s = baseStream.ReadLineAsync().Result; string? s = baseStream.ReadLineAsync().Result;
} }
readChunkTrail = true; readChunkTrail = true;
string chunkHead = baseStream.ReadLineAsync().Result; string? chunkHead = baseStream.ReadLineAsync().Result!;
int idx = chunkHead.IndexOf(";", StringComparison.Ordinal); int idx = chunkHead.IndexOf(";", StringComparison.Ordinal);
if (idx >= 0) if (idx >= 0)
{ {
...@@ -73,7 +73,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -73,7 +73,9 @@ namespace Titanium.Web.Proxy.EventArguments
bytesRemaining = -1; bytesRemaining = -1;
// chunk trail // chunk trail
baseStream.ReadLineAsync().Wait(); var task = baseStream.ReadLineAsync();
if (!task.IsCompleted)
task.AsTask().Wait();
} }
} }
...@@ -132,7 +134,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -132,7 +134,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
if (bytesRemaining != -1) if (bytesRemaining != -1)
{ {
var buffer = bufferPool.GetBuffer(baseStream.BufferSize); var buffer = bufferPool.GetBuffer();
try try
{ {
int res = await ReadAsync(buffer, 0, buffer.Length); int res = await ReadAsync(buffer, 0, buffer.Length);
......
...@@ -9,6 +9,7 @@ using Titanium.Web.Proxy.Helpers; ...@@ -9,6 +9,7 @@ using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http.Responses; using Titanium.Web.Proxy.Http.Responses;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.StreamExtended.Network; using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
...@@ -36,15 +37,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -36,15 +37,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, internal SessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, ProxyClient proxyClient, ConnectRequest? connectRequest, CancellationTokenSource cancellationTokenSource)
CancellationTokenSource cancellationTokenSource) : base(server, endPoint, proxyClient, connectRequest, new Request(), cancellationTokenSource)
: this(server, endPoint, null, cancellationTokenSource)
{
}
protected SessionEventArgs(ProxyServer server, ProxyEndPoint endPoint,
Request request, CancellationTokenSource cancellationTokenSource)
: base(server, endPoint, cancellationTokenSource, request)
{ {
} }
...@@ -70,9 +64,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -70,9 +64,9 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Occurs when multipart request part sent. /// Occurs when multipart request part sent.
/// </summary> /// </summary>
public event EventHandler<MultipartRequestPartSentEventArgs> MultipartRequestPartSent; public event EventHandler<MultipartRequestPartSentEventArgs>? MultipartRequestPartSent;
private ICustomStreamReader getStreamReader(bool isRequest) private CustomBufferedStream getStreamReader(bool isRequest)
{ {
return isRequest ? ProxyClient.ClientStream : HttpClient.Connection.Stream; return isRequest ? ProxyClient.ClientStream : HttpClient.Connection.Stream;
} }
...@@ -105,7 +99,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -105,7 +99,7 @@ namespace Titanium.Web.Proxy.EventArguments
request.ReadHttp2BodyTaskCompletionSource = tcs; request.ReadHttp2BodyTaskCompletionSource = tcs;
// signal to HTTP/2 copy frame method to continue // signal to HTTP/2 copy frame method to continue
request.ReadHttp2BeforeHandlerTaskCompletionSource.SetResult(true); request.ReadHttp2BeforeHandlerTaskCompletionSource!.SetResult(true);
await tcs.Task; await tcs.Task;
...@@ -121,7 +115,6 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -121,7 +115,6 @@ namespace Titanium.Web.Proxy.EventArguments
// Now set the flag to true // Now set the flag to true
// So that next time we can deliver body from cache // So that next time we can deliver body from cache
request.IsBodyRead = true; request.IsBodyRead = true;
OnDataSent(body, 0, body.Length);
} }
} }
} }
...@@ -136,11 +129,11 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -136,11 +129,11 @@ namespace Titanium.Web.Proxy.EventArguments
HttpClient.Response = new Response(); HttpClient.Response = new Response();
} }
internal void OnMultipartRequestPartSent(string boundary, HeaderCollection headers) internal void OnMultipartRequestPartSent(ReadOnlySpan<char> boundary, HeaderCollection headers)
{ {
try try
{ {
MultipartRequestPartSent?.Invoke(this, new MultipartRequestPartSentEventArgs(boundary, headers)); MultipartRequestPartSent?.Invoke(this, new MultipartRequestPartSentEventArgs(boundary.ToString(), headers));
} }
catch (Exception ex) catch (Exception ex)
{ {
...@@ -178,7 +171,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -178,7 +171,7 @@ namespace Titanium.Web.Proxy.EventArguments
response.ReadHttp2BodyTaskCompletionSource = tcs; response.ReadHttp2BodyTaskCompletionSource = tcs;
// signal to HTTP/2 copy frame method to continue // signal to HTTP/2 copy frame method to continue
response.ReadHttp2BeforeHandlerTaskCompletionSource.SetResult(true); response.ReadHttp2BeforeHandlerTaskCompletionSource!.SetResult(true);
await tcs.Task; await tcs.Task;
...@@ -194,7 +187,6 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -194,7 +187,6 @@ namespace Titanium.Web.Proxy.EventArguments
// Now set the flag to true // Now set the flag to true
// So that next time we can deliver body from cache // So that next time we can deliver body from cache
response.IsBodyRead = true; response.IsBodyRead = true;
OnDataReceived(body, 0, body.Length);
} }
} }
} }
...@@ -203,7 +195,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -203,7 +195,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
using (var bodyStream = new MemoryStream()) using (var bodyStream = new MemoryStream())
{ {
var writer = new HttpWriter(bodyStream, BufferPool, BufferSize); var writer = new HttpWriter(bodyStream, BufferPool);
if (isRequest) if (isRequest)
{ {
...@@ -235,7 +227,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -235,7 +227,7 @@ namespace Titanium.Web.Proxy.EventArguments
using (var bodyStream = new MemoryStream()) using (var bodyStream = new MemoryStream())
{ {
var writer = new HttpWriter(bodyStream, BufferPool, BufferSize); var writer = new HttpWriter(bodyStream, BufferPool);
await copyBodyAsync(isRequest, true, writer, TransformationMode.None, null, cancellationToken); await copyBodyAsync(isRequest, true, writer, TransformationMode.None, null, cancellationToken);
} }
} }
...@@ -254,9 +246,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -254,9 +246,9 @@ namespace Titanium.Web.Proxy.EventArguments
if (contentLength > 0 && hasMulipartEventSubscribers && request.IsMultipartFormData) if (contentLength > 0 && hasMulipartEventSubscribers && request.IsMultipartFormData)
{ {
var reader = getStreamReader(true); var reader = getStreamReader(true);
string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType); var boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType);
using (var copyStream = new CopyStream(reader, writer, BufferPool, BufferSize)) using (var copyStream = new CopyStream(reader, writer, BufferPool))
{ {
while (contentLength > copyStream.ReadBytes) while (contentLength > copyStream.ReadBytes)
{ {
...@@ -270,7 +262,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -270,7 +262,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
var headers = new HeaderCollection(); var headers = new HeaderCollection();
await HeaderParser.ReadHeaders(copyStream, headers, cancellationToken); await HeaderParser.ReadHeaders(copyStream, headers, cancellationToken);
OnMultipartRequestPartSent(boundary, headers); OnMultipartRequestPartSent(boundary.Span, headers);
} }
} }
...@@ -288,7 +280,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -288,7 +280,7 @@ namespace Titanium.Web.Proxy.EventArguments
await copyBodyAsync(false, false, writer, transformation, OnDataReceived, cancellationToken); await copyBodyAsync(false, false, writer, transformation, OnDataReceived, cancellationToken);
} }
private async Task copyBodyAsync(bool isRequest, bool useOriginalHeaderValues, HttpWriter writer, TransformationMode transformation, Action<byte[], int, int> onCopy, CancellationToken cancellationToken) private async Task copyBodyAsync(bool isRequest, bool useOriginalHeaderValues, HttpWriter writer, TransformationMode transformation, Action<byte[], int, int>? onCopy, CancellationToken cancellationToken)
{ {
var stream = getStreamReader(isRequest); var stream = getStreamReader(isRequest);
...@@ -304,20 +296,20 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -304,20 +296,20 @@ namespace Titanium.Web.Proxy.EventArguments
} }
LimitedStream limitedStream; LimitedStream limitedStream;
Stream decompressStream = null; Stream? decompressStream = null;
string contentEncoding = useOriginalHeaderValues ? requestResponse.OriginalContentEncoding : requestResponse.ContentEncoding; string? contentEncoding = useOriginalHeaderValues ? requestResponse.OriginalContentEncoding : requestResponse.ContentEncoding;
Stream s = limitedStream = new LimitedStream(stream, BufferPool, isChunked, contentLength); Stream s = limitedStream = new LimitedStream(stream, BufferPool, isChunked, contentLength);
if (transformation == TransformationMode.Uncompress && contentEncoding != null) if (transformation == TransformationMode.Uncompress && contentEncoding != null)
{ {
s = decompressStream = DecompressionFactory.Create(contentEncoding, s); s = decompressStream = DecompressionFactory.Create(CompressionUtil.CompressionNameToEnum(contentEncoding), s);
} }
try try
{ {
using (var bufStream = new CustomBufferedStream(s, BufferPool, BufferSize, true)) using (var bufStream = new CustomBufferedStream(s, BufferPool, true))
{ {
await writer.CopyBodyAsync(bufStream, false, -1, onCopy, cancellationToken); await writer.CopyBodyAsync(bufStream, false, -1, onCopy, cancellationToken);
} }
...@@ -335,11 +327,11 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -335,11 +327,11 @@ namespace Titanium.Web.Proxy.EventArguments
/// Read a line from the byte stream /// Read a line from the byte stream
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
private async Task<long> readUntilBoundaryAsync(ICustomStreamReader reader, long totalBytesToRead, string boundary, CancellationToken cancellationToken) private async Task<long> readUntilBoundaryAsync(ILineStream reader, long totalBytesToRead, ReadOnlyMemory<char> boundary, CancellationToken cancellationToken)
{ {
int bufferDataLength = 0; int bufferDataLength = 0;
var buffer = BufferPool.GetBuffer(BufferSize); var buffer = BufferPool.GetBuffer();
try try
{ {
int boundaryLength = boundary.Length + 4; int boundaryLength = boundary.Length + 4;
...@@ -362,7 +354,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -362,7 +354,7 @@ namespace Titanium.Web.Proxy.EventArguments
bool ok = true; bool ok = true;
for (int i = 0; i < boundary.Length; i++) for (int i = 0; i < boundary.Length; i++)
{ {
if (buffer[startIdx + i] != boundary[i]) if (buffer[startIdx + i] != boundary.Span[i])
{ {
ok = false; ok = false;
break; break;
...@@ -521,7 +513,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -521,7 +513,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="html">HTML content to sent.</param> /// <param name="html">HTML content to sent.</param>
/// <param name="headers">HTTP response headers.</param> /// <param name="headers">HTTP response headers.</param>
/// <param name="closeServerConnection">Close the server connection used by request if any?</param> /// <param name="closeServerConnection">Close the server connection used by request if any?</param>
public void Ok(string html, Dictionary<string, HttpHeader> headers = null, public void Ok(string html, Dictionary<string, HttpHeader>? headers = null,
bool closeServerConnection = false) bool closeServerConnection = false)
{ {
var response = new OkResponse(); var response = new OkResponse();
...@@ -543,7 +535,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -543,7 +535,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="result">The html content bytes.</param> /// <param name="result">The html content bytes.</param>
/// <param name="headers">The HTTP headers.</param> /// <param name="headers">The HTTP headers.</param>
/// <param name="closeServerConnection">Close the server connection used by request if any?</param> /// <param name="closeServerConnection">Close the server connection used by request if any?</param>
public void Ok(byte[] result, Dictionary<string, HttpHeader> headers = null, public void Ok(byte[] result, Dictionary<string, HttpHeader>? headers = null,
bool closeServerConnection = false) bool closeServerConnection = false)
{ {
var response = new OkResponse(); var response = new OkResponse();
...@@ -564,7 +556,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -564,7 +556,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <param name="headers">The HTTP headers.</param> /// <param name="headers">The HTTP headers.</param>
/// <param name="closeServerConnection">Close the server connection used by request if any?</param> /// <param name="closeServerConnection">Close the server connection used by request if any?</param>
public void GenericResponse(string html, HttpStatusCode status, public void GenericResponse(string html, HttpStatusCode status,
Dictionary<string, HttpHeader> headers = null, bool closeServerConnection = false) Dictionary<string, HttpHeader>? headers = null, bool closeServerConnection = false)
{ {
var response = new GenericResponse(status); var response = new GenericResponse(status);
response.HttpVersion = HttpClient.Request.HttpVersion; response.HttpVersion = HttpClient.Request.HttpVersion;
......
...@@ -20,13 +20,17 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -20,13 +20,17 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public abstract class SessionEventArgsBase : EventArgs, IDisposable public abstract class SessionEventArgsBase : EventArgs, IDisposable
{ {
private static bool isWindowsAuthenticationSupported => RunTime.IsWindows;
internal readonly CancellationTokenSource CancellationTokenSource; internal readonly CancellationTokenSource CancellationTokenSource;
internal TcpServerConnection ServerConnection => HttpClient.Connection; internal TcpServerConnection ServerConnection => HttpClient.Connection;
internal TcpClientConnection ClientConnection => ProxyClient.Connection; internal TcpClientConnection ClientConnection => ProxyClient.Connection;
protected readonly int BufferSize;
protected readonly IBufferPool BufferPool; protected readonly IBufferPool BufferPool;
protected readonly ExceptionHandler ExceptionFunc; protected readonly ExceptionHandler ExceptionFunc;
private bool enableWinAuth;
/// <summary> /// <summary>
/// Relative milliseconds for various events. /// Relative milliseconds for various events.
...@@ -36,26 +40,19 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -36,26 +40,19 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class. /// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
/// </summary> /// </summary>
private SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
CancellationTokenSource cancellationTokenSource) ProxyClient proxyClient, ConnectRequest? connectRequest, Request request, CancellationTokenSource cancellationTokenSource)
{ {
BufferSize = server.BufferSize;
BufferPool = server.BufferPool; BufferPool = server.BufferPool;
ExceptionFunc = server.ExceptionFunc; ExceptionFunc = server.ExceptionFunc;
TimeLine["Session Created"] = DateTime.Now; TimeLine["Session Created"] = DateTime.Now;
}
protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
CancellationTokenSource cancellationTokenSource,
Request request) : this(server, endPoint, cancellationTokenSource)
{
CancellationTokenSource = cancellationTokenSource; CancellationTokenSource = cancellationTokenSource;
ProxyClient = new ProxyClient(); ProxyClient = proxyClient;
HttpClient = new HttpWebClient(request); HttpClient = new HttpWebClient(connectRequest, request, new Lazy<int>(() => ProxyClient.Connection.GetProcessId(endPoint)));
LocalEndPoint = endPoint; LocalEndPoint = endPoint;
EnableWinAuth = server.EnableWinAuth && isWindowsAuthenticationSupported;
HttpClient.ProcessId = new Lazy<int>(() => ProxyClient.Connection.GetProcessId(endPoint));
} }
/// <summary> /// <summary>
...@@ -67,12 +64,27 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -67,12 +64,27 @@ namespace Titanium.Web.Proxy.EventArguments
/// Returns a user data for this request/response session which is /// Returns a user data for this request/response session which is
/// same as the user data of HttpClient. /// same as the user data of HttpClient.
/// </summary> /// </summary>
public object UserData public object? UserData
{ {
get => HttpClient.UserData; get => HttpClient.UserData;
set => HttpClient.UserData = value; set => HttpClient.UserData = value;
} }
/// <summary>
/// Enable/disable Windows Authentication (NTLM/Kerberos) for the current session.
/// </summary>
public bool EnableWinAuth
{
get => enableWinAuth;
set
{
if (value && !isWindowsAuthenticationSupported)
throw new Exception("Windows Authentication is not supported");
enableWinAuth = value;
}
}
/// <summary> /// <summary>
/// Does this session uses SSL? /// Does this session uses SSL?
/// </summary> /// </summary>
...@@ -94,7 +106,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -94,7 +106,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Are we using a custom upstream HTTP(S) proxy? /// Are we using a custom upstream HTTP(S) proxy?
/// </summary> /// </summary>
public ExternalProxy CustomUpStreamProxyUsed { get; internal set; } public ExternalProxy? CustomUpStreamProxyUsed { get; internal set; }
/// <summary> /// <summary>
/// Local endpoint via which we make the request. /// Local endpoint via which we make the request.
...@@ -109,7 +121,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -109,7 +121,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// The last exception that happened. /// The last exception that happened.
/// </summary> /// </summary>
public Exception Exception { get; internal set; } public Exception? Exception { get; internal set; }
/// <summary> /// <summary>
/// Implements cleanup here. /// Implements cleanup here.
...@@ -128,12 +140,12 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -128,12 +140,12 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Fired when data is sent within this session to server/client. /// Fired when data is sent within this session to server/client.
/// </summary> /// </summary>
public event EventHandler<DataEventArgs> DataSent; public event EventHandler<DataEventArgs>? DataSent;
/// <summary> /// <summary>
/// Fired when data is received within this session from client/server. /// Fired when data is received within this session from client/server.
/// </summary> /// </summary>
public event EventHandler<DataEventArgs> DataReceived; public event EventHandler<DataEventArgs>? DataReceived;
internal void OnDataSent(byte[] buffer, int offset, int count) internal void OnDataSent(byte[] buffer, int offset, int count)
{ {
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
using System.Threading; using System.Threading;
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.StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
...@@ -13,10 +15,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -13,10 +15,9 @@ 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,
CancellationTokenSource cancellationTokenSource) ProxyClient proxyClient, CancellationTokenSource cancellationTokenSource)
: base(server, endPoint, cancellationTokenSource, connectRequest) : base(server, endPoint, proxyClient, connectRequest, connectRequest, cancellationTokenSource)
{ {
HttpClient.ConnectRequest = connectRequest;
} }
/// <summary> /// <summary>
...@@ -40,5 +41,39 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -40,5 +41,39 @@ namespace Titanium.Web.Proxy.EventArguments
internal set => isHttpsConnect = value; internal set => isHttpsConnect = value;
} }
/// <summary>
/// Fired when decrypted data is sent within this session to server/client.
/// </summary>
public event EventHandler<DataEventArgs>? DecryptedDataSent;
/// <summary>
/// Fired when decrypted data is received within this session from client/server.
/// </summary>
public event EventHandler<DataEventArgs>? DecryptedDataReceived;
internal void OnDecryptedDataSent(byte[] buffer, int offset, int count)
{
try
{
DecryptedDataSent?.Invoke(this, new DataEventArgs(buffer, offset, count));
}
catch (Exception ex)
{
ExceptionFunc(new Exception("Exception thrown in user event", ex));
}
}
internal void OnDecryptedDataReceived(byte[] buffer, int offset, int count)
{
try
{
DecryptedDataReceived?.Invoke(this, new DataEventArgs(buffer, offset, count));
}
catch (Exception ex)
{
ExceptionFunc(new Exception("Exception thrown in user event", ex));
}
}
} }
} }
using System; using System;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
......
...@@ -22,7 +22,7 @@ namespace Titanium.Web.Proxy.Exceptions ...@@ -22,7 +22,7 @@ namespace Titanium.Web.Proxy.Exceptions
/// </summary> /// </summary>
/// <param name="message">Exception message</param> /// <param name="message">Exception message</param>
/// <param name="innerException">Inner exception associated</param> /// <param name="innerException">Inner exception associated</param>
protected ProxyException(string message, Exception innerException) : base(message, innerException) protected ProxyException(string message, Exception? innerException) : base(message, innerException)
{ {
} }
} }
......
...@@ -14,7 +14,7 @@ namespace Titanium.Web.Proxy.Exceptions ...@@ -14,7 +14,7 @@ namespace Titanium.Web.Proxy.Exceptions
/// <param name="message">Message for this exception</param> /// <param name="message">Message for this exception</param>
/// <param name="innerException">Associated inner exception</param> /// <param name="innerException">Associated inner exception</param>
/// <param name="session">Instance of <see cref="EventArguments.SessionEventArgs" /> associated to the exception</param> /// <param name="session">Instance of <see cref="EventArguments.SessionEventArgs" /> associated to the exception</param>
internal ProxyHttpException(string message, Exception innerException, SessionEventArgs session) : base( internal ProxyHttpException(string message, Exception? innerException, SessionEventArgs? session) : base(
message, innerException) message, innerException)
{ {
Session = session; Session = session;
...@@ -26,6 +26,6 @@ namespace Titanium.Web.Proxy.Exceptions ...@@ -26,6 +26,6 @@ namespace Titanium.Web.Proxy.Exceptions
/// <remarks> /// <remarks>
/// This object properties should not be edited. /// This object properties should not be edited.
/// </remarks> /// </remarks>
public SessionEventArgs Session { get; } public SessionEventArgs? Session { get; }
} }
} }
...@@ -14,6 +14,7 @@ using Titanium.Web.Proxy.Helpers; ...@@ -14,6 +14,7 @@ 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 Titanium.Web.Proxy.StreamExtended.Network;
...@@ -35,48 +36,43 @@ namespace Titanium.Web.Proxy ...@@ -35,48 +36,43 @@ namespace Titanium.Web.Proxy
var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferPool, BufferSize); var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferPool);
var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool);
Task<TcpServerConnection> prefetchConnectionTask = null; Task<TcpServerConnection>? prefetchConnectionTask = null;
bool closeServerConnection = false; bool closeServerConnection = false;
bool calledRequestHandler = false; bool calledRequestHandler = false;
SslStream sslStream = null; SslStream? sslStream = null;
try try
{ {
string connectHostname = null; TunnelConnectSessionEventArgs? connectArgs = null;
TunnelConnectSessionEventArgs connectArgs = null;
// Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request) // Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, BufferSize, cancellationToken) == 1) if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, cancellationToken) == 1)
{ {
// read the first line HTTP command // read the first line HTTP command
string httpCmd = await clientStream.ReadLineAsync(cancellationToken); string? httpCmd = await clientStream.ReadLineAsync(cancellationToken);
if (string.IsNullOrEmpty(httpCmd)) if (string.IsNullOrEmpty(httpCmd))
{ {
return; return;
} }
Request.ParseRequestLine(httpCmd, out string _, out string httpUrl, out var version); Request.ParseRequestLine(httpCmd!, out string _, out string httpUrl, out var version);
var httpRemoteUri = new Uri("http://" + httpUrl); var connectRequest = new ConnectRequest(httpUrl)
connectHostname = httpRemoteUri.Host;
var connectRequest = new ConnectRequest
{ {
RequestUri = httpRemoteUri, OriginalUrlData = HttpHeader.Encoding.GetBytes(httpUrl),
OriginalUrl = httpUrl,
HttpVersion = version HttpVersion = version
}; };
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,
cancellationTokenSource); new ProxyClient(clientConnection, clientStream, clientStreamWriter), cancellationTokenSource);
connectArgs.ProxyClient.Connection = clientConnection; clientStream.DataRead += (o, args) => connectArgs.OnDataSent(args.Buffer, args.Offset, args.Count);
connectArgs.ProxyClient.ClientStream = clientStream; clientStream.DataWrite += (o, args) => connectArgs.OnDataReceived(args.Buffer, args.Offset, args.Count);
await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc); await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc);
...@@ -124,18 +120,18 @@ namespace Titanium.Web.Proxy ...@@ -124,18 +120,18 @@ namespace Titanium.Web.Proxy
var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken); var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);
bool isClientHello = clientHelloInfo != null; bool isClientHello = clientHelloInfo != null;
if (isClientHello) if (clientHelloInfo != null)
{ {
connectRequest.IsHttps = true;
connectRequest.TunnelType = TunnelType.Https; connectRequest.TunnelType = TunnelType.Https;
connectRequest.ClientHelloInfo = clientHelloInfo; connectRequest.ClientHelloInfo = clientHelloInfo;
} }
await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc, isClientHello); await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc, isClientHello);
if (decryptSsl && isClientHello) if (decryptSsl && clientHelloInfo != null)
{ {
clientConnection.SslProtocol = clientHelloInfo.SslProtocol; clientConnection.SslProtocol = clientHelloInfo.SslProtocol;
connectRequest.RequestUri = new Uri("https://" + httpUrl);
bool http2Supported = false; bool http2Supported = false;
...@@ -164,7 +160,7 @@ namespace Titanium.Web.Proxy ...@@ -164,7 +160,7 @@ namespace Titanium.Web.Proxy
if (EnableTcpServerConnectionPrefetch) if (EnableTcpServerConnectionPrefetch)
{ {
IPAddress[] ipAddresses = null; IPAddress[]? ipAddresses = null;
try try
{ {
// make sure the host can be resolved before creating the prefetch task // make sure the host can be resolved before creating the prefetch task
...@@ -182,7 +178,14 @@ namespace Titanium.Web.Proxy ...@@ -182,7 +178,14 @@ namespace Titanium.Web.Proxy
} }
} }
X509Certificate2 certificate = null; string connectHostname = httpUrl;
int idx = connectHostname.IndexOf(":");
if (idx >= 0)
{
connectHostname = connectHostname.Substring(0, idx);
}
X509Certificate2? certificate = null;
try try
{ {
sslStream = new SslStream(clientStream, false); sslStream = new SslStream(clientStream, false);
...@@ -208,13 +211,15 @@ namespace Titanium.Web.Proxy ...@@ -208,13 +211,15 @@ namespace Titanium.Web.Proxy
options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck; options.CertificateRevocationCheckMode = X509RevocationMode.NoCheck;
await sslStream.AuthenticateAsServerAsync(options, cancellationToken); await sslStream.AuthenticateAsServerAsync(options, cancellationToken);
#if NETCOREAPP2_1 #if NETSTANDARD2_1
clientConnection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol; clientConnection.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 CustomBufferedStream(sslStream, BufferPool, BufferSize); clientStream = new CustomBufferedStream(sslStream, BufferPool);
clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize); clientStream.DataRead += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count);
clientStream.DataWrite += (o, args) => connectArgs.OnDecryptedDataReceived(args.Buffer, args.Offset, args.Count);
clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool);
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -223,7 +228,7 @@ namespace Titanium.Web.Proxy ...@@ -223,7 +228,7 @@ namespace Titanium.Web.Proxy
$"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs); $"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs);
} }
if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, BufferSize, cancellationToken) == -1) if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, cancellationToken) == -1)
{ {
decryptSsl = false; decryptSsl = false;
} }
...@@ -263,7 +268,7 @@ namespace Titanium.Web.Proxy ...@@ -263,7 +268,7 @@ namespace Titanium.Web.Proxy
if (available > 0) if (available > 0)
{ {
// send the buffered data // send the buffered data
var data = BufferPool.GetBuffer(BufferSize); var data = BufferPool.GetBuffer();
try try
{ {
...@@ -283,10 +288,8 @@ namespace Titanium.Web.Proxy ...@@ -283,10 +288,8 @@ namespace Titanium.Web.Proxy
if (!clientStream.IsClosed && !connection.Stream.IsClosed) if (!clientStream.IsClosed && !connection.Stream.IsClosed)
{ {
await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool, BufferSize, await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool,
(buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); }, null, null, connectArgs.CancellationTokenSource, ExceptionFunc);
(buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
connectArgs.CancellationTokenSource, ExceptionFunc);
} }
} }
finally finally
...@@ -298,16 +301,16 @@ namespace Titanium.Web.Proxy ...@@ -298,16 +301,16 @@ namespace Titanium.Web.Proxy
} }
} }
if (connectArgs != null && await HttpHelper.IsPriMethod(clientStream, BufferPool, BufferSize, cancellationToken) == 1) if (connectArgs != null && await HttpHelper.IsPriMethod(clientStream, BufferPool, cancellationToken) == 1)
{ {
// todo // todo
string httpCmd = await clientStream.ReadLineAsync(cancellationToken); string? httpCmd = await clientStream.ReadLineAsync(cancellationToken);
if (httpCmd == "PRI * HTTP/2.0") if (httpCmd == "PRI * HTTP/2.0")
{ {
connectArgs.HttpClient.ConnectRequest.TunnelType = TunnelType.Http2; connectArgs.HttpClient.ConnectRequest!.TunnelType = TunnelType.Http2;
// HTTP/2 Connection Preface // HTTP/2 Connection Preface
string line = await clientStream.ReadLineAsync(cancellationToken); string? line = await clientStream.ReadLineAsync(cancellationToken);
if (line != string.Empty) if (line != string.Empty)
{ {
throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received"); throw new Exception($"HTTP/2 Protocol violation. Empty string expected, '{line}' received");
...@@ -330,22 +333,16 @@ namespace Titanium.Web.Proxy ...@@ -330,22 +333,16 @@ namespace Titanium.Web.Proxy
noCache: true, cancellationToken: cancellationToken); noCache: true, cancellationToken: cancellationToken);
try try
{ {
await connection.StreamWriter.WriteLineAsync("PRI * HTTP/2.0", cancellationToken); #if NETSTANDARD2_1
await connection.StreamWriter.WriteLineAsync(cancellationToken); var connectionPreface = new ReadOnlyMemory<byte>(Http2Helper.ConnectionPreface);
await connection.StreamWriter.WriteLineAsync("SM", cancellationToken); await connection.StreamWriter.WriteAsync(connectionPreface, cancellationToken);
await connection.StreamWriter.WriteLineAsync(cancellationToken); await Http2Helper.SendHttp2(clientStream, connection.Stream,
#if NETCOREAPP2_1 () => new SessionEventArgs(this, endPoint, new ProxyClient(clientConnection, clientStream, clientStreamWriter), connectArgs?.HttpClient.ConnectRequest, cancellationTokenSource)
await Http2Helper.SendHttp2(clientStream, connection.Stream, BufferSize,
(buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); },
(buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
() => new SessionEventArgs(this, endPoint, cancellationTokenSource)
{ {
ProxyClient = { Connection = clientConnection },
HttpClient = { ConnectRequest = connectArgs?.HttpClient.ConnectRequest },
UserData = connectArgs?.UserData UserData = connectArgs?.UserData
}, },
async args => { await invokeBeforeRequest(args); }, async args => { await onBeforeRequest(args); },
async args => { await invokeBeforeResponse(args); }, async args => { await onBeforeResponse(args); },
connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc); connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc);
#endif #endif
} }
...@@ -357,9 +354,10 @@ namespace Titanium.Web.Proxy ...@@ -357,9 +354,10 @@ namespace Titanium.Web.Proxy
} }
calledRequestHandler = true; calledRequestHandler = true;
// Now create the request // Now create the request
await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter,
cancellationTokenSource, connectHostname, connectArgs, prefetchConnectionTask); cancellationTokenSource, connectArgs, prefetchConnectionTask);
} }
catch (ProxyException e) catch (ProxyException e)
{ {
......
using System;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Extensions
{
internal static class HttpHeaderExtensions
{
internal static string GetString(this ByteString str)
{
return GetString(str.Span);
}
internal static string GetString(this ReadOnlySpan<byte> bytes)
{
#if NETSTANDARD2_1
return HttpHeader.Encoding.GetString(bytes);
#else
return HttpHeader.Encoding.GetString(bytes.ToArray());
#endif
}
internal static ByteString GetByteString(this string str)
{
return HttpHeader.Encoding.GetBytes(str);
}
}
}
...@@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy.Extensions
internal static readonly List<SslApplicationProtocol> Http2ProtocolAsList = internal static readonly List<SslApplicationProtocol> Http2ProtocolAsList =
new List<SslApplicationProtocol> { SslApplicationProtocol.Http2 }; new List<SslApplicationProtocol> { SslApplicationProtocol.Http2 };
internal static string GetServerName(this ClientHelloInfo clientHelloInfo) internal static string? GetServerName(this ClientHelloInfo clientHelloInfo)
{ {
if (clientHelloInfo.Extensions != null && if (clientHelloInfo.Extensions != null &&
clientHelloInfo.Extensions.TryGetValue("server_name", out var serverNameExtension)) clientHelloInfo.Extensions.TryGetValue("server_name", out var serverNameExtension))
...@@ -28,8 +28,8 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -28,8 +28,8 @@ namespace Titanium.Web.Proxy.Extensions
return null; return null;
} }
#if NETCOREAPP2_1 #if NETSTANDARD2_1
internal static List<SslApplicationProtocol> GetAlpn(this ClientHelloInfo clientHelloInfo) internal static List<SslApplicationProtocol>? GetAlpn(this ClientHelloInfo clientHelloInfo)
{ {
if (clientHelloInfo.Extensions != null && clientHelloInfo.Extensions.TryGetValue("ALPN", out var alpnExtension)) if (clientHelloInfo.Extensions != null && clientHelloInfo.Extensions.TryGetValue("ALPN", out var alpnExtension))
{ {
...@@ -77,32 +77,36 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -77,32 +77,36 @@ namespace Titanium.Web.Proxy.Extensions
} }
#endif #endif
} }
}
#if !NETCOREAPP2_1 #if !NETSTANDARD2_1
namespace System.Net.Security
{
internal enum SslApplicationProtocol internal enum SslApplicationProtocol
{ {
Http11, Http11,
Http2 Http2
} }
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "Reviewed.")] [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification =
"Reviewed.")]
internal class SslClientAuthenticationOptions internal class SslClientAuthenticationOptions
{ {
internal bool AllowRenegotiation { get; set; } internal bool AllowRenegotiation { get; set; }
internal string TargetHost { get; set; } internal string? TargetHost { get; set; }
internal X509CertificateCollection ClientCertificates { get; set; } internal X509CertificateCollection? ClientCertificates { get; set; }
internal LocalCertificateSelectionCallback LocalCertificateSelectionCallback { get; set; } internal LocalCertificateSelectionCallback? LocalCertificateSelectionCallback { get; set; }
internal SslProtocols EnabledSslProtocols { get; set; } internal SslProtocols EnabledSslProtocols { get; set; }
internal X509RevocationMode CertificateRevocationCheckMode { get; set; } internal X509RevocationMode CertificateRevocationCheckMode { get; set; }
internal List<SslApplicationProtocol> ApplicationProtocols { get; set; } internal List<SslApplicationProtocol>? ApplicationProtocols { get; set; }
internal RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; } internal RemoteCertificateValidationCallback? RemoteCertificateValidationCallback { get; set; }
internal EncryptionPolicy EncryptionPolicy { get; set; } internal EncryptionPolicy EncryptionPolicy { get; set; }
} }
...@@ -111,7 +115,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -111,7 +115,7 @@ namespace Titanium.Web.Proxy.Extensions
{ {
internal bool AllowRenegotiation { get; set; } internal bool AllowRenegotiation { get; set; }
internal X509Certificate ServerCertificate { get; set; } internal X509Certificate? ServerCertificate { get; set; }
internal bool ClientCertificateRequired { get; set; } internal bool ClientCertificateRequired { get; set; }
...@@ -119,11 +123,11 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -119,11 +123,11 @@ namespace Titanium.Web.Proxy.Extensions
internal X509RevocationMode CertificateRevocationCheckMode { get; set; } internal X509RevocationMode CertificateRevocationCheckMode { get; set; }
internal List<SslApplicationProtocol> ApplicationProtocols { get; set; } internal List<SslApplicationProtocol>? ApplicationProtocols { get; set; }
internal RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; } internal RemoteCertificateValidationCallback? RemoteCertificateValidationCallback { get; set; }
internal EncryptionPolicy EncryptionPolicy { get; set; } internal EncryptionPolicy EncryptionPolicy { get; set; }
} }
#endif
} }
#endif
...@@ -18,11 +18,10 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -18,11 +18,10 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="output"></param> /// <param name="output"></param>
/// <param name="onCopy"></param> /// <param name="onCopy"></param>
/// <param name="bufferPool"></param> /// <param name="bufferPool"></param>
/// <param name="bufferSize"></param>
internal static Task CopyToAsync(this Stream input, Stream output, Action<byte[], int, int> onCopy, internal static Task CopyToAsync(this Stream input, Stream output, Action<byte[], int, int> onCopy,
IBufferPool bufferPool, int bufferSize) IBufferPool bufferPool)
{ {
return CopyToAsync(input, output, onCopy, bufferPool, bufferSize, CancellationToken.None); return CopyToAsync(input, output, onCopy, bufferPool, CancellationToken.None);
} }
/// <summary> /// <summary>
...@@ -32,12 +31,11 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -32,12 +31,11 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="output"></param> /// <param name="output"></param>
/// <param name="onCopy"></param> /// <param name="onCopy"></param>
/// <param name="bufferPool"></param> /// <param name="bufferPool"></param>
/// <param name="bufferSize"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
internal static async Task CopyToAsync(this Stream input, Stream output, Action<byte[], int, int> onCopy, internal static async Task CopyToAsync(this Stream input, Stream output, Action<byte[], int, int>? onCopy,
IBufferPool bufferPool, int bufferSize, CancellationToken cancellationToken) IBufferPool bufferPool, CancellationToken cancellationToken)
{ {
var buffer = bufferPool.GetBuffer(bufferSize); var buffer = bufferPool.GetBuffer();
try try
{ {
while (!cancellationToken.IsCancellationRequested) while (!cancellationToken.IsCancellationRequested)
...@@ -64,7 +62,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -64,7 +62,7 @@ namespace Titanium.Web.Proxy.Extensions
} }
} }
private static async Task<T> withCancellation<T>(this Task<T> task, CancellationToken cancellationToken) private static async Task<T> withCancellation<T>(this Task<T> task, CancellationToken cancellationToken) where T : struct
{ {
var tcs = new TaskCompletionSource<bool>(); var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs)) using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
......
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
{ {
...@@ -10,6 +11,11 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -10,6 +11,11 @@ namespace Titanium.Web.Proxy.Extensions
return str.Equals(value, StringComparison.CurrentCultureIgnoreCase); return str.Equals(value, StringComparison.CurrentCultureIgnoreCase);
} }
internal static bool EqualsIgnoreCase(this ReadOnlySpan<char> str, ReadOnlySpan<char> value)
{
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;
......
using System; using System;
using System.Net.Sockets; using System.Net.Sockets;
using System.Reflection;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
......
using System; using System;
using System.Text;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
......
using System; using System;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.StreamExtended.BufferPool; using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network; using Titanium.Web.Proxy.StreamExtended.Network;
...@@ -14,42 +14,84 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -14,42 +14,84 @@ namespace Titanium.Web.Proxy.Helpers
{ {
internal static class HttpHelper internal static class HttpHelper
{ {
private static readonly Encoding defaultEncoding = Encoding.GetEncoding("ISO-8859-1"); struct SemicolonSplitEnumerator
{
private readonly ReadOnlyMemory<char> data;
private ReadOnlyMemory<char> current;
private int idx;
public SemicolonSplitEnumerator(string str) : this(str.AsMemory())
{
}
public SemicolonSplitEnumerator(ReadOnlyMemory<char> data)
{
this.data = data;
current = null;
idx = 0;
}
public SemicolonSplitEnumerator GetEnumerator() { return this; }
public bool MoveNext()
{
if (this.idx > data.Length) return false;
int idx = data.Span.Slice(this.idx).IndexOf(';');
if (idx == -1)
{
idx = data.Length;
}
else
{
idx += this.idx;
}
current = data.Slice(this.idx, idx - this.idx);
this.idx = idx + 1;
return true;
}
public ReadOnlyMemory<char> Current => current;
}
/// <summary> /// <summary>
/// Gets the character encoding of request/response from content-type header /// Gets the character encoding of request/response from content-type header
/// </summary> /// </summary>
/// <param name="contentType"></param> /// <param name="contentType"></param>
/// <returns></returns> /// <returns></returns>
internal static Encoding GetEncodingFromContentType(string contentType) internal static Encoding GetEncodingFromContentType(string? contentType)
{ {
try try
{ {
// return default if not specified // return default if not specified
if (contentType == null) if (contentType == null)
{ {
return defaultEncoding; return HttpHeader.DefaultEncoding;
} }
// extract the encoding by finding the charset // extract the encoding by finding the charset
var parameters = contentType.Split(ProxyConstants.SemiColonSplit); foreach (var p in new SemicolonSplitEnumerator(contentType))
foreach (string parameter in parameters)
{ {
var split = parameter.Split(ProxyConstants.EqualSplit, 2); var parameter = p.Span;
if (split.Length == 2 && split[0].Trim().EqualsIgnoreCase(KnownHeaders.ContentTypeCharset)) int equalsIndex = parameter.IndexOf('=');
if (equalsIndex != -1 && KnownHeaders.ContentTypeCharset.Equals(parameter.Slice(0, equalsIndex).TrimStart()))
{ {
string value = split[1]; var value = parameter.Slice(equalsIndex + 1);
if (value.EqualsIgnoreCase("x-user-defined")) if (value.EqualsIgnoreCase("x-user-defined".AsSpan()))
{ {
continue; continue;
} }
if (value.Length > 2 && value[0] == '"' && value[value.Length - 1] == '"') if (value.Length > 2 && value[0] == '"' && value[value.Length - 1] == '"')
{ {
value = value.Substring(1, value.Length - 2); value = value.Slice(1, value.Length - 2);
} }
return Encoding.GetEncoding(value); return Encoding.GetEncoding(value.ToString());
} }
} }
} }
...@@ -60,24 +102,23 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -60,24 +102,23 @@ namespace Titanium.Web.Proxy.Helpers
} }
// return default if not specified // return default if not specified
return defaultEncoding; return HttpHeader.DefaultEncoding;
} }
internal static string GetBoundaryFromContentType(string contentType) internal static ReadOnlyMemory<char> GetBoundaryFromContentType(string? contentType)
{ {
if (contentType != null) if (contentType != null)
{ {
// extract the boundary // extract the boundary
var parameters = contentType.Split(ProxyConstants.SemiColonSplit); foreach (var parameter in new SemicolonSplitEnumerator(contentType))
foreach (string parameter in parameters)
{ {
var split = parameter.Split(ProxyConstants.EqualSplit, 2); int equalsIndex = parameter.Span.IndexOf('=');
if (split.Length == 2 && split[0].Trim().EqualsIgnoreCase(KnownHeaders.ContentTypeBoundary)) if (equalsIndex != -1 && KnownHeaders.ContentTypeBoundary.Equals(parameter.Span.Slice(0, equalsIndex).TrimStart()))
{ {
string value = split[1]; var value = parameter.Slice(equalsIndex + 1);
if (value.Length > 2 && value[0] == '"' && value[value.Length - 1] == '"') if (value.Length > 2 && value.Span[0] == '"' && value.Span[value.Length - 1] == '"')
{ {
value = value.Substring(1, value.Length - 2); value = value.Slice(1, value.Length - 2);
} }
return value; return value;
...@@ -128,47 +169,49 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -128,47 +169,49 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary> /// <summary>
/// Determines whether is connect method. /// Determines whether is connect method.
/// </summary> /// </summary>
/// <param name="clientStreamReader">The client stream reader.</param>
/// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns> /// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns>
internal static Task<int> IsConnectMethod(ICustomStreamReader clientStreamReader, IBufferPool bufferPool, int bufferSize, CancellationToken cancellationToken = default) internal static Task<int> IsConnectMethod(CustomBufferedStream clientStreamReader, IBufferPool bufferPool, CancellationToken cancellationToken = default)
{ {
return startsWith(clientStreamReader, bufferPool, bufferSize, "CONNECT", cancellationToken); return startsWith(clientStreamReader, bufferPool, "CONNECT", cancellationToken);
} }
/// <summary> /// <summary>
/// Determines whether is pri method (HTTP/2). /// Determines whether is pri method (HTTP/2).
/// </summary> /// </summary>
/// <param name="clientStreamReader">The client stream reader.</param>
/// <returns>1: when PRI, 0: when valid HTTP method, -1: otherwise</returns> /// <returns>1: when PRI, 0: when valid HTTP method, -1: otherwise</returns>
internal static Task<int> IsPriMethod(ICustomStreamReader clientStreamReader, IBufferPool bufferPool, int bufferSize, CancellationToken cancellationToken = default) internal static Task<int> IsPriMethod(CustomBufferedStream clientStreamReader, IBufferPool bufferPool, CancellationToken cancellationToken = default)
{ {
return startsWith(clientStreamReader, bufferPool, bufferSize, "PRI", cancellationToken); return startsWith(clientStreamReader, bufferPool, "PRI", cancellationToken);
} }
/// <summary> /// <summary>
/// Determines whether the stream starts with the given string. /// Determines whether the stream starts with the given string.
/// </summary> /// </summary>
/// <param name="clientStreamReader">The client stream reader.</param>
/// <param name="expectedStart">The expected start.</param>
/// <returns> /// <returns>
/// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise /// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise
/// </returns> /// </returns>
private static async Task<int> startsWith(ICustomStreamReader clientStreamReader, IBufferPool bufferPool, int bufferSize, string expectedStart, CancellationToken cancellationToken = default) private static async Task<int> startsWith(CustomBufferedStream clientStreamReader, IBufferPool bufferPool, string expectedStart, CancellationToken cancellationToken = default)
{ {
int iRet = -1;
const int lengthToCheck = 10; const int lengthToCheck = 10;
byte[] buffer = null; if (bufferPool.BufferSize < lengthToCheck)
try
{ {
buffer = bufferPool.GetBuffer(Math.Max(bufferSize, lengthToCheck)); throw new Exception($"Buffer is too small. Minimum size is {lengthToCheck} bytes");
}
int peeked = await clientStreamReader.PeekBytesAsync(buffer, 0, 0, lengthToCheck, cancellationToken);
if (peeked > 0) byte[] buffer = bufferPool.GetBuffer(bufferPool.BufferSize);
try
{
bool isExpected = true;
int i = 0;
while (i < lengthToCheck)
{ {
bool isExpected = true; int peeked = await clientStreamReader.PeekBytesAsync(buffer, i, i, lengthToCheck - i, cancellationToken);
if (peeked <= 0)
return -1;
for (int i = 0; i < lengthToCheck; i++) peeked += i;
while (i < peeked)
{ {
int b = buffer[i]; int b = buffer[i];
...@@ -177,23 +220,23 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -177,23 +220,23 @@ namespace Titanium.Web.Proxy.Helpers
else else
{ {
char ch = (char)b; char ch = (char)b;
if (!char.IsLetter(ch)) if (ch < 'A' || ch > 'z' || (ch > 'Z' && ch < 'a')) // ASCII letter
return -1; return -1;
else if (i >= expectedStart.Length || ch != expectedStart[i]) else if (i >= expectedStart.Length || ch != expectedStart[i])
isExpected = false; isExpected = false;
} }
}
// only letters i++;
iRet = isExpected ? 1 : 0; }
} }
// only letters
return 0;
} }
finally finally
{ {
bufferPool.ReturnBuffer(buffer); bufferPool.ReturnBuffer(buffer);
buffer = null;
} }
return iRet;
} }
} }
} }
...@@ -8,8 +8,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -8,8 +8,8 @@ namespace Titanium.Web.Proxy.Helpers
{ {
internal sealed class HttpRequestWriter : HttpWriter internal sealed class HttpRequestWriter : HttpWriter
{ {
internal HttpRequestWriter(Stream stream, IBufferPool bufferPool, int bufferSize) internal HttpRequestWriter(Stream stream, IBufferPool bufferPool)
: base(stream, bufferPool, bufferSize) : base(stream, bufferPool)
{ {
} }
...@@ -17,15 +17,13 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -17,15 +17,13 @@ namespace Titanium.Web.Proxy.Helpers
/// Writes the request. /// Writes the request.
/// </summary> /// </summary>
/// <param name="request">The request object.</param> /// <param name="request">The request object.</param>
/// <param name="flush">Should we flush after write?</param>
/// <param name="cancellationToken">Optional cancellation token for this async task.</param> /// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns></returns> /// <returns></returns>
internal async Task WriteRequestAsync(Request request, bool flush = true, internal async Task WriteRequestAsync(Request request, CancellationToken cancellationToken = default)
CancellationToken cancellationToken = default)
{ {
await WriteLineAsync(Request.CreateRequestLine(request.Method, request.RequestUriString, request.HttpVersion), var headerBuilder = new HeaderBuilder();
cancellationToken); headerBuilder.WriteRequestLine(request.Method, request.Url, request.HttpVersion);
await WriteAsync(request, flush, cancellationToken); await WriteAsync(request, headerBuilder, cancellationToken);
} }
} }
} }
...@@ -9,8 +9,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -9,8 +9,8 @@ namespace Titanium.Web.Proxy.Helpers
{ {
internal sealed class HttpResponseWriter : HttpWriter internal sealed class HttpResponseWriter : HttpWriter
{ {
internal HttpResponseWriter(Stream stream, IBufferPool bufferPool, int bufferSize) internal HttpResponseWriter(Stream stream, IBufferPool bufferPool)
: base(stream, bufferPool, bufferSize) : base(stream, bufferPool)
{ {
} }
...@@ -18,29 +18,13 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -18,29 +18,13 @@ namespace Titanium.Web.Proxy.Helpers
/// Writes the response. /// Writes the response.
/// </summary> /// </summary>
/// <param name="response">The response object.</param> /// <param name="response">The response object.</param>
/// <param name="flush">Should we flush after write?</param>
/// <param name="cancellationToken">Optional cancellation token for this async task.</param> /// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns>The Task.</returns> /// <returns>The Task.</returns>
internal async Task WriteResponseAsync(Response response, bool flush = true, internal async Task WriteResponseAsync(Response response, CancellationToken cancellationToken = default)
CancellationToken cancellationToken = default)
{ {
await WriteResponseStatusAsync(response.HttpVersion, response.StatusCode, response.StatusDescription, var headerBuilder = new HeaderBuilder();
cancellationToken); headerBuilder.WriteResponseLine(response.HttpVersion, response.StatusCode, response.StatusDescription);
await WriteAsync(response, flush, cancellationToken); await WriteAsync(response, headerBuilder, cancellationToken);
}
/// <summary>
/// Write response status
/// </summary>
/// <param name="version">The Http version.</param>
/// <param name="code">The HTTP status code.</param>
/// <param name="description">The HTTP status description.</param>
/// <param name="cancellationToken">Optional cancellation token for this async task.</param>
/// <returns>The Task.</returns>
internal Task WriteResponseStatusAsync(Version version, int code, string description,
CancellationToken cancellationToken)
{
return WriteLineAsync(Response.CreateResponseLine(version, code, description), cancellationToken);
} }
} }
} }
using System; using System;
using System.Buffers;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Text; using System.Text;
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.Models;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
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,17 +20,14 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -18,17 +20,14 @@ namespace Titanium.Web.Proxy.Helpers
private static readonly byte[] newLine = ProxyConstants.NewLineBytes; private static readonly byte[] newLine = ProxyConstants.NewLineBytes;
private static readonly Encoding encoder = Encoding.ASCII; private static Encoding encoding => HttpHeader.Encoding;
internal HttpWriter(Stream stream, IBufferPool bufferPool, int bufferSize) internal HttpWriter(Stream stream, IBufferPool bufferPool)
{ {
BufferSize = bufferSize;
this.stream = stream; this.stream = stream;
this.bufferPool = bufferPool; this.bufferPool = bufferPool;
} }
internal int BufferSize { get; }
/// <summary> /// <summary>
/// Writes a line async /// Writes a line async
/// </summary> /// </summary>
...@@ -48,12 +47,12 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -48,12 +47,12 @@ namespace Titanium.Web.Proxy.Helpers
{ {
int newLineChars = addNewLine ? newLine.Length : 0; int newLineChars = addNewLine ? newLine.Length : 0;
int charCount = value.Length; int charCount = value.Length;
if (charCount < BufferSize - newLineChars) if (charCount < bufferPool.BufferSize - newLineChars)
{ {
var buffer = bufferPool.GetBuffer(BufferSize); var buffer = bufferPool.GetBuffer();
try try
{ {
int idx = encoder.GetBytes(value, 0, charCount, buffer, 0); int idx = encoding.GetBytes(value, 0, charCount, buffer, 0);
if (newLineChars > 0) if (newLineChars > 0)
{ {
Buffer.BlockCopy(newLine, 0, buffer, idx, newLineChars); Buffer.BlockCopy(newLine, 0, buffer, idx, newLineChars);
...@@ -70,7 +69,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -70,7 +69,7 @@ namespace Titanium.Web.Proxy.Helpers
else else
{ {
var buffer = new byte[charCount + newLineChars + 1]; var buffer = new byte[charCount + newLineChars + 1];
int idx = encoder.GetBytes(value, 0, charCount, buffer, 0); int idx = encoding.GetBytes(value, 0, charCount, buffer, 0);
if (newLineChars > 0) if (newLineChars > 0)
{ {
Buffer.BlockCopy(newLine, 0, buffer, idx, newLineChars); Buffer.BlockCopy(newLine, 0, buffer, idx, newLineChars);
...@@ -89,28 +88,21 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -89,28 +88,21 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary> /// <summary>
/// Write the headers to client /// Write the headers to client
/// </summary> /// </summary>
/// <param name="headers"></param> /// <param name="headerBuilder"></param>
/// <param name="flush"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
internal async Task WriteHeadersAsync(HeaderCollection headers, bool flush = true, internal async Task WriteHeadersAsync(HeaderBuilder headerBuilder, CancellationToken cancellationToken = default)
CancellationToken cancellationToken = default)
{ {
var headerBuilder = new StringBuilder(); var buffer = headerBuilder.GetBuffer();
foreach (var header in headers) await WriteAsync(buffer.Array, buffer.Offset, buffer.Count, true, cancellationToken);
{
headerBuilder.Append($"{header.ToString()}{ProxyConstants.NewLine}");
}
headerBuilder.Append(ProxyConstants.NewLine);
await WriteAsync(headerBuilder.ToString(), cancellationToken);
if (flush)
{
await stream.FlushAsync(cancellationToken);
}
} }
/// <summary>
/// Writes the data to the stream.
/// </summary>
/// <param name="data">The data.</param>
/// <param name="flush">Should we flush after write?</param>
/// <param name="cancellationToken">The cancellation token.</param>
internal async Task WriteAsync(byte[] data, bool flush = false, CancellationToken cancellationToken = default) internal async Task WriteAsync(byte[] data, bool flush = false, CancellationToken cancellationToken = default)
{ {
await stream.WriteAsync(data, 0, data.Length, cancellationToken); await stream.WriteAsync(data, 0, data.Length, cancellationToken);
...@@ -157,8 +149,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -157,8 +149,8 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="onCopy"></param> /// <param name="onCopy"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
internal Task CopyBodyAsync(ICustomStreamReader streamReader, bool isChunked, long contentLength, internal Task CopyBodyAsync(CustomBufferedStream streamReader, bool isChunked, long contentLength,
Action<byte[], int, int> onCopy, CancellationToken cancellationToken) Action<byte[], int, int>? onCopy, CancellationToken cancellationToken)
{ {
// For chunked request we need to read data as they arrive, until we reach a chunk end symbol // For chunked request we need to read data as they arrive, until we reach a chunk end symbol
if (isChunked) if (isChunked)
...@@ -202,12 +194,11 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -202,12 +194,11 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="onCopy"></param> /// <param name="onCopy"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
private async Task copyBodyChunkedAsync(ICustomStreamReader reader, Action<byte[], int, int> onCopy, private async Task copyBodyChunkedAsync(CustomBufferedStream reader, Action<byte[], int, int>? onCopy, CancellationToken cancellationToken)
CancellationToken cancellationToken)
{ {
while (true) while (true)
{ {
string chunkHead = await reader.ReadLineAsync(cancellationToken); string chunkHead = (await reader.ReadLineAsync(cancellationToken))!;
int idx = chunkHead.IndexOf(";"); int idx = chunkHead.IndexOf(";");
if (idx >= 0) if (idx >= 0)
{ {
...@@ -243,10 +234,10 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -243,10 +234,10 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="onCopy"></param> /// <param name="onCopy"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
private async Task copyBytesFromStream(ICustomStreamReader reader, long count, Action<byte[], int, int> onCopy, private async Task copyBytesFromStream(CustomBufferedStream reader, long count, Action<byte[], int, int>? onCopy,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
var buffer = bufferPool.GetBuffer(BufferSize); var buffer = bufferPool.GetBuffer();
try try
{ {
...@@ -283,14 +274,14 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -283,14 +274,14 @@ namespace Titanium.Web.Proxy.Helpers
/// Writes the request/response headers and body. /// Writes the request/response headers and body.
/// </summary> /// </summary>
/// <param name="requestResponse"></param> /// <param name="requestResponse"></param>
/// <param name="flush"></param> /// <param name="headerBuilder"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
protected async Task WriteAsync(RequestResponseBase requestResponse, bool flush = true, protected async Task WriteAsync(RequestResponseBase requestResponse, HeaderBuilder headerBuilder, CancellationToken cancellationToken = default)
CancellationToken cancellationToken = default)
{ {
var body = requestResponse.CompressBodyAndUpdateContentLength(); var body = requestResponse.CompressBodyAndUpdateContentLength();
await WriteHeadersAsync(requestResponse.Headers, flush, cancellationToken); headerBuilder.WriteHeaders(requestResponse.Headers);
await WriteHeadersAsync(headerBuilder, cancellationToken);
if (body != null) if (body != null)
{ {
...@@ -325,5 +316,31 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -325,5 +316,31 @@ namespace Titanium.Web.Proxy.Helpers
{ {
return stream.WriteAsync(buffer, offset, count, cancellationToken); return stream.WriteAsync(buffer, offset, count, cancellationToken);
} }
#if NETSTANDARD2_1
/// <summary>
/// Asynchronously writes a sequence of bytes to the current stream, advances the current position within this stream by the number of bytes written, and monitors cancellation requests.
/// </summary>
/// <param name="buffer">The buffer to write data from.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param>
/// <returns>A task that represents the asynchronous write operation.</returns>
public ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
{
return stream.WriteAsync(buffer, cancellationToken);
}
#else
/// <summary>
/// Asynchronously writes a sequence of bytes to the current stream, advances the current position within this stream by the number of bytes written, and monitors cancellation requests.
/// </summary>
/// <param name="buffer">The buffer to write data from.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param>
/// <returns>A task that represents the asynchronous write operation.</returns>
public Task WriteAsync2(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
{
var buf = ArrayPool<byte>.Shared.Rent(buffer.Length);
buffer.CopyTo(buf);
return stream.WriteAsync(buf, 0, buf.Length, cancellationToken);
}
#endif
} }
} }
using System; using System;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets; using System.Net.Sockets;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
......
...@@ -9,8 +9,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -9,8 +9,8 @@ namespace Titanium.Web.Proxy.Helpers
{ {
internal class ProxyInfo internal class ProxyInfo
{ {
internal ProxyInfo(bool? autoDetect, string autoConfigUrl, int? proxyEnable, string proxyServer, internal ProxyInfo(bool? autoDetect, string? autoConfigUrl, int? proxyEnable, string? proxyServer,
string proxyOverride) string? proxyOverride)
{ {
AutoDetect = autoDetect; AutoDetect = autoDetect;
AutoConfigUrl = autoConfigUrl; AutoConfigUrl = autoConfigUrl;
...@@ -54,21 +54,21 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -54,21 +54,21 @@ namespace Titanium.Web.Proxy.Helpers
internal bool? AutoDetect { get; } internal bool? AutoDetect { get; }
internal string AutoConfigUrl { get; } internal string? AutoConfigUrl { get; }
internal int? ProxyEnable { get; } internal int? ProxyEnable { get; }
internal string ProxyServer { get; } internal string? ProxyServer { get; }
internal string ProxyOverride { get; } internal string? ProxyOverride { get; }
internal bool BypassLoopback { get; } internal bool BypassLoopback { get; }
internal bool BypassOnLocal { get; } internal bool BypassOnLocal { get; }
internal Dictionary<ProxyProtocolType, HttpSystemProxyValue> Proxies { get; } internal Dictionary<ProxyProtocolType, HttpSystemProxyValue>? Proxies { get; }
internal string[] BypassList { get; } internal string[]? BypassList { get; }
private static string bypassStringEscape(string rawString) private static string bypassStringEscape(string rawString)
{ {
...@@ -158,7 +158,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -158,7 +158,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
/// <param name="proxyServerValues"></param> /// <param name="proxyServerValues"></param>
/// <returns></returns> /// <returns></returns>
internal static List<HttpSystemProxyValue> GetSystemProxyValues(string proxyServerValues) internal static List<HttpSystemProxyValue> GetSystemProxyValues(string? proxyServerValues)
{ {
var result = new List<HttpSystemProxyValue>(); var result = new List<HttpSystemProxyValue>();
...@@ -167,11 +167,19 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -167,11 +167,19 @@ namespace Titanium.Web.Proxy.Helpers
return result; return result;
} }
var proxyValues = proxyServerValues.Split(';'); var proxyValues = proxyServerValues!.Split(';');
if (proxyValues.Length > 0) if (proxyValues.Length > 0)
{ {
result.AddRange(proxyValues.Select(parseProxyValue).Where(parsedValue => parsedValue != null)); foreach (string str in proxyValues)
{
var proxyValue = parseProxyValue(str);
if (proxyValue != null)
{
result.Add(proxyValue);
}
}
} }
else else
{ {
...@@ -190,7 +198,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -190,7 +198,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
private static HttpSystemProxyValue parseProxyValue(string value) private static HttpSystemProxyValue? parseProxyValue(string value)
{ {
string tmp = Regex.Replace(value, @"\s+", " ").Trim(); string tmp = Regex.Replace(value, @"\s+", " ").Trim();
......
using System; using System;
using System.Reflection;
using System.Text; using System.Text;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
...@@ -41,6 +43,62 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -41,6 +43,62 @@ namespace Titanium.Web.Proxy.Helpers
public static bool IsUwpOnWindows => IsWindows && UwpHelper.IsRunningAsUwp(); public static bool IsUwpOnWindows => IsWindows && UwpHelper.IsRunningAsUwp();
public static bool IsMac => isRunningOnMac; public static bool IsMac => isRunningOnMac;
/// <summary>
/// Is socket reuse available to use?
/// </summary>
public static bool IsSocketReuseAvailable => isSocketReuseAvailable();
private static bool? _isSocketReuseAvailable;
private static bool isSocketReuseAvailable()
{
// use the cached value if we have one
if (_isSocketReuseAvailable != null)
return _isSocketReuseAvailable.Value;
try
{
if (IsWindows)
{
// since we are on windows just return true
// store the result in our static object so we don't have to be bothered going through all this more than once
_isSocketReuseAvailable = true;
return true;
}
// get the currently running framework name and version (EX: .NETFramework,Version=v4.5.1) (Ex: .NETCoreApp,Version=v2.0)
string ver = Assembly.GetEntryAssembly()?.GetCustomAttribute<TargetFrameworkAttribute>()?.FrameworkName;
if (ver == null)
return false; // play it safe if we can not figure out what the framework is
// make sure we are on .NETCoreApp
ver = ver.ToLower(); // make everything lowercase to simplify comparison
if (ver.Contains(".netcoreapp"))
{
var versionString = ver.Replace(".netcoreapp,version=v", "");
var versionArr = versionString.Split('.');
var majorVersion = Convert.ToInt32(versionArr[0]);
var result = majorVersion >= 3; // version 3 and up supports socket reuse
// store the result in our static object so we don't have to be bothered going through all this more than once
_isSocketReuseAvailable = result;
return result;
}
// store the result in our static object so we don't have to be bothered going through all this more than once
_isSocketReuseAvailable = false;
return false;
}
catch
{
// store the result in our static object so we don't have to be bothered going through all this more than once
_isSocketReuseAvailable = false;
return false;
}
}
// https://github.com/qmatteoq/DesktopBridgeHelpers/blob/master/DesktopBridge.Helpers/Helpers.cs // https://github.com/qmatteoq/DesktopBridgeHelpers/blob/master/DesktopBridge.Helpers/Helpers.cs
private class UwpHelper private class UwpHelper
......
...@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy.Helpers
internal const int InternetOptionSettingsChanged = 39; internal const int InternetOptionSettingsChanged = 39;
internal const int InternetOptionRefresh = 37; internal const int InternetOptionRefresh = 37;
private ProxyInfo originalValues; private ProxyInfo? originalValues;
public SystemProxyManager() public SystemProxyManager()
{ {
...@@ -90,8 +90,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -90,8 +90,8 @@ namespace Titanium.Web.Proxy.Helpers
saveOriginalProxyConfiguration(reg); saveOriginalProxyConfiguration(reg);
prepareRegistry(reg); prepareRegistry(reg);
string exisitingContent = reg.GetValue(regProxyServer) as string; string? existingContent = reg.GetValue(regProxyServer) as string;
var existingSystemProxyValues = ProxyInfo.GetSystemProxyValues(exisitingContent); var existingSystemProxyValues = ProxyInfo.GetSystemProxyValues(existingContent);
existingSystemProxyValues.RemoveAll(x => (protocolType & x.ProtocolType) != 0); existingSystemProxyValues.RemoveAll(x => (protocolType & x.ProtocolType) != 0);
if ((protocolType & ProxyProtocolType.Http) != 0) if ((protocolType & ProxyProtocolType.Http) != 0)
{ {
...@@ -141,9 +141,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -141,9 +141,9 @@ namespace Titanium.Web.Proxy.Helpers
if (reg.GetValue(regProxyServer) != null) if (reg.GetValue(regProxyServer) != null)
{ {
string exisitingContent = reg.GetValue(regProxyServer) as string; string? existingContent = reg.GetValue(regProxyServer) as string;
var existingSystemProxyValues = ProxyInfo.GetSystemProxyValues(exisitingContent); var existingSystemProxyValues = ProxyInfo.GetSystemProxyValues(existingContent);
existingSystemProxyValues.RemoveAll(x => (protocolType & x.ProtocolType) != 0); existingSystemProxyValues.RemoveAll(x => (protocolType & x.ProtocolType) != 0);
if (existingSystemProxyValues.Count != 0) if (existingSystemProxyValues.Count != 0)
...@@ -284,7 +284,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -284,7 +284,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
internal ProxyInfo GetProxyInfoFromRegistry() internal ProxyInfo? GetProxyInfoFromRegistry()
{ {
using (var reg = openInternetSettingsKey()) using (var reg = openInternetSettingsKey())
{ {
......
using System; using System;
using System.IO; using System.IO;
using System.Net.Sockets;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
...@@ -8,38 +9,32 @@ using Titanium.Web.Proxy.StreamExtended.BufferPool; ...@@ -8,38 +9,32 @@ using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
internal enum IpVersion
{
Ipv4 = 1,
Ipv6 = 2
}
internal class TcpHelper internal class TcpHelper
{ {
/// <summary> /// <summary>
/// Gets the process id by local port number. /// Gets the process id by local port number.
/// </summary> /// </summary>
/// <returns>Process id.</returns> /// <returns>Process id.</returns>
internal static unsafe int GetProcessIdByLocalPort(IpVersion ipVersion, int localPort) internal static unsafe int GetProcessIdByLocalPort(AddressFamily addressFamily, int localPort)
{ {
var tcpTable = IntPtr.Zero; var tcpTable = IntPtr.Zero;
int tcpTableLength = 0; int tcpTableLength = 0;
int ipVersionValue = ipVersion == IpVersion.Ipv4 ? NativeMethods.AfInet : NativeMethods.AfInet6; int addressFamilyValue = addressFamily == AddressFamily.InterNetwork ? NativeMethods.AfInet : NativeMethods.AfInet6;
const int allPid = (int)NativeMethods.TcpTableType.OwnerPidAll; const int allPid = (int)NativeMethods.TcpTableType.OwnerPidAll;
if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, false, ipVersionValue, allPid, 0) != 0) if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, false, addressFamilyValue, allPid, 0) != 0)
{ {
try try
{ {
tcpTable = Marshal.AllocHGlobal(tcpTableLength); tcpTable = Marshal.AllocHGlobal(tcpTableLength);
if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, ipVersionValue, allPid, if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, addressFamilyValue, allPid,
0) == 0) 0) == 0)
{ {
int rowCount = *(int*)tcpTable; int rowCount = *(int*)tcpTable;
uint portInNetworkByteOrder = toNetworkByteOrder((uint)localPort); uint portInNetworkByteOrder = toNetworkByteOrder((uint)localPort);
if (ipVersion == IpVersion.Ipv4) if (addressFamily == AddressFamily.InterNetwork)
{ {
var rowPtr = (NativeMethods.TcpRow*)(tcpTable + 4); var rowPtr = (NativeMethods.TcpRow*)(tcpTable + 4);
...@@ -102,23 +97,21 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -102,23 +97,21 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="clientStream"></param> /// <param name="clientStream"></param>
/// <param name="serverStream"></param> /// <param name="serverStream"></param>
/// <param name="bufferPool"></param> /// <param name="bufferPool"></param>
/// <param name="bufferSize"></param>
/// <param name="onDataSend"></param> /// <param name="onDataSend"></param>
/// <param name="onDataReceive"></param> /// <param name="onDataReceive"></param>
/// <param name="cancellationTokenSource"></param> /// <param name="cancellationTokenSource"></param>
/// <param name="exceptionFunc"></param> /// <param name="exceptionFunc"></param>
/// <returns></returns> /// <returns></returns>
private static async Task sendRawTap(Stream clientStream, Stream serverStream, private static async Task sendRawTap(Stream clientStream, Stream serverStream, IBufferPool bufferPool,
IBufferPool bufferPool, int bufferSize, Action<byte[], int, int>? onDataSend, Action<byte[], int, int>? onDataReceive,
Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive,
CancellationTokenSource cancellationTokenSource, CancellationTokenSource cancellationTokenSource,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
// Now async relay all server=>client & client=>server data // Now async relay all server=>client & client=>server data
var sendRelay = var sendRelay =
clientStream.CopyToAsync(serverStream, onDataSend, bufferPool, bufferSize, cancellationTokenSource.Token); clientStream.CopyToAsync(serverStream, onDataSend, bufferPool, cancellationTokenSource.Token);
var receiveRelay = var receiveRelay =
serverStream.CopyToAsync(clientStream, onDataReceive, bufferPool, bufferSize, cancellationTokenSource.Token); serverStream.CopyToAsync(clientStream, onDataReceive, bufferPool, cancellationTokenSource.Token);
await Task.WhenAny(sendRelay, receiveRelay); await Task.WhenAny(sendRelay, receiveRelay);
cancellationTokenSource.Cancel(); cancellationTokenSource.Cancel();
...@@ -134,20 +127,18 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -134,20 +127,18 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="clientStream"></param> /// <param name="clientStream"></param>
/// <param name="serverStream"></param> /// <param name="serverStream"></param>
/// <param name="bufferPool"></param> /// <param name="bufferPool"></param>
/// <param name="bufferSize"></param>
/// <param name="onDataSend"></param> /// <param name="onDataSend"></param>
/// <param name="onDataReceive"></param> /// <param name="onDataReceive"></param>
/// <param name="cancellationTokenSource"></param> /// <param name="cancellationTokenSource"></param>
/// <param name="exceptionFunc"></param> /// <param name="exceptionFunc"></param>
/// <returns></returns> /// <returns></returns>
internal static Task SendRaw(Stream clientStream, Stream serverStream, internal static Task SendRaw(Stream clientStream, Stream serverStream, IBufferPool bufferPool,
IBufferPool bufferPool, int bufferSize, Action<byte[], int, int>? onDataSend, Action<byte[], int, int>? onDataReceive,
Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive,
CancellationTokenSource cancellationTokenSource, CancellationTokenSource cancellationTokenSource,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
// todo: fix APM mode // todo: fix APM mode
return sendRawTap(clientStream, serverStream, bufferPool, bufferSize, onDataSend, onDataReceive, return sendRawTap(clientStream, serverStream, bufferPool, onDataSend, onDataReceive,
cancellationTokenSource, cancellationTokenSource,
exceptionFunc); exceptionFunc);
} }
......
...@@ -13,8 +13,8 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -13,8 +13,8 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
ref WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig); ref WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig);
[DllImport("winhttp.dll", CharSet = CharSet.Unicode, SetLastError = true)] [DllImport("winhttp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern WinHttpHandle WinHttpOpen(string userAgent, AccessType accessType, string proxyName, internal static extern WinHttpHandle WinHttpOpen(string? userAgent, AccessType accessType, string? proxyName,
string proxyBypass, int dwFlags); string? proxyBypass, int dwFlags);
[DllImport("winhttp.dll", CharSet = CharSet.Unicode, SetLastError = true)] [DllImport("winhttp.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool WinHttpSetTimeouts(WinHttpHandle session, int resolveTimeout, internal static extern bool WinHttpSetTimeouts(WinHttpHandle session, int resolveTimeout,
...@@ -66,7 +66,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -66,7 +66,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
{ {
public AutoProxyFlags Flags; public AutoProxyFlags Flags;
public AutoDetectType AutoDetectFlags; public AutoDetectType AutoDetectFlags;
[MarshalAs(UnmanagedType.LPWStr)] public string AutoConfigUrl; [MarshalAs(UnmanagedType.LPWStr)] public string? AutoConfigUrl;
private readonly IntPtr lpvReserved; private readonly IntPtr lpvReserved;
private readonly int dwReserved; private readonly int dwReserved;
public bool AutoLogonIfChallenged; public bool AutoLogonIfChallenged;
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
...@@ -34,26 +34,26 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -34,26 +34,26 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
} }
} }
public ICredentials Credentials { get; set; } public ICredentials? Credentials { get; set; }
public ProxyInfo ProxyInfo { get; internal set; } public ProxyInfo? ProxyInfo { get; internal set; }
public bool BypassLoopback { get; internal set; } public bool BypassLoopback { get; internal set; }
public bool BypassOnLocal { get; internal set; } public bool BypassOnLocal { get; internal set; }
public Uri AutomaticConfigurationScript { get; internal set; } public Uri? AutomaticConfigurationScript { get; internal set; }
public bool AutomaticallyDetectSettings { get; internal set; } public bool AutomaticallyDetectSettings { get; internal set; }
private WebProxy proxy { get; set; } private WebProxy? proxy { get; set; }
public void Dispose() public void Dispose()
{ {
dispose(true); dispose(true);
} }
public bool GetAutoProxies(Uri destination, out IList<string> proxyList) public bool GetAutoProxies(Uri destination, out IList<string>? proxyList)
{ {
proxyList = null; proxyList = null;
if (session == null || session.IsInvalid || state == AutoWebProxyState.UnrecognizedScheme) if (session == null || session.IsInvalid || state == AutoWebProxyState.UnrecognizedScheme)
...@@ -61,7 +61,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -61,7 +61,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return false; return false;
} }
string proxyListString = null; string? proxyListString = null;
var errorCode = NativeMethods.WinHttp.ErrorCodes.AudodetectionFailed; var errorCode = NativeMethods.WinHttp.ErrorCodes.AudodetectionFailed;
if (AutomaticallyDetectSettings && !autoDetectFailed) if (AutomaticallyDetectSettings && !autoDetectFailed)
{ {
...@@ -88,14 +88,14 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -88,14 +88,14 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
if (!string.IsNullOrEmpty(proxyListString)) if (!string.IsNullOrEmpty(proxyListString))
{ {
proxyListString = removeWhitespaces(proxyListString); proxyListString = removeWhitespaces(proxyListString!);
proxyList = proxyListString.Split(';'); proxyList = proxyListString.Split(';');
} }
return true; return true;
} }
public ExternalProxy GetProxy(Uri destination) public ExternalProxy? GetProxy(Uri destination)
{ {
if (GetAutoProxies(destination, out var proxies)) if (GetAutoProxies(destination, out var proxies))
{ {
...@@ -131,12 +131,12 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -131,12 +131,12 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
var protocolType = ProxyInfo.ParseProtocolType(destination.Scheme); var protocolType = ProxyInfo.ParseProtocolType(destination.Scheme);
if (protocolType.HasValue) if (protocolType.HasValue)
{ {
HttpSystemProxyValue value = null; HttpSystemProxyValue? value = null;
if (ProxyInfo?.Proxies?.TryGetValue(protocolType.Value, out value) == true) if (ProxyInfo?.Proxies?.TryGetValue(protocolType.Value, out value) == true)
{ {
var systemProxy = new ExternalProxy var systemProxy = new ExternalProxy
{ {
HostName = value.HostName, HostName = value!.HostName,
Port = value.Port Port = value.Port
}; };
...@@ -210,7 +210,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -210,7 +210,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
session.Close(); session.Close();
} }
private int getAutoProxies(Uri destination, Uri scriptLocation, out string proxyListString) private int getAutoProxies(Uri destination, Uri? scriptLocation, out string? proxyListString)
{ {
int num = 0; int num = 0;
var autoProxyOptions = new NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS(); var autoProxyOptions = new NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS();
...@@ -247,7 +247,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp ...@@ -247,7 +247,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
} }
private bool winHttpGetProxyForUrl(string destination, private bool winHttpGetProxyForUrl(string destination,
ref NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions, out string proxyListString) ref NativeMethods.WinHttp.WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions, out string? proxyListString)
{ {
proxyListString = null; proxyListString = null;
bool flag; bool flag;
......
using Titanium.Web.Proxy.StreamExtended; using System;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.StreamExtended;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
{ {
...@@ -7,13 +9,14 @@ namespace Titanium.Web.Proxy.Http ...@@ -7,13 +9,14 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public class ConnectRequest : Request public class ConnectRequest : Request
{ {
public ConnectRequest() public ConnectRequest(string authority)
{ {
Method = "CONNECT"; Method = "CONNECT";
Authority = authority;
} }
public TunnelType TunnelType { get; internal set; } public TunnelType TunnelType { get; internal set; }
public ClientHelloInfo ClientHelloInfo { get; set; } public ClientHelloInfo? ClientHelloInfo { get; set; }
} }
} }
...@@ -9,7 +9,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -9,7 +9,7 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public class ConnectResponse : Response public class ConnectResponse : Response
{ {
public ServerHelloInfo ServerHelloInfo { get; set; } public ServerHelloInfo? ServerHelloInfo { get; set; }
/// <summary> /// <summary>
/// Creates a successful CONNECT response /// Creates a successful CONNECT response
......
using System;
using System.Buffers;
using System.IO;
using System.Text;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Http
{
internal class HeaderBuilder
{
private readonly MemoryStream stream = new MemoryStream();
public void WriteRequestLine(string httpMethod, string httpUrl, Version version)
{
// "{httpMethod} {httpUrl} HTTP/{version.Major}.{version.Minor}";
Write(httpMethod);
Write(" ");
Write(httpUrl);
Write(" HTTP/");
Write(version.Major.ToString());
Write(".");
Write(version.Minor.ToString());
WriteLine();
}
public void WriteResponseLine(Version version, int statusCode, string statusDescription)
{
// "HTTP/{version.Major}.{version.Minor} {statusCode} {statusDescription}";
Write("HTTP/");
Write(version.Major.ToString());
Write(".");
Write(version.Minor.ToString());
Write(" ");
Write(statusCode.ToString());
Write(" ");
Write(statusDescription);
WriteLine();
}
public void WriteHeaders(HeaderCollection headers)
{
foreach (var header in headers)
{
WriteHeader(header);
}
WriteLine();
}
public void WriteHeader(HttpHeader header)
{
Write(header.Name);
Write(": ");
Write(header.Value);
WriteLine();
}
public void WriteLine()
{
var data = ProxyConstants.NewLineBytes;
stream.Write(data, 0, data.Length);
}
public void Write(string str)
{
var encoding = HttpHeader.Encoding;
#if NETSTANDARD2_1
var buf = ArrayPool<byte>.Shared.Rent(encoding.GetMaxByteCount(str.Length));
var span = new Span<byte>(buf);
int bytes = encoding.GetBytes(str.AsSpan(), span);
stream.Write(span.Slice(0, bytes));
ArrayPool<byte>.Shared.Return(buf);
#else
var data = encoding.GetBytes(str);
stream.Write(data, 0, data.Length);
#endif
}
public ArraySegment<byte> GetBuffer()
{
stream.TryGetBuffer(out var buffer);
return buffer;
}
public string GetString(Encoding encoding)
{
stream.TryGetBuffer(out var buffer);
return encoding.GetString(buffer.Array, buffer.Offset, buffer.Count);
}
}
}
...@@ -4,6 +4,7 @@ using System.Collections.Generic; ...@@ -4,6 +4,7 @@ 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
...@@ -71,7 +72,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -71,7 +72,7 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
/// <param name="name"></param> /// <param name="name"></param>
/// <returns></returns> /// <returns></returns>
public List<HttpHeader> GetHeaders(string name) public List<HttpHeader>? GetHeaders(string name)
{ {
if (headers.ContainsKey(name)) if (headers.ContainsKey(name))
{ {
...@@ -89,7 +90,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -89,7 +90,7 @@ namespace Titanium.Web.Proxy.Http
return null; return null;
} }
public HttpHeader GetFirstHeader(string name) public HttpHeader? GetFirstHeader(string name)
{ {
if (headers.TryGetValue(name, out var header)) if (headers.TryGetValue(name, out var header))
{ {
...@@ -104,6 +105,21 @@ namespace Titanium.Web.Proxy.Http ...@@ -104,6 +105,21 @@ namespace Titanium.Web.Proxy.Http
return null; return null;
} }
internal HttpHeader? GetFirstHeader(KnownHeader name)
{
if (headers.TryGetValue(name.String, out var header))
{
return header;
}
if (nonUniqueHeaders.TryGetValue(name.String, out var h))
{
return h.FirstOrDefault();
}
return null;
}
/// <summary> /// <summary>
/// Returns all headers /// Returns all headers
/// </summary> /// </summary>
...@@ -128,6 +144,16 @@ namespace Titanium.Web.Proxy.Http ...@@ -128,6 +144,16 @@ namespace Titanium.Web.Proxy.Http
AddHeader(new HttpHeader(name, value)); AddHeader(new HttpHeader(name, value));
} }
internal void AddHeader(KnownHeader name, string value)
{
AddHeader(new HttpHeader(name, value));
}
internal void AddHeader(KnownHeader name, KnownHeader value)
{
AddHeader(new HttpHeader(name, value));
}
/// <summary> /// <summary>
/// Adds the given header object to Request /// Adds the given header object to Request
/// </summary> /// </summary>
...@@ -198,7 +224,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -198,7 +224,7 @@ namespace Titanium.Web.Proxy.Http
/// Adds the given header objects to Request /// Adds the given header objects to Request
/// </summary> /// </summary>
/// <param name="newHeaders"></param> /// <param name="newHeaders"></param>
public void AddHeaders(IEnumerable<KeyValuePair<string, HttpHeader>> newHeaders) public void AddHeaders(IEnumerable<KeyValuePair<string, HttpHeader>>? newHeaders)
{ {
if (newHeaders == null) if (newHeaders == null)
{ {
...@@ -238,6 +264,27 @@ namespace Titanium.Web.Proxy.Http ...@@ -238,6 +264,27 @@ namespace Titanium.Web.Proxy.Http
return result; return result;
} }
/// <summary>
/// removes all headers with given name
/// </summary>
/// <param name="headerName"></param>
/// <returns>
/// True if header was removed
/// False if no header exists with given name
/// </returns>
public bool RemoveHeader(KnownHeader headerName)
{
bool result = headers.Remove(headerName.String);
// do not convert to '||' expression to avoid lazy evaluation
if (nonUniqueHeaders.Remove(headerName.String))
{
result = true;
}
return result;
}
/// <summary> /// <summary>
/// Removes given header object if it exist /// Removes given header object if it exist
/// </summary> /// </summary>
...@@ -272,9 +319,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -272,9 +319,9 @@ namespace Titanium.Web.Proxy.Http
nonUniqueHeaders.Clear(); nonUniqueHeaders.Clear();
} }
internal string GetHeaderValueOrNull(string headerName) internal string? GetHeaderValueOrNull(KnownHeader headerName)
{ {
if (headers.TryGetValue(headerName, out var header)) if (headers.TryGetValue(headerName.String, out var header))
{ {
return header.Value; return header.Value;
} }
...@@ -282,15 +329,33 @@ namespace Titanium.Web.Proxy.Http ...@@ -282,15 +329,33 @@ namespace Titanium.Web.Proxy.Http
return null; return null;
} }
internal void SetOrAddHeaderValue(string headerName, string value) internal void SetOrAddHeaderValue(KnownHeader headerName, string? value)
{
if (value == null)
{
RemoveHeader(headerName);
return;
}
if (headers.TryGetValue(headerName.String, out var header))
{
header.SetValue(value);
}
else
{
headers.Add(headerName.String, new HttpHeader(headerName, value));
}
}
internal void SetOrAddHeaderValue(KnownHeader headerName, KnownHeader value)
{ {
if (headers.TryGetValue(headerName, out var header)) if (headers.TryGetValue(headerName.String, out var header))
{ {
header.Value = value; header.SetValue(value);
} }
else else
{ {
headers.Add(headerName, new HttpHeader(headerName, value)); headers.Add(headerName.String, new HttpHeader(headerName, value));
} }
} }
...@@ -300,7 +365,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -300,7 +365,7 @@ namespace Titanium.Web.Proxy.Http
internal void FixProxyHeaders() internal void FixProxyHeaders()
{ {
// If proxy-connection close was returned inform to close the connection // If proxy-connection close was returned inform to close the connection
string proxyHeader = GetHeaderValueOrNull(KnownHeaders.ProxyConnection); string? proxyHeader = GetHeaderValueOrNull(KnownHeaders.ProxyConnection);
RemoveHeader(KnownHeaders.ProxyConnection); RemoveHeader(KnownHeaders.ProxyConnection);
if (proxyHeader != null) if (proxyHeader != null)
......
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.StreamExtended.Network; using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
{ {
internal static class HeaderParser internal static class HeaderParser
{ {
internal static async Task ReadHeaders(ICustomStreamReader reader, HeaderCollection headerCollection, internal static async Task ReadHeaders(ILineStream reader, HeaderCollection headerCollection,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
string tmpLine; string? tmpLine;
while (!string.IsNullOrEmpty(tmpLine = await reader.ReadLineAsync(cancellationToken))) while (!string.IsNullOrEmpty(tmpLine = await reader.ReadLineAsync(cancellationToken)))
{ {
var header = tmpLine.Split(ProxyConstants.ColonSplit, 2); int colonIndex = tmpLine!.IndexOf(':');
headerCollection.AddHeader(header[0], header[1]); if (colonIndex == -1)
{
throw new Exception("Header line should contain a colon character.");
}
string headerName = tmpLine.AsSpan(0, colonIndex).ToString();
string headerValue = tmpLine.AsSpan(colonIndex + 1).TrimStart().ToString();
headerCollection.AddHeader(headerName, headerValue);
} }
} }
......
...@@ -8,7 +8,6 @@ using Titanium.Web.Proxy.Exceptions; ...@@ -8,7 +8,6 @@ using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
{ {
...@@ -17,16 +16,33 @@ namespace Titanium.Web.Proxy.Http ...@@ -17,16 +16,33 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public class HttpWebClient public class HttpWebClient
{ {
internal HttpWebClient(Request request) private TcpServerConnection? connection;
internal HttpWebClient(ConnectRequest? connectRequest, Request request, Lazy<int> processIdFunc)
{ {
Request = request ?? new Request(); ConnectRequest = connectRequest;
Request = request;
Response = new Response(); Response = new Response();
ProcessId = processIdFunc;
} }
/// <summary> /// <summary>
/// Connection to server /// Connection to server
/// </summary> /// </summary>
internal TcpServerConnection Connection { get; set; } internal TcpServerConnection Connection
{
get
{
if (connection == null)
{
throw new Exception("Connection is null");
}
return connection;
}
}
internal bool HasConnection => connection != null;
/// <summary> /// <summary>
/// Should we close the server connection at the end of this HTTP request/response session. /// Should we close the server connection at the end of this HTTP request/response session.
...@@ -41,17 +57,17 @@ namespace Titanium.Web.Proxy.Http ...@@ -41,17 +57,17 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Gets or sets the user data. /// Gets or sets the user data.
/// </summary> /// </summary>
public object UserData { get; set; } public object? UserData { get; set; }
/// <summary> /// <summary>
/// Override UpStreamEndPoint for this request; Local NIC via request is made /// Override UpStreamEndPoint for this request; Local NIC via request is made
/// </summary> /// </summary>
public IPEndPoint UpStreamEndPoint { get; set; } public IPEndPoint? UpStreamEndPoint { get; set; }
/// <summary> /// <summary>
/// Headers passed with Connect. /// Headers passed with Connect.
/// </summary> /// </summary>
public ConnectRequest ConnectRequest { get; internal set; } public ConnectRequest? ConnectRequest { get; }
/// <summary> /// <summary>
/// Web Request. /// Web Request.
...@@ -81,7 +97,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -81,7 +97,7 @@ namespace Titanium.Web.Proxy.Http
internal void SetConnection(TcpServerConnection serverConnection) internal void SetConnection(TcpServerConnection serverConnection)
{ {
serverConnection.LastAccess = DateTime.Now; serverConnection.LastAccess = DateTime.Now;
Connection = serverConnection; connection = serverConnection;
} }
/// <summary> /// <summary>
...@@ -100,40 +116,44 @@ namespace Titanium.Web.Proxy.Http ...@@ -100,40 +116,44 @@ namespace Titanium.Web.Proxy.Http
string url; string url;
if (useUpstreamProxy || isTransparent) if (useUpstreamProxy || isTransparent)
{ {
url = Request.RequestUriString; url = Request.Url;
} }
else else
{ {
url = Request.RequestUri.GetOriginalPathAndQuery(); url = Request.RequestUri.GetOriginalPathAndQuery();
if (url == string.Empty)
{
url = "/";
}
} }
var headerBuilder = new HeaderBuilder();
// prepare the request & headers // prepare the request & headers
await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method, url, Request.HttpVersion), cancellationToken); headerBuilder.WriteRequestLine(Request.Method, url, Request.HttpVersion);
var headerBuilder = new StringBuilder();
// Send Authentication to Upstream proxy if needed // Send Authentication to Upstream proxy if needed
if (!isTransparent && upstreamProxy != null if (!isTransparent && upstreamProxy != null
&& Connection.IsHttps == false && Connection.IsHttps == false
&& !string.IsNullOrEmpty(upstreamProxy.UserName) && !string.IsNullOrEmpty(upstreamProxy.UserName)
&& upstreamProxy.Password != null) && upstreamProxy.Password != null)
{ {
headerBuilder.Append($"{HttpHeader.ProxyConnectionKeepAlive}{ProxyConstants.NewLine}"); headerBuilder.WriteHeader(HttpHeader.ProxyConnectionKeepAlive);
headerBuilder.Append($"{HttpHeader.GetProxyAuthorizationHeader(upstreamProxy.UserName, upstreamProxy.Password)}{ProxyConstants.NewLine}"); headerBuilder.WriteHeader(HttpHeader.GetProxyAuthorizationHeader(upstreamProxy.UserName, upstreamProxy.Password));
} }
// write request headers // write request headers
foreach (var header in Request.Headers) foreach (var header in Request.Headers)
{ {
if (isTransparent || header.Name != KnownHeaders.ProxyAuthorization) if (isTransparent || header.Name != KnownHeaders.ProxyAuthorization.String)
{ {
headerBuilder.Append($"{header}{ProxyConstants.NewLine}"); headerBuilder.WriteHeader(header);
} }
} }
headerBuilder.Append(ProxyConstants.NewLine); headerBuilder.WriteLine();
await writer.WriteAsync(headerBuilder.ToString(), cancellationToken); await writer.WriteHeadersAsync(headerBuilder, cancellationToken);
if (enable100ContinueBehaviour && Request.ExpectContinue) if (enable100ContinueBehaviour && Request.ExpectContinue)
{ {
...@@ -166,11 +186,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -166,11 +186,8 @@ namespace Titanium.Web.Proxy.Http
string httpStatus; string httpStatus;
try try
{ {
httpStatus = await Connection.Stream.ReadLineAsync(cancellationToken); httpStatus = await Connection.Stream.ReadLineAsync(cancellationToken) ??
if (httpStatus == null) throw new ServerConnectionException("Server connection was closed.");
{
throw new ServerConnectionException("Server connection was closed.");
}
} }
catch (Exception e) when (!(e is ServerConnectionException)) catch (Exception e) when (!(e is ServerConnectionException))
{ {
...@@ -179,7 +196,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -179,7 +196,8 @@ namespace Titanium.Web.Proxy.Http
if (httpStatus == string.Empty) if (httpStatus == string.Empty)
{ {
httpStatus = await Connection.Stream.ReadLineAsync(cancellationToken); httpStatus = await Connection.Stream.ReadLineAsync(cancellationToken) ??
throw new ServerConnectionException("Server connection was closed.");
} }
Response.ParseResponseLine(httpStatus, out var version, out int statusCode, out string statusDescription); Response.ParseResponseLine(httpStatus, out var version, out int statusCode, out string statusDescription);
...@@ -197,7 +215,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -197,7 +215,7 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
internal void FinishSession() internal void FinishSession()
{ {
Connection = null; connection = null;
ConnectRequest?.FinishSession(); ConnectRequest?.FinishSession();
Request?.FinishSession(); Request?.FinishSession();
......
using System.Collections.Generic; using System.Collections.Generic;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
{ {
...@@ -13,7 +13,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -13,7 +13,8 @@ namespace Titanium.Web.Proxy.Http
} }
else else
{ {
value = default; // hack: https://stackoverflow.com/questions/54593923/nullable-reference-types-with-generic-return-type
value = default!;
} }
return result; return result;
...@@ -24,4 +25,4 @@ namespace Titanium.Web.Proxy.Http ...@@ -24,4 +25,4 @@ namespace Titanium.Web.Proxy.Http
return (T)this[key]; return (T)this[key];
} }
} }
} }
\ No newline at end of file
using System;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http
{
public class KnownHeader
{
internal ByteString String8;
public string String;
private KnownHeader(string str)
{
String8 = (ByteString)str;
String = str;
}
public override string ToString()
{
return String;
}
internal bool Equals(ReadOnlySpan<char> value)
{
return String.AsSpan().EqualsIgnoreCase(value);
}
public static implicit operator KnownHeader(string str) => new KnownHeader(str);
}
}
...@@ -6,46 +6,46 @@ ...@@ -6,46 +6,46 @@
public static class KnownHeaders public static class KnownHeaders
{ {
// Both // Both
public const string Connection = "Connection"; public static KnownHeader Connection = "Connection";
public const string ConnectionClose = "close"; public static KnownHeader ConnectionClose = "close";
public const string ConnectionKeepAlive = "keep-alive"; public static KnownHeader ConnectionKeepAlive = "keep-alive";
public const string ContentLength = "Content-Length"; public static KnownHeader ContentLength = "Content-Length";
public const string ContentType = "Content-Type"; public static KnownHeader ContentType = "Content-Type";
public const string ContentTypeCharset = "charset"; public static KnownHeader ContentTypeCharset = "charset";
public const string ContentTypeBoundary = "boundary"; public static KnownHeader ContentTypeBoundary = "boundary";
public const string Upgrade = "Upgrade"; public static KnownHeader Upgrade = "Upgrade";
public const string UpgradeWebsocket = "websocket"; public static KnownHeader UpgradeWebsocket = "websocket";
// Request headers // Request headers
public const string AcceptEncoding = "Accept-Encoding"; public static KnownHeader AcceptEncoding = "Accept-Encoding";
public const string Authorization = "Authorization"; public static KnownHeader Authorization = "Authorization";
public const string Expect = "Expect"; public static KnownHeader Expect = "Expect";
public const string Expect100Continue = "100-continue"; public static KnownHeader Expect100Continue = "100-continue";
public const string Host = "Host"; public static KnownHeader Host = "Host";
public const string ProxyAuthorization = "Proxy-Authorization"; public static KnownHeader ProxyAuthorization = "Proxy-Authorization";
public const string ProxyAuthorizationBasic = "basic"; public static KnownHeader ProxyAuthorizationBasic = "basic";
public const string ProxyConnection = "Proxy-Connection"; public static KnownHeader ProxyConnection = "Proxy-Connection";
public const string ProxyConnectionClose = "close"; public static KnownHeader ProxyConnectionClose = "close";
// Response headers // Response headers
public const string ContentEncoding = "Content-Encoding"; public static KnownHeader ContentEncoding = "Content-Encoding";
public const string ContentEncodingDeflate = "deflate"; public static KnownHeader ContentEncodingDeflate = "deflate";
public const string ContentEncodingGzip = "gzip"; public static KnownHeader ContentEncodingGzip = "gzip";
public const string ContentEncodingBrotli = "br"; public static KnownHeader ContentEncodingBrotli = "br";
public const string Location = "Location"; public static KnownHeader Location = "Location";
public const string ProxyAuthenticate = "Proxy-Authenticate"; public static KnownHeader ProxyAuthenticate = "Proxy-Authenticate";
public const string TransferEncoding = "Transfer-Encoding"; public static KnownHeader TransferEncoding = "Transfer-Encoding";
public const string TransferEncodingChunked = "chunked"; public static KnownHeader TransferEncodingChunked = "chunked";
} }
} }
\ No newline at end of file
...@@ -3,8 +3,8 @@ using System.ComponentModel; ...@@ -3,8 +3,8 @@ using System.ComponentModel;
using System.Text; 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;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
{ {
...@@ -14,40 +14,109 @@ namespace Titanium.Web.Proxy.Http ...@@ -14,40 +14,109 @@ namespace Titanium.Web.Proxy.Http
[TypeConverter(typeof(ExpandableObjectConverter))] [TypeConverter(typeof(ExpandableObjectConverter))]
public class Request : RequestResponseBase public class Request : RequestResponseBase
{ {
private string originalUrl;
/// <summary> /// <summary>
/// Request Method. /// Request Method.
/// </summary> /// </summary>
public string Method { get; set; } public string Method { get; set; }
/// <summary> /// <summary>
/// Request HTTP Uri. /// Is Https?
/// </summary> /// </summary>
public Uri RequestUri { get; set; } public bool IsHttps { get; internal set; }
private ByteString originalUrlData;
private ByteString urlData;
internal ByteString OriginalUrlData
{
get => originalUrlData;
set
{
originalUrlData = value;
UrlData = value;
}
}
private protected ByteString UrlData
{
get => urlData;
set
{
urlData = value;
var scheme = getUriScheme(UrlData);
if (scheme.Length > 0)
{
IsHttps = scheme.Equals(ProxyServer.UriSchemeHttps8);
}
}
}
internal string? Authority { get; set; }
/// <summary> /// <summary>
/// Is Https? /// The original request Url.
/// </summary> /// </summary>
public bool IsHttps => RequestUri.Scheme == ProxyServer.UriSchemeHttps; public string OriginalUrl => originalUrlData.GetString();
/// <summary> /// <summary>
/// The original request Url. /// Request HTTP Uri.
/// </summary> /// </summary>
public string OriginalUrl public Uri RequestUri
{ {
get => originalUrl; get
internal set
{ {
originalUrl = value; string url = UrlData.GetString();
RequestUriString = value; if (getUriScheme(UrlData).Length == 0)
{
string? hostAndPath = Host ?? Authority;
if (url.StartsWith("/"))
{
hostAndPath += url;
}
else
{
//throw new Exception($"Invalid URL: '{url}'");
}
url = string.Concat(IsHttps ? "https://" : "http://", hostAndPath);
}
try
{
return new Uri(url);
}
catch (Exception ex)
{
throw new Exception($"Invalid URI: '{url}'", ex);
}
} }
} }
/// <summary> /// <summary>
/// The request uri as it is in the HTTP header /// The request url as it is in the HTTP header
/// </summary> /// </summary>
public string RequestUriString { get; set; } public string Url
{
get => UrlData.GetString();
set
{
UrlData = value.GetByteString();
if (Host != null)
{
var uri = new Uri(value);
Host = uri.Authority;
}
}
}
[Obsolete("This property is obsolete. Use Url property instead")]
public string RequestUriString
{
get => Url;
set => Url = value;
}
/// <summary> /// <summary>
/// Has request body? /// Has request body?
...@@ -85,7 +154,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -85,7 +154,7 @@ namespace Titanium.Web.Proxy.Http
/// Note: Changing this does NOT change host in RequestUri. /// Note: Changing this does NOT change host in RequestUri.
/// Users can set new RequestUri separately. /// Users can set new RequestUri separately.
/// </summary> /// </summary>
public string Host public string? Host
{ {
get => Headers.GetHeaderValueOrNull(KnownHeaders.Host); get => Headers.GetHeaderValueOrNull(KnownHeaders.Host);
set => Headers.SetOrAddHeaderValue(KnownHeaders.Host, value); set => Headers.SetOrAddHeaderValue(KnownHeaders.Host, value);
...@@ -98,8 +167,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -98,8 +167,8 @@ namespace Titanium.Web.Proxy.Http
{ {
get get
{ {
string headerValue = Headers.GetHeaderValueOrNull(KnownHeaders.Expect); string? headerValue = Headers.GetHeaderValueOrNull(KnownHeaders.Expect);
return headerValue != null && headerValue.Equals(KnownHeaders.Expect100Continue); return KnownHeaders.Expect100Continue.Equals(headerValue);
} }
} }
...@@ -108,11 +177,6 @@ namespace Titanium.Web.Proxy.Http ...@@ -108,11 +177,6 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
public bool IsMultipartFormData => ContentType?.StartsWith("multipart/form-data") == true; public bool IsMultipartFormData => ContentType?.StartsWith("multipart/form-data") == true;
/// <summary>
/// Request Url.
/// </summary>
public string Url => RequestUri.OriginalString;
/// <summary> /// <summary>
/// Cancels the client HTTP request without sending to server. /// Cancels the client HTTP request without sending to server.
/// This should be set when API user responds with custom response. /// This should be set when API user responds with custom response.
...@@ -126,14 +190,14 @@ namespace Titanium.Web.Proxy.Http ...@@ -126,14 +190,14 @@ namespace Titanium.Web.Proxy.Http
{ {
get get
{ {
string headerValue = Headers.GetHeaderValueOrNull(KnownHeaders.Upgrade); string? headerValue = Headers.GetHeaderValueOrNull(KnownHeaders.Upgrade);
if (headerValue == null) if (headerValue == null)
{ {
return false; return false;
} }
return headerValue.EqualsIgnoreCase(KnownHeaders.UpgradeWebsocket); return headerValue.EqualsIgnoreCase(KnownHeaders.UpgradeWebsocket.String);
} }
} }
...@@ -154,15 +218,10 @@ namespace Titanium.Web.Proxy.Http ...@@ -154,15 +218,10 @@ namespace Titanium.Web.Proxy.Http
{ {
get get
{ {
var sb = new StringBuilder(); var headerBuilder = new HeaderBuilder();
sb.Append($"{CreateRequestLine(Method, RequestUriString, HttpVersion)}{ProxyConstants.NewLine}"); headerBuilder.WriteRequestLine(Method, Url, HttpVersion);
foreach (var header in Headers) headerBuilder.WriteHeaders(Headers);
{ return headerBuilder.GetString(HttpHeader.Encoding);
sb.Append($"{header.ToString()}{ProxyConstants.NewLine}");
}
sb.Append(ProxyConstants.NewLine);
return sb.ToString();
} }
} }
...@@ -197,38 +256,41 @@ namespace Titanium.Web.Proxy.Http ...@@ -197,38 +256,41 @@ namespace Titanium.Web.Proxy.Http
} }
} }
internal static string CreateRequestLine(string httpMethod, string httpUrl, Version version)
{
return $"{httpMethod} {httpUrl} HTTP/{version.Major}.{version.Minor}";
}
internal static void ParseRequestLine(string httpCmd, out string httpMethod, out string httpUrl, internal static void ParseRequestLine(string httpCmd, out string httpMethod, out string httpUrl,
out Version version) out Version version)
{ {
// break up the line into three components (method, remote URL & Http Version) int firstSpace = httpCmd.IndexOf(' ');
var httpCmdSplit = httpCmd.Split(ProxyConstants.SpaceSplit, 3); if (firstSpace == -1)
if (httpCmdSplit.Length < 2)
{ {
// does not contain at least 2 parts
throw new Exception("Invalid HTTP request line: " + httpCmd); throw new Exception("Invalid HTTP request line: " + httpCmd);
} }
int lastSpace = httpCmd.LastIndexOf(' ');
// break up the line into three components (method, remote URL & Http Version)
// Find the request Verb // Find the request Verb
httpMethod = httpCmdSplit[0]; httpMethod = httpCmd.Substring(0, firstSpace);
if (!isAllUpper(httpMethod)) if (!isAllUpper(httpMethod))
{ {
httpMethod = httpMethod.ToUpper(); httpMethod = httpMethod.ToUpper();
} }
httpUrl = httpCmdSplit[1];
// parse the HTTP version
version = HttpHeader.Version11; version = HttpHeader.Version11;
if (httpCmdSplit.Length == 3)
if (firstSpace == lastSpace)
{ {
string httpVersion = httpCmdSplit[2].Trim(); httpUrl = httpCmd.AsSpan(firstSpace + 1).ToString();
}
else
{
httpUrl = httpCmd.AsSpan(firstSpace + 1, lastSpace - firstSpace - 1).ToString();
// parse the HTTP version
var httpVersion = httpCmd.AsSpan(lastSpace + 1);
if (httpVersion.EqualsIgnoreCase("HTTP/1.0")) if (httpVersion.EqualsIgnoreCase("HTTP/1.0".AsSpan(0)))
{ {
version = HttpHeader.Version10; version = HttpHeader.Version10;
} }
...@@ -249,5 +311,46 @@ namespace Titanium.Web.Proxy.Http ...@@ -249,5 +311,46 @@ namespace Titanium.Web.Proxy.Http
return true; return true;
} }
private ByteString getUriScheme(ByteString str)
{
if (str.Length < 3)
{
return ByteString.Empty;
}
// regex: "^[a-z]*://"
int i;
for (i = 0; i < str.Length - 3; i++)
{
byte ch = str[i];
if (ch == ':')
{
break;
}
if (ch < 'A' || ch > 'z' || (ch > 'Z' && ch < 'a')) // ASCII letter
{
return ByteString.Empty;
}
}
if (str[i++] != ':')
{
return ByteString.Empty;
}
if (str[i++] != '/')
{
return ByteString.Empty;
}
if (str[i] != '/')
{
return ByteString.Empty;
}
return new ByteString(str.Data.Slice(0, i - 2));
}
} }
} }
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
...@@ -19,12 +18,12 @@ namespace Titanium.Web.Proxy.Http ...@@ -19,12 +18,12 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Cached body content as byte array. /// Cached body content as byte array.
/// </summary> /// </summary>
protected byte[] BodyInternal { get; private set; } protected byte[]? BodyInternal { get; private set; }
/// <summary> /// <summary>
/// Cached body as string. /// Cached body as string.
/// </summary> /// </summary>
private string bodyString; private string? bodyString;
/// <summary> /// <summary>
/// Store whether the original request/response has body or not, since the user may change the parameters. /// Store whether the original request/response has body or not, since the user may change the parameters.
...@@ -48,17 +47,17 @@ namespace Titanium.Web.Proxy.Http ...@@ -48,17 +47,17 @@ namespace Titanium.Web.Proxy.Http
/// Store whether the original request/response content-encoding, since the user may change the parameters. /// Store whether the original request/response content-encoding, since the user may change the parameters.
/// We need this detail to syphon out attached tcp connection for reuse. /// We need this detail to syphon out attached tcp connection for reuse.
/// </summary> /// </summary>
internal string OriginalContentEncoding { get; set; } internal string? OriginalContentEncoding { get; set; }
internal TaskCompletionSource<bool> ReadHttp2BeforeHandlerTaskCompletionSource; internal TaskCompletionSource<bool>? ReadHttp2BeforeHandlerTaskCompletionSource;
internal TaskCompletionSource<bool> ReadHttp2BodyTaskCompletionSource; internal TaskCompletionSource<bool>? ReadHttp2BodyTaskCompletionSource;
internal MemoryStream Http2BodyData; internal MemoryStream? Http2BodyData;
internal bool Http2IgnoreBodyFrames; internal bool Http2IgnoreBodyFrames;
internal Task Http2BeforeHandlerTask; internal Task? Http2BeforeHandlerTask;
/// <summary> /// <summary>
/// Priority used only in HTTP/2 /// Priority used only in HTTP/2
...@@ -87,7 +86,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -87,7 +86,7 @@ namespace Titanium.Web.Proxy.Http
{ {
get get
{ {
string headerValue = Headers.GetHeaderValueOrNull(KnownHeaders.ContentLength); string? headerValue = Headers.GetHeaderValueOrNull(KnownHeaders.ContentLength);
if (headerValue == null) if (headerValue == null)
{ {
...@@ -119,7 +118,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -119,7 +118,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Content encoding for this request/response. /// Content encoding for this request/response.
/// </summary> /// </summary>
public string ContentEncoding => Headers.GetHeaderValueOrNull(KnownHeaders.ContentEncoding)?.Trim(); public string? ContentEncoding => Headers.GetHeaderValueOrNull(KnownHeaders.ContentEncoding)?.Trim();
/// <summary> /// <summary>
/// Encoding for this request/response. /// Encoding for this request/response.
...@@ -129,7 +128,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -129,7 +128,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Content-type of the request/response. /// Content-type of the request/response.
/// </summary> /// </summary>
public string ContentType public string? ContentType
{ {
get => Headers.GetHeaderValueOrNull(KnownHeaders.ContentType); get => Headers.GetHeaderValueOrNull(KnownHeaders.ContentType);
set => Headers.SetOrAddHeaderValue(KnownHeaders.ContentType, value); set => Headers.SetOrAddHeaderValue(KnownHeaders.ContentType, value);
...@@ -142,8 +141,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -142,8 +141,8 @@ namespace Titanium.Web.Proxy.Http
{ {
get get
{ {
string headerValue = Headers.GetHeaderValueOrNull(KnownHeaders.TransferEncoding); string? headerValue = Headers.GetHeaderValueOrNull(KnownHeaders.TransferEncoding);
return headerValue != null && headerValue.ContainsIgnoreCase(KnownHeaders.TransferEncodingChunked); return headerValue != null && headerValue.ContainsIgnoreCase(KnownHeaders.TransferEncodingChunked.String);
} }
set set
...@@ -174,7 +173,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -174,7 +173,7 @@ namespace Titanium.Web.Proxy.Http
get get
{ {
EnsureBodyAvailable(); EnsureBodyAvailable();
return BodyInternal; return BodyInternal!;
} }
internal set internal set
...@@ -220,7 +219,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -220,7 +219,7 @@ namespace Titanium.Web.Proxy.Http
/// <param name="encodingType"></param> /// <param name="encodingType"></param>
/// <param name="body"></param> /// <param name="body"></param>
/// <returns></returns> /// <returns></returns>
internal byte[] GetCompressedBody(string encodingType, byte[] body) internal byte[] GetCompressedBody(HttpCompression encodingType, byte[] body)
{ {
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())
{ {
...@@ -233,7 +232,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -233,7 +232,7 @@ namespace Titanium.Web.Proxy.Http
} }
} }
internal byte[] CompressBodyAndUpdateContentLength() internal byte[]? CompressBodyAndUpdateContentLength()
{ {
if (!IsBodyRead && BodyInternal == null) if (!IsBodyRead && BodyInternal == null)
{ {
...@@ -241,14 +240,14 @@ namespace Titanium.Web.Proxy.Http ...@@ -241,14 +240,14 @@ namespace Titanium.Web.Proxy.Http
} }
bool isChunked = IsChunked; bool isChunked = IsChunked;
string contentEncoding = ContentEncoding; string? contentEncoding = ContentEncoding;
if (HasBody) if (HasBody)
{ {
var body = Body; var body = Body;
if (contentEncoding != null && body != null) if (contentEncoding != null && body != null)
{ {
body = GetCompressedBody(contentEncoding, body); body = GetCompressedBody(CompressionUtil.CompressionNameToEnum(contentEncoding), body);
if (isChunked == false) if (isChunked == false)
{ {
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
using System.ComponentModel; using System.ComponentModel;
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.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
{ {
...@@ -36,7 +36,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -36,7 +36,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Response Status description. /// Response Status description.
/// </summary> /// </summary>
public string StatusDescription { get; set; } public string StatusDescription { get; set; } = string.Empty;
/// <summary> /// <summary>
/// Has response body? /// Has response body?
...@@ -78,11 +78,11 @@ namespace Titanium.Web.Proxy.Http ...@@ -78,11 +78,11 @@ namespace Titanium.Web.Proxy.Http
{ {
get get
{ {
string headerValue = Headers.GetHeaderValueOrNull(KnownHeaders.Connection); string? headerValue = Headers.GetHeaderValueOrNull(KnownHeaders.Connection);
if (headerValue != null) if (headerValue != null)
{ {
if (headerValue.EqualsIgnoreCase(KnownHeaders.ConnectionClose)) if (headerValue.EqualsIgnoreCase(KnownHeaders.ConnectionClose.String))
{ {
return false; return false;
} }
...@@ -99,15 +99,10 @@ namespace Titanium.Web.Proxy.Http ...@@ -99,15 +99,10 @@ namespace Titanium.Web.Proxy.Http
{ {
get get
{ {
var sb = new StringBuilder(); var headerBuilder = new HeaderBuilder();
sb.Append($"{CreateResponseLine(HttpVersion, StatusCode, StatusDescription)}{ProxyConstants.NewLine}"); headerBuilder.WriteResponseLine(HttpVersion, StatusCode, StatusDescription);
foreach (var header in Headers) headerBuilder.WriteHeaders(Headers);
{ return headerBuilder.GetString(HttpHeader.Encoding);
sb.Append($"{header.ToString()}{ProxyConstants.NewLine}");
}
sb.Append(ProxyConstants.NewLine);
return sb.ToString();
} }
} }
...@@ -126,30 +121,41 @@ namespace Titanium.Web.Proxy.Http ...@@ -126,30 +121,41 @@ namespace Titanium.Web.Proxy.Http
} }
} }
internal static string CreateResponseLine(Version version, int statusCode, string statusDescription) internal static void ParseResponseLine(string httpStatus, out Version version, out int statusCode, out string statusDescription)
{
return $"HTTP/{version.Major}.{version.Minor} {statusCode} {statusDescription}";
}
internal static void ParseResponseLine(string httpStatus, out Version version, out int statusCode,
out string statusDescription)
{ {
var httpResult = httpStatus.Split(ProxyConstants.SpaceSplit, 3); int firstSpace = httpStatus.IndexOf(' ');
if (httpResult.Length <= 1) if (firstSpace == -1)
{ {
throw new Exception("Invalid HTTP status line: " + httpStatus); throw new Exception("Invalid HTTP status line: " + httpStatus);
} }
string httpVersion = httpResult[0]; var httpVersion = httpStatus.AsSpan(0, firstSpace);
version = HttpHeader.Version11; version = HttpHeader.Version11;
if (httpVersion.EqualsIgnoreCase("HTTP/1.0")) if (httpVersion.EqualsIgnoreCase("HTTP/1.0".AsSpan()))
{ {
version = HttpHeader.Version10; version = HttpHeader.Version10;
} }
statusCode = int.Parse(httpResult[1]); int secondSpace = httpStatus.IndexOf(' ', firstSpace + 1);
statusDescription = httpResult.Length > 2 ? httpResult[2] : string.Empty; if (secondSpace != -1)
{
#if NETSTANDARD2_1
statusCode = int.Parse(httpStatus.AsSpan(firstSpace + 1, secondSpace - firstSpace - 1));
#else
statusCode = int.Parse(httpStatus.AsSpan(firstSpace + 1, secondSpace - firstSpace - 1).ToString());
#endif
statusDescription = httpStatus.AsSpan(secondSpace + 1).ToString();
}
else
{
#if NETSTANDARD2_1
statusCode = int.Parse(httpStatus.AsSpan(firstSpace + 1));
#else
statusCode = int.Parse(httpStatus.AsSpan(firstSpace + 1).ToString());
#endif
statusDescription = string.Empty;
}
} }
} }
} }
using System.Net; using System.Net;
using System.Web;
namespace Titanium.Web.Proxy.Http.Responses namespace Titanium.Web.Proxy.Http.Responses
{ {
...@@ -15,7 +14,7 @@ namespace Titanium.Web.Proxy.Http.Responses ...@@ -15,7 +14,7 @@ namespace Titanium.Web.Proxy.Http.Responses
public GenericResponse(HttpStatusCode status) public GenericResponse(HttpStatusCode status)
{ {
StatusCode = (int)status; StatusCode = (int)status;
StatusDescription = Get(StatusCode); StatusDescription = Get(StatusCode) ?? string.Empty;
} }
/// <summary> /// <summary>
...@@ -29,7 +28,7 @@ namespace Titanium.Web.Proxy.Http.Responses ...@@ -29,7 +28,7 @@ namespace Titanium.Web.Proxy.Http.Responses
StatusDescription = statusDescription; StatusDescription = statusDescription;
} }
internal static string Get(int code) internal static string? Get(int code)
{ {
switch (code) switch (code)
{ {
...@@ -98,6 +97,7 @@ namespace Titanium.Web.Proxy.Http.Responses ...@@ -98,6 +97,7 @@ namespace Titanium.Web.Proxy.Http.Responses
case 510: return "Not Extended"; case 510: return "Not Extended";
case 511: return "Network Authentication Required"; case 511: return "Network Authentication Required";
} }
return null; return null;
} }
} }
......
...@@ -22,7 +22,7 @@ using Titanium.Web.Proxy.Models; ...@@ -22,7 +22,7 @@ using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http2.Hpack namespace Titanium.Web.Proxy.Http2.Hpack
{ {
public class Decoder internal class Decoder
{ {
private readonly DynamicTable dynamicTable; private readonly DynamicTable dynamicTable;
...@@ -39,7 +39,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -39,7 +39,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
private int skipLength; private int skipLength;
private int nameLength; private int nameLength;
private int valueLength; private int valueLength;
private string name; private ByteString name;
private enum State private enum State
{ {
...@@ -248,7 +248,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -248,7 +248,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
if (indexType == HpackUtil.IndexType.None) if (indexType == HpackUtil.IndexType.None)
{ {
// Name is unused so skip bytes // Name is unused so skip bytes
name = string.Empty; name = ByteString.Empty;
skipLength = nameLength; skipLength = nameLength;
state = State.SkipLiteralHeaderName; state = State.SkipLiteralHeaderName;
break; break;
...@@ -258,7 +258,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -258,7 +258,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
if (nameLength + HttpHeader.HttpHeaderOverhead > dynamicTable.Capacity) if (nameLength + HttpHeader.HttpHeaderOverhead > dynamicTable.Capacity)
{ {
dynamicTable.Clear(); dynamicTable.Clear();
name = string.Empty; name = Array.Empty<byte>();
skipLength = nameLength; skipLength = nameLength;
state = State.SkipLiteralHeaderName; state = State.SkipLiteralHeaderName;
break; break;
...@@ -292,7 +292,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -292,7 +292,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
if (indexType == HpackUtil.IndexType.None) if (indexType == HpackUtil.IndexType.None)
{ {
// Name is unused so skip bytes // Name is unused so skip bytes
name = string.Empty; name = ByteString.Empty;
skipLength = nameLength; skipLength = nameLength;
state = State.SkipLiteralHeaderName; state = State.SkipLiteralHeaderName;
break; break;
...@@ -302,7 +302,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -302,7 +302,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
if (nameLength + HttpHeader.HttpHeaderOverhead > dynamicTable.Capacity) if (nameLength + HttpHeader.HttpHeaderOverhead > dynamicTable.Capacity)
{ {
dynamicTable.Clear(); dynamicTable.Clear();
name = string.Empty; name = ByteString.Empty;
skipLength = nameLength; skipLength = nameLength;
state = State.SkipLiteralHeaderName; state = State.SkipLiteralHeaderName;
break; break;
...@@ -375,7 +375,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -375,7 +375,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
if (valueLength == 0) if (valueLength == 0)
{ {
InsertHeader(headerListener, name, string.Empty, indexType); InsertHeader(headerListener, name, Array.Empty<byte>(), indexType);
state = State.ReadHeaderRepresentation; state = State.ReadHeaderRepresentation;
} }
else else
...@@ -519,29 +519,28 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -519,29 +519,28 @@ namespace Titanium.Web.Proxy.Http2.Hpack
var headerField = StaticTable.Get(index); var headerField = StaticTable.Get(index);
return headerField; return headerField;
} }
else if (index - StaticTable.Length <= dynamicTable.Length())
if (index - StaticTable.Length <= dynamicTable.Length())
{ {
var headerField = dynamicTable.GetEntry(index - StaticTable.Length); var headerField = dynamicTable.GetEntry(index - StaticTable.Length);
return headerField; return headerField;
} }
else
{ throw new IOException("illegal index value (" + index + ")");
throw new IOException("illegal index value (" + index + ")");
}
} }
private void ReadName(int index) private void ReadName(int index)
{ {
name = GetHeaderField(index).Name; name = GetHeaderField(index).NameData;
} }
private void IndexHeader(int index, IHeaderListener headerListener) private void IndexHeader(int index, IHeaderListener headerListener)
{ {
var headerField = GetHeaderField(index); var headerField = GetHeaderField(index);
AddHeader(headerListener, headerField.Name, headerField.Value, false); AddHeader(headerListener, headerField.NameData, headerField.ValueData, false);
} }
private void InsertHeader(IHeaderListener headerListener, string name, string value, HpackUtil.IndexType indexType) private void InsertHeader(IHeaderListener headerListener, ByteString name, ByteString value, HpackUtil.IndexType indexType)
{ {
AddHeader(headerListener, name, value, indexType == HpackUtil.IndexType.Never); AddHeader(headerListener, name, value, indexType == HpackUtil.IndexType.Never);
...@@ -560,7 +559,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -560,7 +559,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
} }
} }
private void AddHeader(IHeaderListener headerListener, string name, string value, bool sensitive) private void AddHeader(IHeaderListener headerListener, ByteString name, ByteString value, bool sensitive)
{ {
if (name.Length == 0) if (name.Length == 0)
{ {
...@@ -593,7 +592,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -593,7 +592,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
return true; return true;
} }
private string ReadStringLiteral(BinaryReader input, int length) private ByteString ReadStringLiteral(BinaryReader input, int length)
{ {
var buf = new byte[length]; var buf = new byte[length];
int lengthToRead = length; int lengthToRead = length;
...@@ -608,7 +607,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -608,7 +607,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
throw new IOException("decompression failure"); throw new IOException("decompression failure");
} }
return huffmanEncoded ? HuffmanDecoder.Instance.Decode(buf) : Encoding.UTF8.GetString(buf); return new ByteString(huffmanEncoded ? HuffmanDecoder.Instance.Decode(buf) : buf);
} }
// Unsigned Little Endian Base 128 Variable-Length Integer Encoding // Unsigned Little Endian Base 128 Variable-Length Integer Encoding
......
...@@ -23,7 +23,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -23,7 +23,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
public class DynamicTable public class DynamicTable
{ {
// a circular queue of header fields // a circular queue of header fields
HttpHeader[] headerFields; HttpHeader[] headerFields = Array.Empty<HttpHeader>();
int head; int head;
int tail; int tail;
...@@ -89,10 +89,10 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -89,10 +89,10 @@ namespace Titanium.Web.Proxy.Http2.Hpack
int i = head - index; int i = head - index;
if (i < 0) if (i < 0)
{ {
return headerFields[i + headerFields.Length]; return headerFields[i + headerFields.Length]!;
} }
return headerFields[i]; return headerFields[i]!;
} }
/// <summary> /// <summary>
...@@ -128,7 +128,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -128,7 +128,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <summary> /// <summary>
/// Remove and return the oldest header field from the dynamic table. /// Remove and return the oldest header field from the dynamic table.
/// </summary> /// </summary>
public HttpHeader Remove() public HttpHeader? Remove()
{ {
var removed = headerFields[tail]; var removed = headerFields[tail];
if (removed == null) if (removed == null)
...@@ -218,8 +218,8 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -218,8 +218,8 @@ namespace Titanium.Web.Proxy.Http2.Hpack
int cursor = tail; int cursor = tail;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
var entry = headerFields[cursor++]; var entry = headerFields![cursor++];
tmp[i] = entry; tmp[i] = entry!;
if (cursor == headerFields.Length) if (cursor == headerFields.Length)
{ {
cursor = 0; cursor = 0;
......
/* 
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
* *
...@@ -14,7 +18,6 @@ ...@@ -14,7 +18,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
using System; using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
...@@ -22,13 +25,13 @@ using Titanium.Web.Proxy.Models; ...@@ -22,13 +25,13 @@ using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http2.Hpack namespace Titanium.Web.Proxy.Http2.Hpack
{ {
public class Encoder internal class Encoder
{ {
private const int bucketSize = 17; private const int bucketSize = 17;
// a linked hash map of header fields // a linked hash map of header fields
private readonly HeaderEntry[] headerFields = new HeaderEntry[bucketSize]; private readonly HeaderEntry[] headerFields = new HeaderEntry[bucketSize];
private readonly HeaderEntry head = new HeaderEntry(-1, string.Empty, string.Empty, int.MaxValue, null); private readonly HeaderEntry head = new HeaderEntry(-1, ByteString.Empty, ByteString.Empty, int.MaxValue, null);
private int size; private int size;
/// <summary> /// <summary>
...@@ -63,7 +66,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -63,7 +66,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <param name="sensitive">If set to <c>true</c> sensitive.</param> /// <param name="sensitive">If set to <c>true</c> sensitive.</param>
/// <param name="indexType">Index type.</param> /// <param name="indexType">Index type.</param>
/// <param name="useStaticName">Use static name.</param> /// <param name="useStaticName">Use static name.</param>
public void EncodeHeader(BinaryWriter output, string name, string value, bool sensitive = false, HpackUtil.IndexType indexType = HpackUtil.IndexType.Incremental, bool useStaticName = true) public void EncodeHeader(BinaryWriter output, ByteString name, ByteString value, bool sensitive = false, HpackUtil.IndexType indexType = HpackUtil.IndexType.Incremental, bool useStaticName = true)
{ {
// If the header value is sensitive then it must never be indexed // If the header value is sensitive then it must never be indexed
if (sensitive) if (sensitive)
...@@ -190,12 +193,11 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -190,12 +193,11 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// Encode string literal according to Section 5.2. /// Encode string literal according to Section 5.2.
/// </summary> /// </summary>
/// <param name="output">Output.</param> /// <param name="output">Output.</param>
/// <param name="stringLiteral">String literal.</param> /// <param name="stringData">String data.</param>
private void encodeStringLiteral(BinaryWriter output, string stringLiteral) private void encodeStringLiteral(BinaryWriter output, ByteString stringData)
{ {
var stringData = Encoding.UTF8.GetBytes(stringLiteral);
int huffmanLength = HuffmanEncoder.Instance.GetEncodedLength(stringData); int huffmanLength = HuffmanEncoder.Instance.GetEncodedLength(stringData);
if (huffmanLength < stringLiteral.Length) if (huffmanLength < stringData.Length)
{ {
encodeInteger(output, 0x80, 7, huffmanLength); encodeInteger(output, 0x80, 7, huffmanLength);
HuffmanEncoder.Instance.Encode(output, stringData); HuffmanEncoder.Instance.Encode(output, stringData);
...@@ -203,7 +205,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -203,7 +205,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
else else
{ {
encodeInteger(output, 0x00, 7, stringData.Length); encodeInteger(output, 0x00, 7, stringData.Length);
output.Write(stringData, 0, stringData.Length); output.Write(stringData.Span);
} }
} }
...@@ -215,7 +217,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -215,7 +217,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <param name="value">Value.</param> /// <param name="value">Value.</param>
/// <param name="indexType">Index type.</param> /// <param name="indexType">Index type.</param>
/// <param name="nameIndex">Name index.</param> /// <param name="nameIndex">Name index.</param>
private void encodeLiteral(BinaryWriter output, string name, string value, HpackUtil.IndexType indexType, private void encodeLiteral(BinaryWriter output, ByteString name, ByteString value, HpackUtil.IndexType indexType,
int nameIndex) int nameIndex)
{ {
int mask; int mask;
...@@ -250,7 +252,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -250,7 +252,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
encodeStringLiteral(output, value); encodeStringLiteral(output, value);
} }
private int getNameIndex(string name) private int getNameIndex(ByteString name)
{ {
int index = StaticTable.GetIndex(name); int index = StaticTable.GetIndex(name);
if (index == -1) if (index == -1)
...@@ -299,9 +301,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -299,9 +301,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <returns>The entry.</returns> /// <returns>The entry.</returns>
/// <param name="name">Name.</param> /// <param name="name">Name.</param>
/// <param name="value">Value.</param> /// <param name="value">Value.</param>
private HeaderEntry getEntry(string name, string value) private HeaderEntry? getEntry(ByteString name, ByteString value)
{ {
if (length() == 0 || name == null || value == null) if (length() == 0 || name.Length == 0 || value.Length == 0)
{ {
return null; return null;
} }
...@@ -310,7 +312,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -310,7 +312,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
int i = index(h); int i = index(h);
for (var e = headerFields[i]; e != null; e = e.Next) for (var e = headerFields[i]; e != null; e = e.Next)
{ {
if (e.Hash == h && name.Equals(e.Name, StringComparison.OrdinalIgnoreCase) && Equals(value, e.Value)) if (e.Hash == h && name.Equals(e.NameData) && Equals(value, e.ValueData))
{ {
return e; return e;
} }
...@@ -325,9 +327,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -325,9 +327,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// </summary> /// </summary>
/// <returns>The index.</returns> /// <returns>The index.</returns>
/// <param name="name">Name.</param> /// <param name="name">Name.</param>
private int getIndex(string name) private int getIndex(ByteString name)
{ {
if (length() == 0 || name == null) if (length() == 0 || name.Length == 0)
{ {
return -1; return -1;
} }
...@@ -335,9 +337,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -335,9 +337,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack
int h = hash(name); int h = hash(name);
int i = Encoder.index(h); int i = Encoder.index(h);
int index = -1; int index = -1;
for (var e = headerFields[i]; e != null; e = e.Next) for (HeaderEntry? e = headerFields[i]; e != null; e = e.Next)
{ {
if (e.Hash == h && name.Equals(e.Name, StringComparison.OrdinalIgnoreCase)) if (e.Hash == h && name.Equals(e.NameData))
{ {
index = e.Index; index = e.Index;
break; break;
...@@ -371,7 +373,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -371,7 +373,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// </summary> /// </summary>
/// <param name="name">Name.</param> /// <param name="name">Name.</param>
/// <param name="value">Value.</param> /// <param name="value">Value.</param>
private void add(string name, string value) private void add(ByteString name, ByteString value)
{ {
int headerSize = HttpHeader.SizeOf(name, value); int headerSize = HttpHeader.SizeOf(name, value);
...@@ -400,7 +402,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -400,7 +402,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <summary> /// <summary>
/// Remove and return the oldest header field from the dynamic table. /// Remove and return the oldest header field from the dynamic table.
/// </summary> /// </summary>
private HttpHeader remove() private HttpHeader? remove()
{ {
if (size == 0) if (size == 0)
{ {
...@@ -423,7 +425,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -423,7 +425,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
} }
else else
{ {
prev.Next = next; prev!.Next = next;
} }
eldest.Remove(); eldest.Remove();
...@@ -457,12 +459,12 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -457,12 +459,12 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// </summary> /// </summary>
/// <returns><c>true</c> if hash name; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if hash name; otherwise, <c>false</c>.</returns>
/// <param name="name">Name.</param> /// <param name="name">Name.</param>
private static int hash(string name) private static int hash(ByteString name)
{ {
int h = 0; int h = 0;
for (int i = 0; i < name.Length; i++) for (int i = 0; i < name.Length; i++)
{ {
h = 31 * h + name[i]; h = 31 * h + name.Span[i];
} }
if (h > 0) if (h > 0)
...@@ -500,7 +502,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -500,7 +502,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
public HeaderEntry After { get; set; } public HeaderEntry After { get; set; }
// These fields comprise the chained list for header fields with the same hash. // These fields comprise the chained list for header fields with the same hash.
public HeaderEntry Next { get; set; } public HeaderEntry? Next { get; set; }
public int Hash { get; } public int Hash { get; }
...@@ -514,11 +516,13 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -514,11 +516,13 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <param name="value">Value.</param> /// <param name="value">Value.</param>
/// <param name="index">Index.</param> /// <param name="index">Index.</param>
/// <param name="next">Next.</param> /// <param name="next">Next.</param>
public HeaderEntry(int hash, string name, string value, int index, HeaderEntry next) : base(name, value, true) public HeaderEntry(int hash, ByteString name, ByteString value, int index, HeaderEntry? next) : base(name, value, true)
{ {
Index = index; Index = index;
Hash = hash; Hash = hash;
Next = next; Next = next;
Before = this;
After = this;
} }
/// <summary> /// <summary>
...@@ -544,3 +548,4 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -544,3 +548,4 @@ namespace Titanium.Web.Proxy.Http2.Hpack
} }
} }
} }
#endif
...@@ -54,7 +54,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -54,7 +54,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <param name="buf">the string literal to be decoded</param> /// <param name="buf">the string literal to be decoded</param>
/// <returns>the output stream for the compressed data</returns> /// <returns>the output stream for the compressed data</returns>
/// <exception cref="IOException">throws IOException if an I/O error occurs. In particular, an <code>IOException</code> may be thrown if the output stream has been closed.</exception> /// <exception cref="IOException">throws IOException if an I/O error occurs. In particular, an <code>IOException</code> may be thrown if the output stream has been closed.</exception>
public string Decode(byte[] buf) public ReadOnlyMemory<byte> Decode(byte[] buf)
{ {
var resultBuf = new byte[buf.Length * 2]; var resultBuf = new byte[buf.Length * 2];
int resultSize = 0; int resultSize = 0;
...@@ -69,7 +69,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -69,7 +69,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
while (bits >= 8) while (bits >= 8)
{ {
int c = (current >> (bits - 8)) & 0xFF; int c = (current >> (bits - 8)) & 0xFF;
node = node.Children[c]; node = node.Children![c];
bits -= node.Bits; bits -= node.Bits;
if (node.IsTerminal) if (node.IsTerminal)
{ {
...@@ -87,7 +87,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -87,7 +87,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
while (bits > 0) while (bits > 0)
{ {
int c = (current << (8 - bits)) & 0xFF; int c = (current << (8 - bits)) & 0xFF;
node = node.Children[c]; node = node.Children![c];
if (node.IsTerminal && node.Bits <= bits) if (node.IsTerminal && node.Bits <= bits)
{ {
bits -= node.Bits; bits -= node.Bits;
...@@ -109,7 +109,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -109,7 +109,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
throw new IOException("Invalid Padding"); throw new IOException("Invalid Padding");
} }
return Encoding.UTF8.GetString(resultBuf, 0, resultSize); return resultBuf.AsMemory(0, resultSize);
} }
private class Node private class Node
...@@ -121,7 +121,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -121,7 +121,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
public int Bits { get; } public int Bits { get; }
// internal nodes have children // internal nodes have children
public Node[] Children { get; } public Node[]? Children { get; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="HuffmanDecoder"/> class. /// Initializes a new instance of the <see cref="HuffmanDecoder"/> class.
...@@ -173,7 +173,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -173,7 +173,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
length -= 8; length -= 8;
int i = (code >> length) & 0xFF; int i = (code >> length) & 0xFF;
if (current.Children[i] == null) if (current.Children![i] == null)
{ {
current.Children[i] = new Node(); current.Children[i] = new Node();
} }
...@@ -187,7 +187,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -187,7 +187,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
int end = 1 << shift; int end = 1 << shift;
for (int i = start; i < start + end; i++) for (int i = start; i < start + end; i++)
{ {
current.Children[i] = terminal; current.Children![i] = terminal;
} }
} }
} }
......
...@@ -17,10 +17,11 @@ ...@@ -17,10 +17,11 @@
using System; using System;
using System.IO; using System.IO;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http2.Hpack namespace Titanium.Web.Proxy.Http2.Hpack
{ {
public class HuffmanEncoder internal class HuffmanEncoder
{ {
/// <summary> /// <summary>
/// Huffman Encoder /// Huffman Encoder
...@@ -42,39 +43,15 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -42,39 +43,15 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// </summary> /// </summary>
/// <param name="output">the output stream for the compressed data</param> /// <param name="output">the output stream for the compressed data</param>
/// <param name="data">the string literal to be Huffman encoded</param> /// <param name="data">the string literal to be Huffman encoded</param>
/// <exception cref="IOException">if an I/O error occurs.</exception>
/// <see cref="Encode(BinaryWriter,byte[],int,int)"/>
public void Encode(BinaryWriter output, byte[] data)
{
Encode(output, data, 0, data.Length);
}
/// <summary>
/// Compresses the input string literal using the Huffman coding.
/// </summary>
/// <param name="output">the output stream for the compressed data</param>
/// <param name="data">the string literal to be Huffman encoded</param>
/// <param name="off">the start offset in the data</param>
/// <param name="len">the number of bytes to encode</param>
/// <exception cref="IOException">if an I/O error occurs. In particular, an <code>IOException</code> may be thrown if the output stream has been closed.</exception> /// <exception cref="IOException">if an I/O error occurs. In particular, an <code>IOException</code> may be thrown if the output stream has been closed.</exception>
public void Encode(BinaryWriter output, byte[] data, int off, int len) public void Encode(BinaryWriter output, ByteString data)
{ {
if (output == null) if (output == null)
{ {
throw new ArgumentNullException(nameof(output)); throw new ArgumentNullException(nameof(output));
} }
if (data == null) if (data.Length == 0)
{
throw new ArgumentNullException(nameof(data));
}
if (off < 0 || len < 0 || (off + len) < 0 || off > data.Length || (off + len) > data.Length)
{
throw new IndexOutOfRangeException();
}
if (len == 0)
{ {
return; return;
} }
...@@ -82,9 +59,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -82,9 +59,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack
long current = 0L; long current = 0L;
int n = 0; int n = 0;
for (int i = 0; i < len; i++) for (int i = 0; i < data.Length; i++)
{ {
int b = data[off + i] & 0xFF; int b = data.Span[i] & 0xFF;
uint code = (uint)codes[b]; uint code = (uint)codes[b];
int nbits = lengths[b]; int nbits = lengths[b];
...@@ -112,15 +89,10 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -112,15 +89,10 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// </summary> /// </summary>
/// <returns>the number of bytes required to Huffman encode <code>data</code></returns> /// <returns>the number of bytes required to Huffman encode <code>data</code></returns>
/// <param name="data">the string literal to be Huffman encoded</param> /// <param name="data">the string literal to be Huffman encoded</param>
public int GetEncodedLength(byte[] data) public int GetEncodedLength(ByteString data)
{ {
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
long len = 0L; long len = 0L;
foreach (byte b in data) foreach (byte b in data.Span)
{ {
len += lengths[b]; len += lengths[b];
} }
......
...@@ -14,9 +14,13 @@ ...@@ -14,9 +14,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
using System;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Http2.Hpack namespace Titanium.Web.Proxy.Http2.Hpack
{ {
public interface IHeaderListener internal interface IHeaderListener
{ {
/// <summary> /// <summary>
/// EmitHeader is called by the decoder during header field emission. /// EmitHeader is called by the decoder during header field emission.
...@@ -25,6 +29,6 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -25,6 +29,6 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <param name="name">Name.</param> /// <param name="name">Name.</param>
/// <param name="value">Value.</param> /// <param name="value">Value.</param>
/// <param name="sensitive">If set to <c>true</c> sensitive.</param> /// <param name="sensitive">If set to <c>true</c> sensitive.</param>
void AddHeader(string name, string value, bool sensitive); void AddHeader(ByteString name, ByteString value, bool sensitive);
} }
} }
...@@ -18,149 +18,104 @@ ...@@ -18,149 +18,104 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; 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
{ {
public static class StaticTable internal static class StaticTable
{ {
/// <summary> /// <summary>
/// Appendix A: Static Table Definition /// Appendix A: Static Table Definition
/// </summary> /// </summary>
/// <see cref="http://tools.ietf.org/html/rfc7541#appendix-A"/> /// <see cref="http://tools.ietf.org/html/rfc7541#appendix-A"/>
private static readonly List<HttpHeader> staticTable = new List<HttpHeader>() private static readonly List<HttpHeader> staticTable;
private static readonly Dictionary<ByteString, int> staticIndexByName;
public static ByteString KnownHeaderAuhtority = (ByteString)":authority";
public static ByteString KnownHeaderMethod = (ByteString)":method";
public static ByteString KnownHeaderPath = (ByteString)":path";
public static ByteString KnownHeaderScheme = (ByteString)":scheme";
public static ByteString KnownHeaderStatus = (ByteString)":status";
static StaticTable()
{ {
/* 1 */ const int entryCount = 61;
new HttpHeader(":authority", string.Empty), staticTable = new List<HttpHeader>(entryCount);
/* 2 */ staticIndexByName = new Dictionary<ByteString, int>(entryCount);
new HttpHeader(":method", "GET"), create(KnownHeaderAuhtority, string.Empty); // 1
/* 3 */ create(KnownHeaderMethod, "GET"); // 2
new HttpHeader(":method", "POST"), create(KnownHeaderMethod, "POST"); // 3
/* 4 */ create(KnownHeaderPath, "/"); // 4
new HttpHeader(":path", "/"), create(KnownHeaderPath, "/index.html"); // 5
/* 5 */ create(KnownHeaderScheme, "http"); // 6
new HttpHeader(":path", "/index.html"), create(KnownHeaderScheme, "https"); // 7
/* 6 */ create(KnownHeaderStatus, "200"); // 8
new HttpHeader(":scheme", "http"), create(KnownHeaderStatus, "204"); // 9
/* 7 */ create(KnownHeaderStatus, "206"); // 10
new HttpHeader(":scheme", "https"), create(KnownHeaderStatus, "304"); // 11
/* 8 */ create(KnownHeaderStatus, "400"); // 12
new HttpHeader(":status", "200"), create(KnownHeaderStatus, "404"); // 13
/* 9 */ create(KnownHeaderStatus, "500"); // 14
new HttpHeader(":status", "204"), create("Accept-Charset", string.Empty); // 15
/* 10 */ create("Accept-Encoding", "gzip, deflate"); // 16
new HttpHeader(":status", "206"), create("Accept-Language", string.Empty); // 17
/* 11 */ create("Accept-Ranges", string.Empty); // 18
new HttpHeader(":status", "304"), create("Accept", string.Empty); // 19
/* 12 */ create("Access-Control-Allow-Origin", string.Empty); // 20
new HttpHeader(":status", "400"), create("Age", string.Empty); // 21
/* 13 */ create("Allow", string.Empty); // 22
new HttpHeader(":status", "404"), create("Authorization", string.Empty); // 23
/* 14 */ create("Cache-Control", string.Empty); // 24
new HttpHeader(":status", "500"), create("Content-Disposition", string.Empty); // 25
/* 15 */ create("Content-Encoding", string.Empty); // 26
new HttpHeader("Accept-Charset", string.Empty), create("Content-Language", string.Empty); // 27
/* 16 */ create("Content-Length", string.Empty); // 28
new HttpHeader("Accept-Encoding", "gzip, deflate"), create("Content-Location", string.Empty); // 29
/* 17 */ create("Content-Range", string.Empty); // 30
new HttpHeader("Accept-Language", string.Empty), create("Content-Type", string.Empty); // 31
/* 18 */ create("Cookie", string.Empty); // 32
new HttpHeader("Accept-Ranges", string.Empty), create("Date", string.Empty); // 33
/* 19 */ create("ETag", string.Empty); // 34
new HttpHeader("Accept", string.Empty), create("Expect", string.Empty); // 35
/* 20 */ create("Expires", string.Empty); // 36
new HttpHeader("Access-Control-Allow-Origin", string.Empty), create("From", string.Empty); // 37
/* 21 */ create("Host", string.Empty); // 38
new HttpHeader("Age", string.Empty), create("If-Match", string.Empty); // 39
/* 22 */ create("If-Modified-Since", string.Empty); // 40
new HttpHeader("Allow", string.Empty), create("If-None-Match", string.Empty); // 41
/* 23 */ create("If-Range", string.Empty); // 42
new HttpHeader("Authorization", string.Empty), create("If-Unmodified-Since", string.Empty); // 43
/* 24 */ create("Last-Modified", string.Empty); // 44
new HttpHeader("Cache-Control", string.Empty), create("Link", string.Empty); // 45
/* 25 */ create("Location", string.Empty); // 46
new HttpHeader("Content-Disposition", string.Empty), create("Max-Forwards", string.Empty); // 47
/* 26 */ create("Proxy-Authenticate", string.Empty); // 48
new HttpHeader("Content-Encoding", string.Empty), create("Proxy-Authorization", string.Empty); // 49
/* 27 */ create("Range", string.Empty); // 50
new HttpHeader("Content-Language", string.Empty), create("Referer", string.Empty); // 51
/* 28 */ create("Refresh", string.Empty); // 52
new HttpHeader("Content-Length", string.Empty), create("Retry-After", string.Empty); // 53
/* 29 */ create("Server", string.Empty); // 54
new HttpHeader("Content-Location", string.Empty), create("Set-Cookie", string.Empty); // 55
/* 30 */ create("Strict-Transport-Security", string.Empty); // 56
new HttpHeader("Content-Range", string.Empty), create("Transfer-Encoding", string.Empty); // 57
/* 31 */ create("User-Agent", string.Empty); // 58
new HttpHeader("Content-Type", string.Empty), create("Vary", string.Empty); // 59
/* 32 */ create("Via", string.Empty); // 60
new HttpHeader("Cookie", string.Empty), create("WWW-Authenticate", string.Empty); // 61
/* 33 */ }
new HttpHeader("Date", string.Empty),
/* 34 */
new HttpHeader("ETag", string.Empty),
/* 35 */
new HttpHeader("Expect", string.Empty),
/* 36 */
new HttpHeader("Expires", string.Empty),
/* 37 */
new HttpHeader("From", string.Empty),
/* 38 */
new HttpHeader("Host", string.Empty),
/* 39 */
new HttpHeader("If-Match", string.Empty),
/* 40 */
new HttpHeader("If-Modified-Since", string.Empty),
/* 41 */
new HttpHeader("If-None-Match", string.Empty),
/* 42 */
new HttpHeader("If-Range", string.Empty),
/* 43 */
new HttpHeader("If-Unmodified-Since", string.Empty),
/* 44 */
new HttpHeader("Last-Modified", string.Empty),
/* 45 */
new HttpHeader("Link", string.Empty),
/* 46 */
new HttpHeader("Location", string.Empty),
/* 47 */
new HttpHeader("Max-Forwards", string.Empty),
/* 48 */
new HttpHeader("Proxy-Authenticate", string.Empty),
/* 49 */
new HttpHeader("Proxy-Authorization", string.Empty),
/* 50 */
new HttpHeader("Range", string.Empty),
/* 51 */
new HttpHeader("Referer", string.Empty),
/* 52 */
new HttpHeader("Refresh", string.Empty),
/* 53 */
new HttpHeader("Retry-After", string.Empty),
/* 54 */
new HttpHeader("Server", string.Empty),
/* 55 */
new HttpHeader("Set-Cookie", string.Empty),
/* 56 */
new HttpHeader("Strict-Transport-Security", string.Empty),
/* 57 */
new HttpHeader("Transfer-Encoding", string.Empty),
/* 58 */
new HttpHeader("User-Agent", string.Empty),
/* 59 */
new HttpHeader("Vary", string.Empty),
/* 60 */
new HttpHeader("Via", string.Empty),
/* 61 */
new HttpHeader("WWW-Authenticate", string.Empty)
};
private static readonly Dictionary<string, int> staticIndexByName = createMap();
/// <summary> /// <summary>
/// The number of header fields in the static table. /// The number of header fields in the static table.
/// </summary> /// </summary>
/// <value>The length.</value> /// <value>The length.</value>
public static int Length => staticTable.Count; public static int Length => staticTable.Count;
/// <summary> /// <summary>
/// Return the http header field at the given index value. /// Return the http header field at the given index value.
...@@ -178,7 +133,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -178,7 +133,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// </summary> /// </summary>
/// <returns>The index.</returns> /// <returns>The index.</returns>
/// <param name="name">Name.</param> /// <param name="name">Name.</param>
public static int GetIndex(string name) public static int GetIndex(ByteString name)
{ {
if (!staticIndexByName.TryGetValue(name, out int index)) if (!staticIndexByName.TryGetValue(name, out int index))
{ {
...@@ -195,7 +150,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -195,7 +150,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <returns>The index.</returns> /// <returns>The index.</returns>
/// <param name="name">Name.</param> /// <param name="name">Name.</param>
/// <param name="value">Value.</param> /// <param name="value">Value.</param>
public static int GetIndex(string name, string value) public static int GetIndex(ByteString name, ByteString value)
{ {
int index = GetIndex(name); int index = GetIndex(name);
if (index == -1) if (index == -1)
...@@ -207,12 +162,12 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -207,12 +162,12 @@ namespace Titanium.Web.Proxy.Http2.Hpack
while (index <= Length) while (index <= Length)
{ {
var entry = Get(index); var entry = Get(index);
if (!name.Equals(entry.Name, StringComparison.OrdinalIgnoreCase)) if (!name.Equals(entry.NameData))
{ {
break; break;
} }
if (HpackUtil.Equals(value, entry.Value)) if (Equals(value, entry.Value))
{ {
return index; return index;
} }
...@@ -223,25 +178,15 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -223,25 +178,15 @@ namespace Titanium.Web.Proxy.Http2.Hpack
return -1; return -1;
} }
/// <summary> private static void create(string name, string value)
/// create a map of header name to index value to allow quick lookup
/// </summary>
/// <returns>The map.</returns>
private static Dictionary<string, int> createMap()
{ {
int length = staticTable.Count; create((ByteString)name.ToLower(), value);
var ret = new Dictionary<string, int>(length); }
// Iterate through the static table in reverse order to
// save the smallest index for a given name in the map.
for (int index = length; index > 0; index--)
{
var entry = Get(index);
string name = entry.Name.ToLower();
ret[name] = index;
}
return ret; private static void create(ByteString name, string value)
{
staticTable.Add(new HttpHeader(name, (ByteString)value));
staticIndexByName[name] = staticTable.Count;
} }
} }
} }
...@@ -10,12 +10,9 @@ ...@@ -10,12 +10,9 @@
public int StreamId; public int StreamId;
public byte[] Buffer; public void CopyToBuffer(byte[] buf)
public byte[] CopyToBuffer()
{ {
int length = Length; int length = Length;
var buf = /*new byte[9];*/Buffer;
buf[0] = (byte)((length >> 16) & 0xff); buf[0] = (byte)((length >> 16) & 0xff);
buf[1] = (byte)((length >> 8) & 0xff); buf[1] = (byte)((length >> 8) & 0xff);
buf[2] = (byte)(length & 0xff); buf[2] = (byte)(length & 0xff);
...@@ -26,7 +23,6 @@ ...@@ -26,7 +23,6 @@
//buf[6] = (byte)((streamId >> 16) & 0xff); //buf[6] = (byte)((streamId >> 16) & 0xff);
//buf[7] = (byte)((streamId >> 8) & 0xff); //buf[7] = (byte)((streamId >> 8) & 0xff);
//buf[8] = (byte)(streamId & 0xff); //buf[8] = (byte)(streamId & 0xff);
return buf;
} }
} }
} }
#if NETCOREAPP2_1 
using Titanium.Web.Proxy.Extensions;
#if NETSTANDARD2_1
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; 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.Compression; using Titanium.Web.Proxy.Compression;
...@@ -12,11 +15,16 @@ using Titanium.Web.Proxy.EventArguments; ...@@ -12,11 +15,16 @@ using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions; using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http2.Hpack; using Titanium.Web.Proxy.Http2.Hpack;
using Titanium.Web.Proxy.Models;
using Decoder = Titanium.Web.Proxy.Http2.Hpack.Decoder;
using Encoder = Titanium.Web.Proxy.Http2.Hpack.Encoder;
namespace Titanium.Web.Proxy.Http2 namespace Titanium.Web.Proxy.Http2
{ {
internal class Http2Helper internal class Http2Helper
{ {
public static readonly byte[] ConnectionPreface = Encoding.ASCII.GetBytes("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n");
/// <summary> /// <summary>
/// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers
/// as prefix /// as prefix
...@@ -24,8 +32,7 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -24,8 +32,7 @@ namespace Titanium.Web.Proxy.Http2
/// Task-based Asynchronous Pattern /// Task-based Asynchronous Pattern
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
internal static async Task SendHttp2(Stream clientStream, Stream serverStream, int bufferSize, internal static async Task SendHttp2(Stream clientStream, Stream serverStream,
Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive,
Func<SessionEventArgs> sessionFactory, Func<SessionEventArgs> sessionFactory,
Func<SessionEventArgs, Task> onBeforeRequest, Func<SessionEventArgs, Task> onBeforeResponse, Func<SessionEventArgs, Task> onBeforeRequest, Func<SessionEventArgs, Task> onBeforeResponse,
CancellationTokenSource cancellationTokenSource, Guid connectionId, CancellationTokenSource cancellationTokenSource, Guid connectionId,
...@@ -38,13 +45,13 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -38,13 +45,13 @@ namespace Titanium.Web.Proxy.Http2
// Now async relay all server=>client & client=>server data // Now async relay all server=>client & client=>server data
var sendRelay = var sendRelay =
copyHttp2FrameAsync(clientStream, serverStream, onDataSend, clientSettings, serverSettings, copyHttp2FrameAsync(clientStream, serverStream, clientSettings, serverSettings,
sessionFactory, sessions, onBeforeRequest, sessionFactory, sessions, onBeforeRequest,
bufferSize, connectionId, true, cancellationTokenSource.Token, exceptionFunc); connectionId, true, cancellationTokenSource.Token, exceptionFunc);
var receiveRelay = var receiveRelay =
copyHttp2FrameAsync(serverStream, clientStream, onDataReceive, serverSettings, clientSettings, copyHttp2FrameAsync(serverStream, clientStream, serverSettings, clientSettings,
sessionFactory, sessions, onBeforeResponse, sessionFactory, sessions, onBeforeResponse,
bufferSize, connectionId, false, cancellationTokenSource.Token, exceptionFunc); connectionId, false, cancellationTokenSource.Token, exceptionFunc);
await Task.WhenAny(sendRelay, receiveRelay); await Task.WhenAny(sendRelay, receiveRelay);
cancellationTokenSource.Cancel(); cancellationTokenSource.Cancel();
...@@ -52,24 +59,22 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -52,24 +59,22 @@ namespace Titanium.Web.Proxy.Http2
await Task.WhenAll(sendRelay, receiveRelay); await Task.WhenAll(sendRelay, receiveRelay);
} }
private static async Task copyHttp2FrameAsync(Stream input, Stream output, Action<byte[], int, int> onCopy, private static async Task copyHttp2FrameAsync(Stream input, Stream output,
Http2Settings localSettings, Http2Settings remoteSettings, Http2Settings localSettings, Http2Settings remoteSettings,
Func<SessionEventArgs> sessionFactory, ConcurrentDictionary<int, SessionEventArgs> sessions, Func<SessionEventArgs> sessionFactory, ConcurrentDictionary<int, SessionEventArgs> sessions,
Func<SessionEventArgs, Task> onBeforeRequestResponse, Func<SessionEventArgs, Task> onBeforeRequestResponse,
int bufferSize, Guid connectionId, bool isClient, CancellationToken cancellationToken, Guid connectionId, bool isClient, CancellationToken cancellationToken,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
int headerTableSize = 0; int headerTableSize = 0;
Decoder decoder = null; Decoder? decoder = null;
var frameHeader = new Http2FrameHeader(); var frameHeader = new Http2FrameHeader();
frameHeader.Buffer = new byte[9]; var frameHeaderBuffer = new byte[9];
byte[] buffer = null; byte[]? buffer = null;
while (true) while (true)
{ {
var frameHeaderBuffer = frameHeader.Buffer;
int read = await forceRead(input, frameHeaderBuffer, 0, 9, cancellationToken); int read = await forceRead(input, frameHeaderBuffer, 0, 9, cancellationToken);
onCopy(frameHeaderBuffer, 0, read);
if (read != 9) if (read != 9)
{ {
return; return;
...@@ -92,7 +97,6 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -92,7 +97,6 @@ namespace Titanium.Web.Proxy.Http2
} }
read = await forceRead(input, buffer, 0, length, cancellationToken); read = await forceRead(input, buffer, 0, length, cancellationToken);
onCopy(buffer, 0, read);
if (read != length) if (read != length)
{ {
return; return;
...@@ -101,8 +105,8 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -101,8 +105,8 @@ namespace Titanium.Web.Proxy.Http2
bool sendPacket = true; bool sendPacket = true;
bool endStream = false; bool endStream = false;
SessionEventArgs args = null; SessionEventArgs? args = null;
RequestResponseBase rr = null; RequestResponseBase? rr = null;
if (type == Http2FrameType.Data || type == Http2FrameType.Headers/* || type == Http2FrameType.PushPromise*/) if (type == Http2FrameType.Data || type == Http2FrameType.Headers/* || type == Http2FrameType.PushPromise*/)
{ {
if (!sessions.TryGetValue(streamId, out args)) if (!sessions.TryGetValue(streamId, out args))
...@@ -127,6 +131,11 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -127,6 +131,11 @@ namespace Titanium.Web.Proxy.Http2
//System.Diagnostics.Debug.WriteLine("CONN: " + connectionId + ", CLIENT: " + isClient + ", STREAM: " + streamId + ", TYPE: " + type); //System.Diagnostics.Debug.WriteLine("CONN: " + connectionId + ", CLIENT: " + isClient + ", STREAM: " + streamId + ", TYPE: " + type);
if (type == Http2FrameType.Data && args != null) if (type == Http2FrameType.Data && args != null)
{ {
if (isClient)
args.OnDataSent(buffer, 0, read);
else
args.OnDataReceived(buffer, 0, read);
rr = isClient ? (RequestResponseBase)args.HttpClient.Request : args.HttpClient.Response; rr = isClient ? (RequestResponseBase)args.HttpClient.Request : args.HttpClient.Response;
bool padded = (flags & Http2FrameFlag.Padded) != 0; bool padded = (flags & Http2FrameFlag.Padded) != 0;
...@@ -154,7 +163,7 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -154,7 +163,7 @@ namespace Titanium.Web.Proxy.Http2
length -= buffer[0]; length -= buffer[0];
} }
data.Write(buffer, offset, length); data!.Write(buffer, offset, length);
} }
} }
else if (type == Http2FrameType.Headers/* || type == Http2FrameType.PushPromise*/) else if (type == Http2FrameType.Headers/* || type == Http2FrameType.PushPromise*/)
...@@ -182,8 +191,10 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -182,8 +191,10 @@ namespace Titanium.Web.Proxy.Http2
{ {
args = sessionFactory(); args = sessionFactory();
args.IsPromise = true; args.IsPromise = true;
sessions.TryAdd(streamId, args); if (!sessions.TryAdd(streamId, args))
sessions.TryAdd(promisedStreamId, args); ;
if (!sessions.TryAdd(promisedStreamId, args))
;
} }
System.Diagnostics.Debug.WriteLine("PROMISE STREAM: " + streamId + ", " + promisedStreamId + System.Diagnostics.Debug.WriteLine("PROMISE STREAM: " + streamId + ", " + promisedStreamId +
...@@ -201,7 +212,8 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -201,7 +212,8 @@ namespace Titanium.Web.Proxy.Http2
if (!sessions.TryGetValue(streamId, out args)) if (!sessions.TryGetValue(streamId, out args))
{ {
args = sessionFactory(); args = sessionFactory();
sessions.TryAdd(streamId, args); if (!sessions.TryAdd(streamId, args))
;
} }
rr = isClient ? (RequestResponseBase)args.HttpClient.Request : args.HttpClient.Response; rr = isClient ? (RequestResponseBase)args.HttpClient.Request : args.HttpClient.Response;
...@@ -224,7 +236,7 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -224,7 +236,7 @@ namespace Titanium.Web.Proxy.Http2
(name, value) => (name, value) =>
{ {
var headers = isClient ? args.HttpClient.Request.Headers : args.HttpClient.Response.Headers; var headers = isClient ? args.HttpClient.Request.Headers : args.HttpClient.Response.Headers;
headers.AddHeader(name, value); headers.AddHeader(new HttpHeader(name, value));
}); });
try try
{ {
...@@ -242,18 +254,31 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -242,18 +254,31 @@ namespace Titanium.Web.Proxy.Http2
if (rr is Request request) if (rr is Request request)
{ {
var method = headerListener.Method;
var path = headerListener.Path;
if (method.Length == 0 || path.Length == 0)
{
throw new Exception("HTTP/2 Missing method or path");
}
request.HttpVersion = HttpVersion.Version20; request.HttpVersion = HttpVersion.Version20;
request.Method = headerListener.Method; request.Method = method.GetString();
request.OriginalUrl = headerListener.Path; request.IsHttps = headerListener.Scheme == ProxyServer.UriSchemeHttps;
request.Authority = headerListener.Authority.GetString();
request.OriginalUrlData = path;
request.RequestUri = headerListener.GetUri(); //request.RequestUri = headerListener.GetUri();
} }
else else
{ {
var response = (Response)rr; var response = (Response)rr;
response.HttpVersion = HttpVersion.Version20; response.HttpVersion = HttpVersion.Version20;
int.TryParse(headerListener.Status, out int statusCode);
// todo: avoid string conversion
string statusHack = HttpHeader.Encoding.GetString(headerListener.Status.Span);
int.TryParse(statusHack, out int statusCode);
response.StatusCode = statusCode; response.StatusCode = statusCode;
response.StatusDescription = string.Empty;
} }
} }
catch (Exception ex) catch (Exception ex)
...@@ -278,7 +303,7 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -278,7 +303,7 @@ namespace Titanium.Web.Proxy.Http2
{ {
rr.ReadHttp2BeforeHandlerTaskCompletionSource = null; rr.ReadHttp2BeforeHandlerTaskCompletionSource = null;
tcs.SetResult(true); tcs.SetResult(true);
await sendHeader(remoteSettings, frameHeader, rr, endStream, output, args.IsPromise); await sendHeader(remoteSettings, frameHeader, frameHeaderBuffer, rr, endStream, output, args.IsPromise);
} }
else else
{ {
...@@ -343,19 +368,19 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -343,19 +368,19 @@ namespace Titanium.Web.Proxy.Http2
} }
} }
if (endStream && rr.ReadHttp2BodyTaskCompletionSource != null) if (endStream && rr!.ReadHttp2BodyTaskCompletionSource != null)
{ {
if (!rr.BodyAvailable) if (!rr.BodyAvailable)
{ {
var data = rr.Http2BodyData; var data = rr.Http2BodyData;
var body = data.ToArray(); var body = data!.ToArray();
if (rr.ContentEncoding != null) if (rr.ContentEncoding != null)
{ {
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())
{ {
using (var zip = using (var zip =
DecompressionFactory.Create(rr.ContentEncoding, new MemoryStream(body))) DecompressionFactory.Create(CompressionUtil.CompressionNameToEnum(rr.ContentEncoding), new MemoryStream(body)))
{ {
zip.CopyTo(ms); zip.CopyTo(ms);
} }
...@@ -384,12 +409,12 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -384,12 +409,12 @@ namespace Titanium.Web.Proxy.Http2
await rr.Http2BeforeHandlerTask; await rr.Http2BeforeHandlerTask;
} }
if (args.IsPromise) if (args!.IsPromise)
{ {
breakpoint(); breakpoint();
} }
await sendBody(remoteSettings, rr, frameHeader, buffer, output); await sendBody(remoteSettings, rr, frameHeader, frameHeaderBuffer, buffer, output);
} }
if (!isClient && endStream) if (!isClient && endStream)
...@@ -401,8 +426,8 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -401,8 +426,8 @@ namespace Titanium.Web.Proxy.Http2
if (sendPacket) if (sendPacket)
{ {
// do not cancel the write operation // do not cancel the write operation
var buf = frameHeader.CopyToBuffer(); frameHeader.CopyToBuffer(frameHeaderBuffer);
await output.WriteAsync(buf, 0, buf.Length/*, cancellationToken*/); await output.WriteAsync(frameHeaderBuffer, 0, frameHeaderBuffer.Length/*, cancellationToken*/);
await output.WriteAsync(buffer, 0, length /*, cancellationToken*/); await output.WriteAsync(buffer, 0, length /*, cancellationToken*/);
} }
...@@ -426,7 +451,7 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -426,7 +451,7 @@ namespace Titanium.Web.Proxy.Http2
; ;
} }
private static async Task sendHeader(Http2Settings settings, Http2FrameHeader frameHeader, RequestResponseBase rr, bool endStream, Stream output, bool pushPromise) private static async Task sendHeader(Http2Settings settings, Http2FrameHeader frameHeader, byte[] frameHeaderBuffer, RequestResponseBase rr, bool endStream, Stream output, bool pushPromise)
{ {
var encoder = new Encoder(settings.HeaderTableSize); var encoder = new Encoder(settings.HeaderTableSize);
var ms = new MemoryStream(); var ms = new MemoryStream();
...@@ -443,21 +468,22 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -443,21 +468,22 @@ namespace Titanium.Web.Proxy.Http2
if (rr is Request request) if (rr is Request request)
{ {
encoder.EncodeHeader(writer, ":method", request.Method); var uri = request.RequestUri;
encoder.EncodeHeader(writer, ":authority", request.RequestUri.Host); encoder.EncodeHeader(writer, StaticTable.KnownHeaderMethod, request.Method.GetByteString());
encoder.EncodeHeader(writer, ":scheme", request.RequestUri.Scheme); encoder.EncodeHeader(writer, StaticTable.KnownHeaderAuhtority, uri.Authority.GetByteString());
encoder.EncodeHeader(writer, ":path", request.RequestUriString, false, encoder.EncodeHeader(writer, StaticTable.KnownHeaderScheme, uri.Scheme.GetByteString());
encoder.EncodeHeader(writer, StaticTable.KnownHeaderPath, request.Url.GetByteString(), false,
HpackUtil.IndexType.None, false); HpackUtil.IndexType.None, false);
} }
else else
{ {
var response = (Response)rr; var response = (Response)rr;
encoder.EncodeHeader(writer, ":status", response.StatusCode.ToString()); encoder.EncodeHeader(writer, StaticTable.KnownHeaderStatus, response.StatusCode.ToString().GetByteString());
} }
foreach (var header in rr.Headers) foreach (var header in rr.Headers)
{ {
encoder.EncodeHeader(writer, header.Name.ToLower(), header.Value); encoder.EncodeHeader(writer, header.NameData, header.ValueData);
} }
var data = ms.ToArray(); var data = ms.ToArray();
...@@ -483,20 +509,20 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -483,20 +509,20 @@ namespace Titanium.Web.Proxy.Http2
//headerBuffer[4] = (byte)(flags & ~((int)Http2FrameFlag.Padded)); //headerBuffer[4] = (byte)(flags & ~((int)Http2FrameFlag.Padded));
// send the header // send the header
var buf = frameHeader.CopyToBuffer(); frameHeader.CopyToBuffer(frameHeaderBuffer);
await output.WriteAsync(buf, 0, buf.Length/*, cancellationToken*/); await output.WriteAsync(frameHeaderBuffer, 0, frameHeaderBuffer.Length/*, cancellationToken*/);
await output.WriteAsync(data, 0, data.Length /*, cancellationToken*/); await output.WriteAsync(data, 0, data.Length /*, cancellationToken*/);
} }
private static async Task sendBody(Http2Settings settings, RequestResponseBase rr, Http2FrameHeader frameHeader, byte[] buffer, Stream output) private static async Task sendBody(Http2Settings settings, RequestResponseBase rr, Http2FrameHeader frameHeader, byte[] frameHeaderBuffer, byte[] buffer, Stream output)
{ {
var body = rr.CompressBodyAndUpdateContentLength(); var body = rr.CompressBodyAndUpdateContentLength();
await sendHeader(settings, frameHeader, rr, !(rr.HasBody && rr.IsBodyRead), output, false); await sendHeader(settings, frameHeader, frameHeaderBuffer, rr, !(rr.HasBody && rr.IsBodyRead), output, false);
if (rr.HasBody && rr.IsBodyRead) if (rr.HasBody && rr.IsBodyRead)
{ {
int pos = 0; int pos = 0;
while (pos < body.Length) while (pos < body!.Length)
{ {
int bodyFrameLength = Math.Min(buffer.Length, body.Length - pos); int bodyFrameLength = Math.Min(buffer.Length, body.Length - pos);
Buffer.BlockCopy(body, pos, buffer, 0, bodyFrameLength); Buffer.BlockCopy(body, pos, buffer, 0, bodyFrameLength);
...@@ -506,8 +532,8 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -506,8 +532,8 @@ namespace Titanium.Web.Proxy.Http2
frameHeader.Type = Http2FrameType.Data; frameHeader.Type = Http2FrameType.Data;
frameHeader.Flags = pos < body.Length ? (Http2FrameFlag)0 : Http2FrameFlag.EndStream; frameHeader.Flags = pos < body.Length ? (Http2FrameFlag)0 : Http2FrameFlag.EndStream;
var buf = frameHeader.CopyToBuffer(); frameHeader.CopyToBuffer(frameHeaderBuffer);
await output.WriteAsync(buf, 0, buf.Length/*, cancellationToken*/); await output.WriteAsync(frameHeaderBuffer, 0, frameHeaderBuffer.Length/*, cancellationToken*/);
await output.WriteAsync(buffer, 0, bodyFrameLength /*, cancellationToken*/); await output.WriteAsync(buffer, 0, bodyFrameLength /*, cancellationToken*/);
} }
} }
...@@ -547,34 +573,53 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -547,34 +573,53 @@ namespace Titanium.Web.Proxy.Http2
class MyHeaderListener : IHeaderListener class MyHeaderListener : IHeaderListener
{ {
private readonly Action<string, string> addHeaderFunc; private readonly Action<ByteString, ByteString> addHeaderFunc;
public ByteString Method { get; private set; }
public ByteString Status { get; private set; }
public string Method { get; private set; } public ByteString Authority { get; private set; }
public string Status { get; private set; } private ByteString scheme;
private string authority; public ByteString Path { get; private set; }
private string scheme; public string Scheme
{
get
{
if (scheme.Equals(ProxyServer.UriSchemeHttp8))
{
return ProxyServer.UriSchemeHttp;
}
public string Path { get; private set; } if (scheme.Equals(ProxyServer.UriSchemeHttps8))
{
return ProxyServer.UriSchemeHttps;
}
return string.Empty;
}
}
public MyHeaderListener(Action<string, string> addHeaderFunc) public MyHeaderListener(Action<ByteString, ByteString> addHeaderFunc)
{ {
this.addHeaderFunc = addHeaderFunc; this.addHeaderFunc = addHeaderFunc;
} }
public void AddHeader(string name, string value, bool sensitive) public void AddHeader(ByteString name, ByteString value, bool sensitive)
{ {
if (name[0] == ':') if (name.Span[0] == ':')
{ {
switch (name) string nameStr = Encoding.ASCII.GetString(name.Span);
switch (nameStr)
{ {
case ":method": case ":method":
Method = value; Method = value;
return; return;
case ":authority": case ":authority":
authority = value; Authority = value;
return; return;
case ":scheme": case ":scheme":
scheme = value; scheme = value;
...@@ -593,13 +638,23 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -593,13 +638,23 @@ namespace Titanium.Web.Proxy.Http2
public Uri GetUri() public Uri GetUri()
{ {
if (authority == null) if (Authority.Length == 0)
{ {
// todo // todo
authority = "abc.abc"; Authority = HttpHeader.Encoding.GetBytes("abc.abc");
} }
return new Uri(scheme + "://" + authority + Path); var bytes = new byte[scheme.Length + 3 + Authority.Length + Path.Length];
scheme.Span.CopyTo(bytes);
int idx = scheme.Length;
bytes[idx++] = (byte)':';
bytes[idx++] = (byte)'/';
bytes[idx++] = (byte)'/';
Authority.Span.CopyTo(bytes.AsSpan(idx, Authority.Length));
idx += Authority.Length;
Path.Span.CopyTo(bytes.AsSpan(idx, Path.Length));
return new Uri(HttpHeader.Encoding.GetString(bytes));
} }
} }
} }
......
using System;
using System.Text;
namespace Titanium.Web.Proxy.Models
{
internal struct ByteString : IEquatable<ByteString>
{
public static ByteString Empty = new ByteString(ReadOnlyMemory<byte>.Empty);
public ReadOnlyMemory<byte> Data { get; }
public ReadOnlySpan<byte> Span => Data.Span;
public int Length => Data.Length;
public ByteString(ReadOnlyMemory<byte> data)
{
Data = data;
}
public override bool Equals(object? obj)
{
return obj is ByteString other && Equals(other);
}
public bool Equals(ByteString other)
{
return Data.Span.SequenceEqual(other.Data.Span);
}
public override int GetHashCode()
{
return Data.GetHashCode();
}
public static explicit operator ByteString(string str) => new ByteString(Encoding.ASCII.GetBytes(str));
public static implicit operator ByteString(byte[] data) => new ByteString(data);
public static implicit operator ByteString(ReadOnlyMemory<byte> data) => new ByteString(data);
public byte this[int i]
{
get => Span[i];
}
}
}
using System.Net; using System.Diagnostics;
using System.Security.Cryptography.X509Certificates; 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;
...@@ -10,6 +10,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -10,6 +10,7 @@ namespace Titanium.Web.Proxy.Models
/// A proxy endpoint that the client is aware of. /// A proxy endpoint that the client is aware of.
/// So client application know that it is communicating with a proxy server. /// So client application know that it is communicating with a proxy server.
/// </summary> /// </summary>
[DebuggerDisplay("Explicit: {IpAddress}:{Port}")]
public class ExplicitProxyEndPoint : ProxyEndPoint public class ExplicitProxyEndPoint : ProxyEndPoint
{ {
/// <summary> /// <summary>
...@@ -33,13 +34,13 @@ namespace Titanium.Web.Proxy.Models ...@@ -33,13 +34,13 @@ namespace Titanium.Web.Proxy.Models
/// Set the <see cref="TunnelConnectSessionEventArgs.DecryptSsl" /> property to false if this HTTP connect request /// Set the <see cref="TunnelConnectSessionEventArgs.DecryptSsl" /> property to false if this HTTP connect request
/// shouldn't be decrypted and instead be relayed. /// shouldn't be decrypted and instead be relayed.
/// </summary> /// </summary>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectRequest; public event AsyncEventHandler<TunnelConnectSessionEventArgs>? BeforeTunnelConnectRequest;
/// <summary> /// <summary>
/// Intercept tunnel connect response. /// Intercept tunnel connect response.
/// Valid only for explicit endpoints. /// Valid only for explicit endpoints.
/// </summary> /// </summary>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectResponse; public event AsyncEventHandler<TunnelConnectSessionEventArgs>? BeforeTunnelConnectResponse;
internal async Task InvokeBeforeTunnelConnectRequest(ProxyServer proxyServer, internal async Task InvokeBeforeTunnelConnectRequest(ProxyServer proxyServer,
TunnelConnectSessionEventArgs connectArgs, ExceptionHandler exceptionFunc) TunnelConnectSessionEventArgs connectArgs, ExceptionHandler exceptionFunc)
......
...@@ -11,9 +11,9 @@ namespace Titanium.Web.Proxy.Models ...@@ -11,9 +11,9 @@ namespace Titanium.Web.Proxy.Models
private static readonly Lazy<NetworkCredential> defaultCredentials = private static readonly Lazy<NetworkCredential> defaultCredentials =
new Lazy<NetworkCredential>(() => CredentialCache.DefaultNetworkCredentials); new Lazy<NetworkCredential>(() => CredentialCache.DefaultNetworkCredentials);
private string password; private string? password;
private string userName; private string? userName;
/// <summary> /// <summary>
/// Use default windows credentials? /// Use default windows credentials?
...@@ -28,7 +28,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -28,7 +28,7 @@ namespace Titanium.Web.Proxy.Models
/// <summary> /// <summary>
/// Username. /// Username.
/// </summary> /// </summary>
public string UserName public string? UserName
{ {
get => UseDefaultCredentials ? defaultCredentials.Value.UserName : userName; get => UseDefaultCredentials ? defaultCredentials.Value.UserName : userName;
set set
...@@ -45,7 +45,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -45,7 +45,7 @@ namespace Titanium.Web.Proxy.Models
/// <summary> /// <summary>
/// Password. /// Password.
/// </summary> /// </summary>
public string Password public string? Password
{ {
get => UseDefaultCredentials ? defaultCredentials.Value.Password : password; get => UseDefaultCredentials ? defaultCredentials.Value.Password : password;
set set
...@@ -62,22 +62,13 @@ namespace Titanium.Web.Proxy.Models ...@@ -62,22 +62,13 @@ namespace Titanium.Web.Proxy.Models
/// <summary> /// <summary>
/// Host name. /// Host name.
/// </summary> /// </summary>
public string HostName { get; set; } public string HostName { get; set; } = string.Empty;
/// <summary> /// <summary>
/// Port. /// Port.
/// </summary> /// </summary>
public int Port { get; set; } public int Port { get; set; }
/// <summary>
/// Get cache key for Tcp connection cache.
/// </summary>
/// <returns></returns>
internal string GetCacheKey()
{
return $"{HostName}-{Port}" + (UseDefaultCredentials ? $"-{UserName}-{Password}" : string.Empty);
}
/// <summary> /// <summary>
/// returns data in Hostname:port format. /// returns data in Hostname:port format.
/// </summary> /// </summary>
......
using System; using System;
using System.Net;
using System.Text; using System.Text;
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,16 +19,32 @@ namespace Titanium.Web.Proxy.Models ...@@ -16,16 +19,32 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public const int HttpHeaderOverhead = 32; public const int HttpHeaderOverhead = 32;
internal static readonly Version VersionUnknown = new Version(0, 0); #if NETSTANDARD2_1
internal static Version VersionUnknown => HttpVersion.Unknown;
#else
internal static Version VersionUnknown { get; } = new Version(0, 0);
#endif
internal static readonly Version Version10 = new Version(1, 0); internal static Version Version10 => HttpVersion.Version10;
internal static readonly Version Version11 = new Version(1, 1); internal static Version Version11 => HttpVersion.Version11;
internal static readonly Version Version20 = new Version(2, 0); #if NETSTANDARD2_1
internal static Version Version20 => HttpVersion.Version20;
#else
internal static Version Version20 { get; } = new Version(2, 0);
#endif
internal static readonly Encoding DefaultEncoding = Encoding.GetEncoding("ISO-8859-1");
public static Encoding Encoding => DefaultEncoding;
internal static readonly HttpHeader ProxyConnectionKeepAlive = new HttpHeader("Proxy-Connection", "keep-alive"); internal static readonly HttpHeader ProxyConnectionKeepAlive = new HttpHeader("Proxy-Connection", "keep-alive");
private string? nameString;
private string? valueString;
/// <summary> /// <summary>
/// Initialize a new instance. /// Initialize a new instance.
/// </summary> /// </summary>
...@@ -38,34 +57,82 @@ namespace Titanium.Web.Proxy.Models ...@@ -38,34 +57,82 @@ namespace Titanium.Web.Proxy.Models
throw new Exception("Name cannot be null or empty"); throw new Exception("Name cannot be null or empty");
} }
Name = name.Trim(); nameString = name.Trim();
Value = value.Trim(); NameData = nameString.GetByteString();
valueString = value.Trim();
ValueData = valueString.GetByteString();
}
internal HttpHeader(KnownHeader name, string value)
{
nameString = name.String;
NameData = name.String8;
valueString = value.Trim();
ValueData = valueString.GetByteString();
}
internal HttpHeader(KnownHeader name, KnownHeader value)
{
nameString = name.String;
NameData = name.String8;
valueString = value.String;
ValueData = value.String8;
}
internal HttpHeader(ByteString name, ByteString value)
{
if (name.Length == 0)
{
throw new Exception("Name cannot be empty");
}
NameData = name;
ValueData = value;
} }
protected HttpHeader(string name, string value, bool headerEntry) private protected HttpHeader(ByteString name, ByteString value, bool headerEntry)
{ {
// special header entry created in inherited class with empty name // special header entry created in inherited class with empty name
Name = name.Trim(); NameData = name;
Value = value.Trim(); ValueData = value;
} }
/// <summary> /// <summary>
/// Header Name. /// Header Name.
/// </summary> /// </summary>
public string Name { get; } public string Name => nameString ??= NameData.GetString();
internal ByteString NameData { get; }
/// <summary> /// <summary>
/// Header Value. /// Header Value.
/// </summary> /// </summary>
public string Value { get; set; } public string Value => valueString ??= ValueData.GetString();
internal ByteString ValueData { get; private set; }
public int Size => Name.Length + Value.Length + HttpHeaderOverhead; public int Size => Name.Length + Value.Length + HttpHeaderOverhead;
public static int SizeOf(string name, string value) internal static int SizeOf(ByteString name, ByteString value)
{ {
return name.Length + value.Length + HttpHeaderOverhead; return name.Length + value.Length + HttpHeaderOverhead;
} }
internal void SetValue(string value)
{
valueString = value;
ValueData = value.GetByteString();
}
internal void SetValue(KnownHeader value)
{
valueString = value.String;
ValueData = value.String8;
}
/// <summary> /// <summary>
/// Returns header as a valid header string. /// Returns header as a valid header string.
/// </summary> /// </summary>
...@@ -75,7 +142,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -75,7 +142,7 @@ namespace Titanium.Web.Proxy.Models
return $"{Name}: {Value}"; return $"{Name}: {Value}";
} }
internal static HttpHeader GetProxyAuthorizationHeader(string userName, string password) internal static HttpHeader GetProxyAuthorizationHeader(string? userName, string? password)
{ {
var result = new HttpHeader(KnownHeaders.ProxyAuthorization, var result = new HttpHeader(KnownHeaders.ProxyAuthorization,
"Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{userName}:{password}"))); "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{userName}:{password}")));
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
/// <summary> /// <summary>
/// An optional continuation token to return to the caller if set /// An optional continuation token to return to the caller if set
/// </summary> /// </summary>
public string Continuation { get; set; } public string? Continuation { get; set; }
public static ProxyAuthenticationContext Failed() public static ProxyAuthenticationContext Failed()
{ {
......
...@@ -25,7 +25,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -25,7 +25,7 @@ namespace Titanium.Web.Proxy.Models
/// <summary> /// <summary>
/// underlying TCP Listener object /// underlying TCP Listener object
/// </summary> /// </summary>
internal TcpListener Listener { get; set; } internal TcpListener? Listener { get; set; }
/// <summary> /// <summary>
/// Ip Address we are listening. /// Ip Address we are listening.
...@@ -42,17 +42,9 @@ namespace Titanium.Web.Proxy.Models ...@@ -42,17 +42,9 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public bool DecryptSsl { get; } public bool DecryptSsl { get; }
/// <summary>
/// Is IPv6 enabled?
/// </summary>
public bool IpV6Enabled => Equals(IpAddress, IPAddress.IPv6Any)
|| Equals(IpAddress, IPAddress.IPv6Loopback)
|| Equals(IpAddress, IPAddress.IPv6None);
/// <summary> /// <summary>
/// Generic certificate to use for SSL decryption. /// Generic certificate to use for SSL decryption.
/// </summary> /// </summary>
public X509Certificate2 GenericCertificate { get; set; } public X509Certificate2? GenericCertificate { get; set; }
} }
} }
using System.Net; using System.Diagnostics;
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;
...@@ -9,6 +10,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -9,6 +10,7 @@ namespace Titanium.Web.Proxy.Models
/// A proxy end point client is not aware of. /// A proxy end point client is not aware of.
/// Useful when requests are redirected to this proxy end point through port forwarding via router. /// Useful when requests are redirected to this proxy end point through port forwarding via router.
/// </summary> /// </summary>
[DebuggerDisplay("Transparent: {IpAddress}:{Port}")]
public class TransparentProxyEndPoint : ProxyEndPoint public class TransparentProxyEndPoint : ProxyEndPoint
{ {
/// <summary> /// <summary>
...@@ -32,7 +34,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -32,7 +34,7 @@ namespace Titanium.Web.Proxy.Models
/// <summary> /// <summary>
/// Before Ssl authentication this event is fired. /// Before Ssl authentication this event is fired.
/// </summary> /// </summary>
public event AsyncEventHandler<BeforeSslAuthenticateEventArgs> BeforeSslAuthenticate; public event AsyncEventHandler<BeforeSslAuthenticateEventArgs>? BeforeSslAuthenticate;
internal async Task InvokeBeforeSslAuthenticate(ProxyServer proxyServer, internal async Task InvokeBeforeSslAuthenticate(ProxyServer proxyServer,
BeforeSslAuthenticateEventArgs connectArgs, ExceptionHandler exceptionFunc) BeforeSslAuthenticateEventArgs connectArgs, ExceptionHandler exceptionFunc)
......
using System; using System;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Network namespace Titanium.Web.Proxy.Network
{ {
...@@ -9,7 +8,12 @@ namespace Titanium.Web.Proxy.Network ...@@ -9,7 +8,12 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
internal sealed class CachedCertificate internal sealed class CachedCertificate
{ {
internal X509Certificate2 Certificate { get; set; } public CachedCertificate(X509Certificate2 certificate)
{
Certificate = certificate;
}
internal X509Certificate2 Certificate { get; }
/// <summary> /// <summary>
/// Last time this certificate was used. /// Last time this certificate was used.
......
...@@ -48,9 +48,9 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -48,9 +48,9 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <param name="isRoot">if set to <c>true</c> [is root].</param> /// <param name="isRoot">if set to <c>true</c> [is root].</param>
/// <param name="signingCert">The signing cert.</param> /// <param name="signingCert">The signing cert.</param>
/// <returns>X509Certificate2 instance.</returns> /// <returns>X509Certificate2 instance.</returns>
public X509Certificate2 MakeCertificate(string sSubjectCn, bool isRoot, X509Certificate2 signingCert = null) public X509Certificate2 MakeCertificate(string sSubjectCn, X509Certificate2? signingCert = null)
{ {
return makeCertificateInternal(sSubjectCn, isRoot, true, signingCert); return makeCertificateInternal(sSubjectCn, true, signingCert);
} }
/// <summary> /// <summary>
...@@ -66,12 +66,12 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -66,12 +66,12 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <param name="hostName">The host name</param> /// <param name="hostName">The host name</param>
/// <returns>X509Certificate2 instance.</returns> /// <returns>X509Certificate2 instance.</returns>
/// <exception cref="PemException">Malformed sequence in RSA private key</exception> /// <exception cref="PemException">Malformed sequence in RSA private key</exception>
private static X509Certificate2 generateCertificate(string hostName, private static X509Certificate2 generateCertificate(string? hostName,
string subjectName, string subjectName,
string issuerName, DateTime validFrom, string issuerName, DateTime validFrom,
DateTime validTo, int keyStrength = 2048, DateTime validTo, int keyStrength = 2048,
string signatureAlgorithm = "SHA256WithRSA", string signatureAlgorithm = "SHA256WithRSA",
AsymmetricKeyParameter issuerPrivateKey = null) AsymmetricKeyParameter? issuerPrivateKey = null)
{ {
// Generating Random Numbers // Generating Random Numbers
var randomGenerator = new CryptoApiRandomGenerator(); var randomGenerator = new CryptoApiRandomGenerator();
...@@ -162,11 +162,11 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -162,11 +162,11 @@ namespace Titanium.Web.Proxy.Network.Certificate
private static X509Certificate2 withPrivateKey(X509Certificate certificate, AsymmetricKeyParameter privateKey) private static X509Certificate2 withPrivateKey(X509Certificate certificate, AsymmetricKeyParameter privateKey)
{ {
const string password = "password"; const string password = "password";
Pkcs12Store store = null; Pkcs12Store store;
if(RunTime.IsRunningOnMono) if(RunTime.IsRunningOnMono)
{ {
Pkcs12StoreBuilder builder = new Pkcs12StoreBuilder(); var builder = new Pkcs12StoreBuilder();
builder.SetUseDerEncoding(true); builder.SetUseDerEncoding(true);
store = builder.Build(); store = builder.Build();
} }
...@@ -190,7 +190,6 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -190,7 +190,6 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <summary> /// <summary>
/// Makes the certificate internal. /// Makes the certificate internal.
/// </summary> /// </summary>
/// <param name="isRoot">if set to <c>true</c> [is root].</param>
/// <param name="hostName">hostname for certificate</param> /// <param name="hostName">hostname for certificate</param>
/// <param name="subjectName">The full subject.</param> /// <param name="subjectName">The full subject.</param>
/// <param name="validFrom">The valid from.</param> /// <param name="validFrom">The valid from.</param>
...@@ -201,18 +200,10 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -201,18 +200,10 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// You must specify a Signing Certificate if and only if you are not creating a /// You must specify a Signing Certificate if and only if you are not creating a
/// root. /// root.
/// </exception> /// </exception>
private X509Certificate2 makeCertificateInternal(bool isRoot, private X509Certificate2 makeCertificateInternal(string hostName, string subjectName,
string hostName, string subjectName, DateTime validFrom, DateTime validTo, X509Certificate2? signingCertificate)
DateTime validFrom, DateTime validTo, X509Certificate2 signingCertificate)
{ {
if (isRoot != (null == signingCertificate)) if (signingCertificate == null)
{
throw new ArgumentException(
"You must specify a Signing Certificate if and only if you are not creating a root.",
nameof(signingCertificate));
}
if (isRoot)
{ {
return generateCertificate(null, subjectName, subjectName, validFrom, validTo); return generateCertificate(null, subjectName, subjectName, validFrom, validTo);
} }
...@@ -226,18 +217,17 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -226,18 +217,17 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// Makes the certificate internal. /// Makes the certificate internal.
/// </summary> /// </summary>
/// <param name="subject">The s subject cn.</param> /// <param name="subject">The s subject cn.</param>
/// <param name="isRoot">if set to <c>true</c> [is root].</param>
/// <param name="switchToMtaIfNeeded">if set to <c>true</c> [switch to MTA if needed].</param> /// <param name="switchToMtaIfNeeded">if set to <c>true</c> [switch to MTA if needed].</param>
/// <param name="signingCert">The signing cert.</param> /// <param name="signingCert">The signing cert.</param>
/// <param name="cancellationToken">Task cancellation token</param> /// <param name="cancellationToken">Task cancellation token</param>
/// <returns>X509Certificate2.</returns> /// <returns>X509Certificate2.</returns>
private X509Certificate2 makeCertificateInternal(string subject, bool isRoot, private X509Certificate2 makeCertificateInternal(string subject,
bool switchToMtaIfNeeded, X509Certificate2 signingCert = null, bool switchToMtaIfNeeded, X509Certificate2? signingCert = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
return makeCertificateInternal(isRoot, subject, $"CN={subject}", return makeCertificateInternal(subject, $"CN={subject}",
DateTime.UtcNow.AddDays(-certificateGraceDays), DateTime.UtcNow.AddDays(certificateValidDays), DateTime.UtcNow.AddDays(-certificateGraceDays), DateTime.UtcNow.AddDays(certificateValidDays),
isRoot ? null : signingCert); signingCert);
} }
} }
} }
...@@ -7,6 +7,6 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -7,6 +7,6 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// </summary> /// </summary>
internal interface ICertificateMaker internal interface ICertificateMaker
{ {
X509Certificate2 MakeCertificate(string sSubjectCn, bool isRoot, X509Certificate2 signingCert); X509Certificate2 MakeCertificate(string sSubjectCn, X509Certificate2? signingCert);
} }
} }
...@@ -44,7 +44,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -44,7 +44,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
private readonly Type typeX509PrivateKey; private readonly Type typeX509PrivateKey;
private object sharedPrivateKey; private object? sharedPrivateKey;
/// <summary> /// <summary>
/// Constructor. /// Constructor.
...@@ -75,18 +75,18 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -75,18 +75,18 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <summary> /// <summary>
/// Make certificate. /// Make certificate.
/// </summary> /// </summary>
public X509Certificate2 MakeCertificate(string sSubjectCN, bool isRoot, X509Certificate2 signingCert = null) public X509Certificate2 MakeCertificate(string sSubjectCN, X509Certificate2? signingCert = null)
{ {
return makeCertificate(sSubjectCN, isRoot, true, signingCert); return makeCertificate(sSubjectCN, true, signingCert);
} }
private X509Certificate2 makeCertificate(string sSubjectCN, bool isRoot, private X509Certificate2 makeCertificate(string sSubjectCN,
bool switchToMTAIfNeeded, X509Certificate2 signingCert = null, bool switchToMTAIfNeeded, X509Certificate2? signingCertificate = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
if (switchToMTAIfNeeded && Thread.CurrentThread.GetApartmentState() != ApartmentState.MTA) if (switchToMTAIfNeeded && Thread.CurrentThread.GetApartmentState() != ApartmentState.MTA)
{ {
return Task.Run(() => makeCertificate(sSubjectCN, isRoot, false, signingCert), return Task.Run(() => makeCertificate(sSubjectCN, false, signingCertificate),
cancellationToken).Result; cancellationToken).Result;
} }
...@@ -107,37 +107,30 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -107,37 +107,30 @@ namespace Titanium.Web.Proxy.Network.Certificate
var now = DateTime.Now; var now = DateTime.Now;
var graceTime = now.AddDays(graceDays); var graceTime = now.AddDays(graceDays);
var certificate = makeCertificate(isRoot, sSubjectCN, fullSubject, keyLength, hashAlgo, graceTime, var certificate = makeCertificate(sSubjectCN, fullSubject, keyLength, hashAlgo, graceTime,
now.AddDays(validDays), isRoot ? null : signingCert); now.AddDays(validDays), signingCertificate);
return certificate; return certificate;
} }
private X509Certificate2 makeCertificate(bool isRoot, string subject, string fullSubject, private X509Certificate2 makeCertificate(string subject, string fullSubject,
int privateKeyLength, string hashAlg, DateTime validFrom, DateTime validTo, int privateKeyLength, string hashAlg, DateTime validFrom, DateTime validTo,
X509Certificate2 signingCertificate) X509Certificate2? signingCertificate)
{ {
if (isRoot != (null == signingCertificate))
{
throw new ArgumentException(
"You must specify a Signing Certificate if and only if you are not creating a root.",
nameof(isRoot));
}
var x500CertDN = Activator.CreateInstance(typeX500DN); var x500CertDN = Activator.CreateInstance(typeX500DN);
var typeValue = new object[] { fullSubject, 0 }; var typeValue = new object[] { fullSubject, 0 };
typeX500DN.InvokeMember("Encode", BindingFlags.InvokeMethod, null, x500CertDN, typeValue); typeX500DN.InvokeMember("Encode", BindingFlags.InvokeMethod, null, x500CertDN, typeValue);
var x500RootCertDN = Activator.CreateInstance(typeX500DN); var x500RootCertDN = Activator.CreateInstance(typeX500DN);
if (!isRoot) if (signingCertificate != null)
{ {
typeValue[0] = signingCertificate.Subject; typeValue[0] = signingCertificate.Subject;
} }
typeX500DN.InvokeMember("Encode", BindingFlags.InvokeMethod, null, x500RootCertDN, typeValue); typeX500DN.InvokeMember("Encode", BindingFlags.InvokeMethod, null, x500RootCertDN, typeValue);
object sharedPrivateKey = null; object? sharedPrivateKey = null;
if (!isRoot) if (signingCertificate != null)
{ {
sharedPrivateKey = this.sharedPrivateKey; sharedPrivateKey = this.sharedPrivateKey;
} }
...@@ -151,11 +144,11 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -151,11 +144,11 @@ namespace Titanium.Web.Proxy.Network.Certificate
typeValue[0] = 2; typeValue[0] = 2;
typeX509PrivateKey.InvokeMember("ExportPolicy", BindingFlags.PutDispProperty, null, sharedPrivateKey, typeX509PrivateKey.InvokeMember("ExportPolicy", BindingFlags.PutDispProperty, null, sharedPrivateKey,
typeValue); typeValue);
typeValue = new object[] { isRoot ? 2 : 1 }; typeValue = new object[] { signingCertificate == null ? 2 : 1 };
typeX509PrivateKey.InvokeMember("KeySpec", BindingFlags.PutDispProperty, null, sharedPrivateKey, typeX509PrivateKey.InvokeMember("KeySpec", BindingFlags.PutDispProperty, null, sharedPrivateKey,
typeValue); typeValue);
if (!isRoot) if (signingCertificate != null)
{ {
typeValue = new object[] { 176 }; typeValue = new object[] { 176 };
typeX509PrivateKey.InvokeMember("KeyUsage", BindingFlags.PutDispProperty, null, sharedPrivateKey, typeX509PrivateKey.InvokeMember("KeyUsage", BindingFlags.PutDispProperty, null, sharedPrivateKey,
...@@ -167,7 +160,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -167,7 +160,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
typeValue); typeValue);
typeX509PrivateKey.InvokeMember("Create", BindingFlags.InvokeMethod, null, sharedPrivateKey, null); typeX509PrivateKey.InvokeMember("Create", BindingFlags.InvokeMethod, null, sharedPrivateKey, null);
if (!isRoot) if (signingCertificate != null)
{ {
this.sharedPrivateKey = sharedPrivateKey; this.sharedPrivateKey = sharedPrivateKey;
} }
...@@ -210,7 +203,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -210,7 +203,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
typeRequestCert.InvokeMember("X509Extensions", BindingFlags.GetProperty, null, requestCert, null); typeRequestCert.InvokeMember("X509Extensions", BindingFlags.GetProperty, null, requestCert, null);
typeValue = new object[1]; typeValue = new object[1];
if (!isRoot) if (signingCertificate != null)
{ {
typeValue[0] = kuExt; typeValue[0] = kuExt;
typeX509Extensions.InvokeMember("Add", BindingFlags.InvokeMethod, null, certificate, typeValue); typeX509Extensions.InvokeMember("Add", BindingFlags.InvokeMethod, null, certificate, typeValue);
...@@ -219,7 +212,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -219,7 +212,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
typeValue[0] = ekuExt; typeValue[0] = ekuExt;
typeX509Extensions.InvokeMember("Add", BindingFlags.InvokeMethod, null, certificate, typeValue); typeX509Extensions.InvokeMember("Add", BindingFlags.InvokeMethod, null, certificate, typeValue);
if (!isRoot) if (signingCertificate != null)
{ {
// add alternative names // add alternative names
// https://forums.iis.net/t/1180823.aspx // https://forums.iis.net/t/1180823.aspx
...@@ -244,7 +237,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -244,7 +237,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
typeX509Extensions.InvokeMember("Add", BindingFlags.InvokeMethod, null, certificate, typeValue); typeX509Extensions.InvokeMember("Add", BindingFlags.InvokeMethod, null, certificate, typeValue);
} }
if (!isRoot) if (signingCertificate != null)
{ {
var signerCertificate = Activator.CreateInstance(typeSignerCertificate); var signerCertificate = Activator.CreateInstance(typeSignerCertificate);
...@@ -281,7 +274,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -281,7 +274,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
typeX509Enrollment.InvokeMember("InitializeFromRequest", BindingFlags.InvokeMethod, null, x509Enrollment, typeX509Enrollment.InvokeMember("InitializeFromRequest", BindingFlags.InvokeMethod, null, x509Enrollment,
typeValue); typeValue);
if (isRoot) if (signingCertificate == null)
{ {
typeValue[0] = fullSubject; typeValue[0] = fullSubject;
typeX509Enrollment.InvokeMember("CertificateFriendlyName", BindingFlags.PutDispProperty, null, typeX509Enrollment.InvokeMember("CertificateFriendlyName", BindingFlags.PutDispProperty, null,
...@@ -296,7 +289,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -296,7 +289,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
typeX509Enrollment.InvokeMember("InstallResponse", BindingFlags.InvokeMethod, null, x509Enrollment, typeX509Enrollment.InvokeMember("InstallResponse", BindingFlags.InvokeMethod, null, x509Enrollment,
typeValue); typeValue);
typeValue = new object[] { null, 0, 1 }; typeValue = new object[] { null!, 0, 1 };
string empty = (string)typeX509Enrollment.InvokeMember("CreatePFX", BindingFlags.InvokeMethod, null, string empty = (string)typeX509Enrollment.InvokeMember("CreatePFX", BindingFlags.InvokeMethod, null,
x509Enrollment, typeValue); x509Enrollment, typeValue);
......
...@@ -52,23 +52,38 @@ namespace Titanium.Web.Proxy.Network ...@@ -52,23 +52,38 @@ namespace Titanium.Web.Proxy.Network
/// Useful to prevent multiple threads working on same certificate generation /// Useful to prevent multiple threads working on same certificate generation
/// when burst certificate generation requests happen for same certificate. /// when burst certificate generation requests happen for same certificate.
/// </summary> /// </summary>
private readonly ConcurrentDictionary<string, Task<X509Certificate2>> pendingCertificateCreationTasks private readonly ConcurrentDictionary<string, Task<X509Certificate2?>> pendingCertificateCreationTasks
= new ConcurrentDictionary<string, Task<X509Certificate2>>(); = new ConcurrentDictionary<string, Task<X509Certificate2?>>();
private readonly CancellationTokenSource clearCertificatesTokenSource private readonly CancellationTokenSource clearCertificatesTokenSource
= new CancellationTokenSource(); = new CancellationTokenSource();
private readonly object rootCertCreationLock = new object(); private readonly object rootCertCreationLock = new object();
private ICertificateMaker certEngine; private ICertificateMaker? certEngineValue;
private ICertificateMaker certEngine
{
get
{
if (certEngineValue == null)
{
certEngineValue = engine == CertificateEngine.BouncyCastle
? (ICertificateMaker)new BCCertificateMaker(ExceptionFunc)
: new WinCertificateMaker(ExceptionFunc);
}
return certEngineValue;
}
}
private CertificateEngine engine; private CertificateEngine engine;
private string issuer; private string? issuer;
private X509Certificate2 rootCertificate; private X509Certificate2? rootCertificate;
private string rootCertificateName; private string? rootCertificateName;
private ICertificateCache certificateCache = new DefaultCertificateDiskCache(); private ICertificateCache certificateCache = new DefaultCertificateDiskCache();
...@@ -87,7 +102,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -87,7 +102,7 @@ namespace Titanium.Web.Proxy.Network
/// prompting for UAC if required? /// prompting for UAC if required?
/// </param> /// </param>
/// <param name="exceptionFunc"></param> /// <param name="exceptionFunc"></param>
internal CertificateManager(string rootCertificateName, string rootCertificateIssuerName, internal CertificateManager(string? rootCertificateName, string? rootCertificateIssuerName,
bool userTrustRootCertificate, bool machineTrustRootCertificate, bool trustRootCertificateAsAdmin, bool userTrustRootCertificate, bool machineTrustRootCertificate, bool trustRootCertificateAsAdmin,
ExceptionHandler exceptionFunc) ExceptionHandler exceptionFunc)
{ {
...@@ -156,16 +171,9 @@ namespace Titanium.Web.Proxy.Network ...@@ -156,16 +171,9 @@ namespace Titanium.Web.Proxy.Network
if (value != engine) if (value != engine)
{ {
certEngine = null; certEngineValue = null!;
engine = value; engine = value;
} }
if (certEngine == null)
{
certEngine = engine == CertificateEngine.BouncyCastle
? (ICertificateMaker)new BCCertificateMaker(ExceptionFunc)
: new WinCertificateMaker(ExceptionFunc);
}
} }
} }
...@@ -210,7 +218,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -210,7 +218,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary> /// <summary>
/// The root certificate. /// The root certificate.
/// </summary> /// </summary>
public X509Certificate2 RootCertificate public X509Certificate2? RootCertificate
{ {
get => rootCertificate; get => rootCertificate;
set set
...@@ -268,6 +276,11 @@ namespace Titanium.Web.Proxy.Network ...@@ -268,6 +276,11 @@ namespace Titanium.Web.Proxy.Network
/// <returns></returns> /// <returns></returns>
private bool rootCertificateInstalled(StoreLocation storeLocation) private bool rootCertificateInstalled(StoreLocation storeLocation)
{ {
if (RootCertificate == null)
{
throw new Exception("Root certificate is null.");
}
string value = $"{RootCertificate.Issuer}"; string value = $"{RootCertificate.Issuer}";
return findCertificates(StoreName.Root, storeLocation, value).Count > 0 return findCertificates(StoreName.Root, storeLocation, value).Count > 0
&& (CertificateEngine != CertificateEngine.DefaultWindows && (CertificateEngine != CertificateEngine.DefaultWindows
...@@ -298,8 +311,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -298,8 +311,7 @@ namespace Titanium.Web.Proxy.Network
{ {
if (RootCertificate == null) if (RootCertificate == null)
{ {
ExceptionFunc(new Exception("Could not install certificate as it is null or empty.")); throw new Exception("Could not install certificate as it is null or empty.");
return;
} }
var x509Store = new X509Store(storeName, storeLocation); var x509Store = new X509Store(storeName, storeLocation);
...@@ -330,8 +342,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -330,8 +342,7 @@ namespace Titanium.Web.Proxy.Network
/// <param name="storeName"></param> /// <param name="storeName"></param>
/// <param name="storeLocation"></param> /// <param name="storeLocation"></param>
/// <param name="certificate"></param> /// <param name="certificate"></param>
private void uninstallCertificate(StoreName storeName, StoreLocation storeLocation, private void uninstallCertificate(StoreName storeName, StoreLocation storeLocation, X509Certificate2? certificate)
X509Certificate2 certificate)
{ {
if (certificate == null) if (certificate == null)
{ {
...@@ -361,12 +372,19 @@ namespace Titanium.Web.Proxy.Network ...@@ -361,12 +372,19 @@ namespace Titanium.Web.Proxy.Network
private X509Certificate2 makeCertificate(string certificateName, bool isRootCertificate) private X509Certificate2 makeCertificate(string certificateName, bool isRootCertificate)
{ {
//if (isRoot != (null == signingCertificate))
//{
// throw new ArgumentException(
// "You must specify a Signing Certificate if and only if you are not creating a root.",
// nameof(signingCertificate));
//}
if (!isRootCertificate && RootCertificate == null) if (!isRootCertificate && RootCertificate == null)
{ {
CreateRootCertificate(); CreateRootCertificate();
} }
var certificate = certEngine.MakeCertificate(certificateName, isRootCertificate, RootCertificate); var certificate = certEngine.MakeCertificate(certificateName, isRootCertificate ? null : RootCertificate);
if (CertificateEngine == CertificateEngine.DefaultWindows) if (CertificateEngine == CertificateEngine.DefaultWindows)
{ {
...@@ -382,9 +400,9 @@ namespace Titanium.Web.Proxy.Network ...@@ -382,9 +400,9 @@ namespace Titanium.Web.Proxy.Network
/// <param name="certificateName"></param> /// <param name="certificateName"></param>
/// <param name="isRootCertificate"></param> /// <param name="isRootCertificate"></param>
/// <returns></returns> /// <returns></returns>
internal X509Certificate2 CreateCertificate(string certificateName, bool isRootCertificate) internal X509Certificate2? CreateCertificate(string certificateName, bool isRootCertificate)
{ {
X509Certificate2 certificate; X509Certificate2? certificate;
try try
{ {
if (!isRootCertificate && SaveFakeCertificates) if (!isRootCertificate && SaveFakeCertificates)
...@@ -436,7 +454,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -436,7 +454,7 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
/// <param name="certificateName"></param> /// <param name="certificateName"></param>
/// <returns></returns> /// <returns></returns>
public async Task<X509Certificate2> CreateServerCertificate(string certificateName) public async Task<X509Certificate2?> CreateServerCertificate(string certificateName)
{ {
// check in cache first // check in cache first
if (cachedCertificates.TryGetValue(certificateName, out var cached)) if (cachedCertificates.TryGetValue(certificateName, out var cached))
...@@ -458,10 +476,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -458,10 +476,7 @@ namespace Titanium.Web.Proxy.Network
var result = CreateCertificate(certificateName, false); var result = CreateCertificate(certificateName, false);
if (result != null) if (result != null)
{ {
cachedCertificates.TryAdd(certificateName, new CachedCertificate cachedCertificates.TryAdd(certificateName, new CachedCertificate(result));
{
Certificate = result
});
} }
return result; return result;
...@@ -589,7 +604,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -589,7 +604,7 @@ namespace Titanium.Web.Proxy.Network
/// Loads root certificate from current executing assembly location with expected name rootCert.pfx. /// Loads root certificate from current executing assembly location with expected name rootCert.pfx.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public X509Certificate2 LoadRootCertificate() public X509Certificate2? LoadRootCertificate()
{ {
try try
{ {
...@@ -671,7 +686,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -671,7 +686,7 @@ namespace Titanium.Web.Proxy.Network
installCertificate(StoreName.My, StoreLocation.CurrentUser); installCertificate(StoreName.My, StoreLocation.CurrentUser);
string pfxFileName = Path.GetTempFileName(); string pfxFileName = Path.GetTempFileName();
File.WriteAllBytes(pfxFileName, RootCertificate.Export(X509ContentType.Pkcs12, PfxPassword)); File.WriteAllBytes(pfxFileName, RootCertificate!.Export(X509ContentType.Pkcs12, PfxPassword));
// currentUser\Root, currentMachine\Personal & currentMachine\Root // currentUser\Root, currentMachine\Personal & currentMachine\Root
var info = new ProcessStartInfo var info = new ProcessStartInfo
......
...@@ -19,8 +19,8 @@ namespace Titanium.Web.Proxy.Network ...@@ -19,8 +19,8 @@ namespace Titanium.Web.Proxy.Network
private readonly FileStream fileStreamSent; private readonly FileStream fileStreamSent;
public DebugCustomBufferedStream(Guid connectionId, string type, Stream baseStream, IBufferPool bufferPool, int bufferSize, bool leaveOpen = false) public DebugCustomBufferedStream(Guid connectionId, string type, Stream baseStream, IBufferPool bufferPool, bool leaveOpen = false)
: base(baseStream, bufferPool, bufferSize, leaveOpen) : base(baseStream, bufferPool, leaveOpen)
{ {
Counter = Interlocked.Increment(ref counter); Counter = Interlocked.Increment(ref counter);
fileStreamSent = new FileStream(Path.Combine(basePath, $"{connectionId}_{type}_{Counter}_sent.dat"), FileMode.Create); fileStreamSent = new FileStream(Path.Combine(basePath, $"{connectionId}_{type}_{Counter}_sent.dat"), FileMode.Create);
......
...@@ -11,10 +11,10 @@ namespace Titanium.Web.Proxy.Network ...@@ -11,10 +11,10 @@ namespace Titanium.Web.Proxy.Network
private const string defaultCertificateDirectoryName = "crts"; private const string defaultCertificateDirectoryName = "crts";
private const string defaultCertificateFileExtension = ".pfx"; private const string defaultCertificateFileExtension = ".pfx";
private const string defaultRootCertificateFileName = "rootCert" + defaultCertificateFileExtension; private const string defaultRootCertificateFileName = "rootCert" + defaultCertificateFileExtension;
private string rootCertificatePath; private string? rootCertificatePath;
private string certificatePath; private string? certificatePath;
public X509Certificate2 LoadRootCertificate(string pathOrName, string password, X509KeyStorageFlags storageFlags) public X509Certificate2? LoadRootCertificate(string pathOrName, string password, X509KeyStorageFlags storageFlags)
{ {
string path = getRootCertificatePath(pathOrName); string path = getRootCertificatePath(pathOrName);
return loadCertificate(path, password, storageFlags); return loadCertificate(path, password, storageFlags);
...@@ -28,7 +28,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -28,7 +28,7 @@ namespace Titanium.Web.Proxy.Network
} }
/// <inheritdoc /> /// <inheritdoc />
public X509Certificate2 LoadCertificate(string subjectName, X509KeyStorageFlags storageFlags) public X509Certificate2? LoadCertificate(string subjectName, X509KeyStorageFlags storageFlags)
{ {
string path = Path.Combine(getCertificatePath(), subjectName + defaultCertificateFileExtension); string path = Path.Combine(getCertificatePath(), subjectName + defaultCertificateFileExtension);
return loadCertificate(path, string.Empty, storageFlags); return loadCertificate(path, string.Empty, storageFlags);
...@@ -56,7 +56,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -56,7 +56,7 @@ namespace Titanium.Web.Proxy.Network
certificatePath = null; certificatePath = null;
} }
private X509Certificate2 loadCertificate(string path, string password, X509KeyStorageFlags storageFlags) private X509Certificate2? loadCertificate(string path, string password, X509KeyStorageFlags storageFlags)
{ {
byte[] exported; byte[] exported;
......
...@@ -7,7 +7,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -7,7 +7,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary> /// <summary>
/// Loads the root certificate from the storage. /// Loads the root certificate from the storage.
/// </summary> /// </summary>
X509Certificate2 LoadRootCertificate(string pathOrName, string password, X509KeyStorageFlags storageFlags); X509Certificate2? LoadRootCertificate(string pathOrName, string password, X509KeyStorageFlags storageFlags);
/// <summary> /// <summary>
/// Saves the root certificate to the storage. /// Saves the root certificate to the storage.
...@@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -17,7 +17,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary> /// <summary>
/// Loads certificate from the storage. Returns true if certificate does not exist. /// Loads certificate from the storage. Returns true if certificate does not exist.
/// </summary> /// </summary>
X509Certificate2 LoadCertificate(string subjectName, X509KeyStorageFlags storageFlags); X509Certificate2? LoadCertificate(string subjectName, X509KeyStorageFlags storageFlags);
/// <summary> /// <summary>
/// Stores certificate into the storage. /// Stores certificate into the storage.
......
...@@ -9,19 +9,26 @@ namespace Titanium.Web.Proxy.Network ...@@ -9,19 +9,26 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
internal class ProxyClient internal class ProxyClient
{ {
public ProxyClient(TcpClientConnection connection, CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter)
{
Connection = connection;
ClientStream = clientStream;
ClientStreamWriter = clientStreamWriter;
}
/// <summary> /// <summary>
/// TcpClient connection used to communicate with client /// TcpClient connection used to communicate with client
/// </summary> /// </summary>
internal TcpClientConnection Connection { get; set; } internal TcpClientConnection Connection { get; }
/// <summary> /// <summary>
/// Holds the stream to client /// Holds the stream to client
/// </summary> /// </summary>
internal CustomBufferedStream ClientStream { get; set; } internal CustomBufferedStream ClientStream { get; }
/// <summary> /// <summary>
/// Used to write line by line to client /// Used to write line by line to client
/// </summary> /// </summary>
internal HttpResponseWriter ClientStreamWriter { get; set; } internal HttpResponseWriter ClientStreamWriter { get; }
} }
} }
...@@ -9,7 +9,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -9,7 +9,7 @@ namespace Titanium.Web.Proxy.Network
private readonly int retries; private readonly int retries;
private readonly TcpConnectionFactory tcpConnectionFactory; private readonly TcpConnectionFactory tcpConnectionFactory;
private TcpServerConnection currentConnection; private TcpServerConnection? currentConnection;
internal RetryPolicy(int retries, TcpConnectionFactory tcpConnectionFactory) internal RetryPolicy(int retries, TcpConnectionFactory tcpConnectionFactory)
{ {
...@@ -25,11 +25,11 @@ namespace Titanium.Web.Proxy.Network ...@@ -25,11 +25,11 @@ namespace Titanium.Web.Proxy.Network
/// <param name="initialConnection">Initial Tcp connection to use.</param> /// <param name="initialConnection">Initial Tcp connection to use.</param>
/// <returns>Returns the latest connection used and the latest exception if any.</returns> /// <returns>Returns the latest connection used and the latest exception if any.</returns>
internal async Task<RetryResult> ExecuteAsync(Func<TcpServerConnection, Task<bool>> action, internal async Task<RetryResult> ExecuteAsync(Func<TcpServerConnection, Task<bool>> action,
Func<Task<TcpServerConnection>> generator, TcpServerConnection initialConnection) Func<Task<TcpServerConnection>> generator, TcpServerConnection? initialConnection)
{ {
currentConnection = initialConnection; currentConnection = initialConnection;
bool @continue = true; bool @continue = true;
Exception exception = null; Exception? exception = null;
var attempts = retries; var attempts = retries;
...@@ -79,12 +79,13 @@ namespace Titanium.Web.Proxy.Network ...@@ -79,12 +79,13 @@ namespace Titanium.Web.Proxy.Network
internal class RetryResult internal class RetryResult
{ {
internal bool IsSuccess => Exception == null; internal TcpServerConnection? LatestConnection { get; }
internal TcpServerConnection LatestConnection { get; }
internal Exception Exception { get; } internal Exception? Exception { get; }
internal bool Continue { get; } internal bool Continue { get; }
internal RetryResult(TcpServerConnection lastConnection, Exception exception, bool @continue) internal RetryResult(TcpServerConnection? lastConnection, Exception? exception, bool @continue)
{ {
LatestConnection = lastConnection; LatestConnection = lastConnection;
Exception = exception; Exception = exception;
......
using System; using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
#if NETCOREAPP2_1
using System.Net.Security; using System.Net.Security;
#endif
using System.Net.Sockets; using System.Net.Sockets;
using System.Security.Authentication; using System.Security.Authentication;
using System.Threading.Tasks; using System.Threading.Tasks;
...@@ -60,8 +58,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -60,8 +58,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
// If client is localhost get the process id // If client is localhost get the process id
if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address)) if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
{ {
var ipVersion = endPoint.IpV6Enabled ? IpVersion.Ipv6 : IpVersion.Ipv4; processId = TcpHelper.GetProcessIdByLocalPort(endPoint.IpAddress.AddressFamily, remoteEndPoint.Port);
processId = TcpHelper.GetProcessIdByLocalPort(ipVersion, remoteEndPoint.Port);
} }
else else
{ {
......
...@@ -11,6 +11,7 @@ using System.Text; ...@@ -11,6 +11,7 @@ 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;
...@@ -47,28 +48,53 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -47,28 +48,53 @@ namespace Titanium.Web.Proxy.Network.Tcp
internal ProxyServer Server { get; } internal ProxyServer Server { get; }
internal string GetConnectionCacheKey(string remoteHostName, int remotePort, internal string GetConnectionCacheKey(string remoteHostName, int remotePort,
bool isHttps, List<SslApplicationProtocol> applicationProtocols, bool isHttps, List<SslApplicationProtocol>? applicationProtocols,
IPEndPoint upStreamEndPoint, ExternalProxy externalProxy) IPEndPoint? upStreamEndPoint, ExternalProxy? externalProxy)
{ {
// http version is ignored since its an application level decision b/w HTTP 1.0/1.1 // http version is ignored since its an application level decision b/w HTTP 1.0/1.1
// also when doing connect request MS Edge browser sends http 1.0 but uses 1.1 after server sends 1.1 its response. // also when doing connect request MS Edge browser sends http 1.0 but uses 1.1 after server sends 1.1 its response.
// That can create cache miss for same server connection unnecessarily especially when prefetching with Connect. // That can create cache miss for same server connection unnecessarily especially when prefetching with Connect.
// http version 2 is separated using applicationProtocols below. // http version 2 is separated using applicationProtocols below.
var cacheKeyBuilder = new StringBuilder($"{remoteHostName}-{remotePort}-" + var cacheKeyBuilder = new StringBuilder();
// when creating Tcp client isConnect won't matter cacheKeyBuilder.Append(remoteHostName);
$"{isHttps}-"); cacheKeyBuilder.Append("-");
cacheKeyBuilder.Append(remotePort);
cacheKeyBuilder.Append("-");
// when creating Tcp client isConnect won't matter
cacheKeyBuilder.Append(isHttps);
if (applicationProtocols != null) if (applicationProtocols != null)
{ {
foreach (var protocol in applicationProtocols.OrderBy(x => x)) foreach (var protocol in applicationProtocols.OrderBy(x => x))
{ {
cacheKeyBuilder.Append($"{protocol}-"); cacheKeyBuilder.Append("-");
cacheKeyBuilder.Append(protocol);
} }
} }
cacheKeyBuilder.Append(upStreamEndPoint != null if (upStreamEndPoint != null)
? $"{upStreamEndPoint.Address}-{upStreamEndPoint.Port}-" {
: string.Empty); cacheKeyBuilder.Append("-");
cacheKeyBuilder.Append(externalProxy != null ? $"{externalProxy.GetCacheKey()}-" : string.Empty); cacheKeyBuilder.Append(upStreamEndPoint.Address);
cacheKeyBuilder.Append("-");
cacheKeyBuilder.Append(upStreamEndPoint.Port);
}
if (externalProxy != null)
{
cacheKeyBuilder.Append("-");
cacheKeyBuilder.Append(externalProxy.HostName);
cacheKeyBuilder.Append("-");
cacheKeyBuilder.Append(externalProxy.Port);
if (externalProxy.UseDefaultCredentials)
{
cacheKeyBuilder.Append("-");
cacheKeyBuilder.Append(externalProxy.UserName);
cacheKeyBuilder.Append("-");
cacheKeyBuilder.Append(externalProxy.Password);
}
}
return cacheKeyBuilder.ToString(); return cacheKeyBuilder.ToString();
} }
...@@ -76,19 +102,20 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -76,19 +102,20 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary> /// <summary>
/// Gets the connection cache key. /// Gets the connection cache key.
/// </summary> /// </summary>
/// <param name="server">The server.</param>
/// <param name="session">The session event arguments.</param> /// <param name="session">The session event arguments.</param>
/// <param name="applicationProtocol"></param> /// <param name="applicationProtocol">The application protocol.</param>
/// <returns></returns> /// <returns></returns>
internal async Task<string> GetConnectionCacheKey(ProxyServer server, SessionEventArgsBase session, internal async Task<string> GetConnectionCacheKey(ProxyServer server, SessionEventArgsBase session,
SslApplicationProtocol applicationProtocol) SslApplicationProtocol applicationProtocol)
{ {
List<SslApplicationProtocol> applicationProtocols = null; List<SslApplicationProtocol>? applicationProtocols = null;
if (applicationProtocol != default) if (applicationProtocol != default)
{ {
applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol }; applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol };
} }
ExternalProxy customUpStreamProxy = null; ExternalProxy? customUpStreamProxy = null;
bool isHttps = session.IsHttps; bool isHttps = session.IsHttps;
if (server.GetCustomUpStreamProxyFunc != null) if (server.GetCustomUpStreamProxyFunc != null)
...@@ -98,9 +125,10 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -98,9 +125,10 @@ namespace Titanium.Web.Proxy.Network.Tcp
session.CustomUpStreamProxyUsed = customUpStreamProxy; session.CustomUpStreamProxyUsed = customUpStreamProxy;
var uri = session.HttpClient.Request.RequestUri;
return GetConnectionCacheKey( return GetConnectionCacheKey(
session.HttpClient.Request.RequestUri.Host, uri.Host,
session.HttpClient.Request.RequestUri.Port, uri.Port,
isHttps, applicationProtocols, isHttps, applicationProtocols,
session.HttpClient.UpStreamEndPoint ?? server.UpStreamEndPoint, session.HttpClient.UpStreamEndPoint ?? server.UpStreamEndPoint,
customUpStreamProxy ?? (isHttps ? server.UpStreamHttpsProxy : server.UpStreamHttpProxy)); customUpStreamProxy ?? (isHttps ? server.UpStreamHttpsProxy : server.UpStreamHttpProxy));
...@@ -120,7 +148,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -120,7 +148,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
internal Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase session, bool isConnect, internal Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase session, bool isConnect,
SslApplicationProtocol applicationProtocol, bool noCache, CancellationToken cancellationToken) SslApplicationProtocol applicationProtocol, bool noCache, CancellationToken cancellationToken)
{ {
List<SslApplicationProtocol> applicationProtocols = null; List<SslApplicationProtocol>? applicationProtocols = null;
if (applicationProtocol != default) if (applicationProtocol != default)
{ {
applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol }; applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol };
...@@ -140,9 +168,9 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -140,9 +168,9 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <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 server, SessionEventArgsBase session, bool isConnect,
List<SslApplicationProtocol> applicationProtocols, bool noCache, CancellationToken cancellationToken) List<SslApplicationProtocol>? applicationProtocols, bool noCache, CancellationToken cancellationToken)
{ {
ExternalProxy customUpStreamProxy = null; ExternalProxy? customUpStreamProxy = null;
bool isHttps = session.IsHttps; bool isHttps = session.IsHttps;
if (server.GetCustomUpStreamProxyFunc != null) if (server.GetCustomUpStreamProxyFunc != null)
...@@ -152,9 +180,10 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -152,9 +180,10 @@ namespace Titanium.Web.Proxy.Network.Tcp
session.CustomUpStreamProxyUsed = customUpStreamProxy; session.CustomUpStreamProxyUsed = customUpStreamProxy;
var uri = session.HttpClient.Request.RequestUri;
return await GetServerConnection( return await GetServerConnection(
session.HttpClient.Request.RequestUri.Host, uri.Host,
session.HttpClient.Request.RequestUri.Port, uri.Port,
session.HttpClient.Request.HttpVersion, session.HttpClient.Request.HttpVersion,
isHttps, applicationProtocols, isConnect, isHttps, applicationProtocols, isConnect,
server, session, session.HttpClient.UpStreamEndPoint ?? server.UpStreamEndPoint, server, session, session.HttpClient.UpStreamEndPoint ?? server.UpStreamEndPoint,
...@@ -178,11 +207,11 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -178,11 +207,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <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(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, ExternalProxy externalProxy, ProxyServer proxyServer, SessionEventArgsBase? session, IPEndPoint? upStreamEndPoint, ExternalProxy? externalProxy,
bool noCache, CancellationToken cancellationToken) bool noCache, CancellationToken cancellationToken)
{ {
var sslProtocol = session.ProxyClient.Connection.SslProtocol; var sslProtocol = session?.ProxyClient.Connection.SslProtocol ?? SslProtocols.None;
var cacheKey = GetConnectionCacheKey(remoteHostName, remotePort, var cacheKey = GetConnectionCacheKey(remoteHostName, remotePort,
isHttps, applicationProtocols, upStreamEndPoint, externalProxy); isHttps, applicationProtocols, upStreamEndPoint, externalProxy);
...@@ -209,9 +238,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -209,9 +238,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, cancellationToken); applicationProtocols, isConnect, proxyServer, session, upStreamEndPoint, externalProxy, cacheKey, cancellationToken);
connection.CacheKey = cacheKey;
return connection; return connection;
} }
...@@ -230,11 +257,12 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -230,11 +257,12 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="session">The http session.</param> /// <param name="session">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="cancellationToken">The cancellation token for this async task.</param> /// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns> /// <returns></returns>
private async Task<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, ExternalProxy externalProxy, ProxyServer proxyServer, SessionEventArgsBase? session, IPEndPoint? upStreamEndPoint, ExternalProxy? 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.
...@@ -268,8 +296,8 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -268,8 +296,8 @@ namespace Titanium.Web.Proxy.Network.Tcp
} }
} }
TcpClient tcpClient = null; TcpClient? tcpClient = null;
CustomBufferedStream stream = null; CustomBufferedStream? stream = null;
SslApplicationProtocol negotiatedApplicationProtocol = default; SslApplicationProtocol negotiatedApplicationProtocol = default;
...@@ -279,8 +307,8 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -279,8 +307,8 @@ namespace Titanium.Web.Proxy.Network.Tcp
retry: retry:
try try
{ {
var hostname = useUpstreamProxy ? externalProxy.HostName : remoteHostName; string hostname = useUpstreamProxy ? externalProxy!.HostName : remoteHostName;
var port = useUpstreamProxy ? externalProxy.Port : remotePort; int port = useUpstreamProxy ? externalProxy!.Port : remotePort;
var ipAddresses = await Dns.GetHostAddressesAsync(hostname); var ipAddresses = await Dns.GetHostAddressesAsync(hostname);
if (ipAddresses == null || ipAddresses.Length == 0) if (ipAddresses == null || ipAddresses.Length == 0)
...@@ -293,6 +321,8 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -293,6 +321,8 @@ namespace Titanium.Web.Proxy.Network.Tcp
session.TimeLine["Dns Resolved"] = DateTime.Now; session.TimeLine["Dns Resolved"] = DateTime.Now;
} }
Array.Sort(ipAddresses, (x, y) => x.AddressFamily.CompareTo(y.AddressFamily));
for (int i = 0; i < ipAddresses.Length; i++) for (int i = 0; i < ipAddresses.Length; i++)
{ {
try try
...@@ -312,13 +342,12 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -312,13 +342,12 @@ namespace Titanium.Web.Proxy.Network.Tcp
tcpClient.SendTimeout = proxyServer.ConnectionTimeOutSeconds * 1000; tcpClient.SendTimeout = proxyServer.ConnectionTimeOutSeconds * 1000;
tcpClient.LingerState = new LingerOption(true, proxyServer.TcpTimeWaitSeconds); tcpClient.LingerState = new LingerOption(true, proxyServer.TcpTimeWaitSeconds);
// linux has a bug with socket reuse in .net core. if (proxyServer.ReuseSocket && RunTime.IsSocketReuseAvailable)
if (proxyServer.ReuseSocket && RunTime.IsWindows)
{ {
tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
} }
await tcpClient.ConnectAsync(ipAddresses[i], port); await tcpClient.ConnectAsync(ipAddress, port);
break; break;
} }
catch (Exception e) catch (Exception e)
...@@ -338,22 +367,24 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -338,22 +367,24 @@ namespace Titanium.Web.Proxy.Network.Tcp
session.TimeLine["Connection Established"] = DateTime.Now; session.TimeLine["Connection Established"] = DateTime.Now;
} }
await proxyServer.InvokeConnectionCreateEvent(tcpClient, false); await proxyServer.InvokeConnectionCreateEvent(tcpClient!, false);
stream = new CustomBufferedStream(tcpClient.GetStream(), proxyServer.BufferPool, proxyServer.BufferSize); stream = new CustomBufferedStream(tcpClient!.GetStream(), proxyServer.BufferPool);
if (useUpstreamProxy && (isConnect || isHttps)) if (useUpstreamProxy && (isConnect || isHttps))
{ {
var writer = new HttpRequestWriter(stream, proxyServer.BufferPool, proxyServer.BufferSize); var writer = new HttpRequestWriter(stream, proxyServer.BufferPool);
var connectRequest = new ConnectRequest string authority = $"{remoteHostName}:{remotePort}";
var connectRequest = new ConnectRequest(authority)
{ {
OriginalUrl = $"{remoteHostName}:{remotePort}", IsHttps = isHttps,
OriginalUrlData = HttpHeader.Encoding.GetBytes(authority),
HttpVersion = httpVersion HttpVersion = httpVersion
}; };
connectRequest.Headers.AddHeader(KnownHeaders.Connection, KnownHeaders.ConnectionKeepAlive); connectRequest.Headers.AddHeader(KnownHeaders.Connection, KnownHeaders.ConnectionKeepAlive);
if (!string.IsNullOrEmpty(externalProxy.UserName) && externalProxy.Password != null) if (!string.IsNullOrEmpty(externalProxy!.UserName) && externalProxy.Password != null)
{ {
connectRequest.Headers.AddHeader(HttpHeader.ProxyConnectionKeepAlive); connectRequest.Headers.AddHeader(HttpHeader.ProxyConnectionKeepAlive);
connectRequest.Headers.AddHeader( connectRequest.Headers.AddHeader(
...@@ -362,7 +393,8 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -362,7 +393,8 @@ namespace Titanium.Web.Proxy.Network.Tcp
await writer.WriteRequestAsync(connectRequest, cancellationToken: cancellationToken); await writer.WriteRequestAsync(connectRequest, cancellationToken: cancellationToken);
string httpStatus = await stream.ReadLineAsync(cancellationToken); string httpStatus = await stream.ReadLineAsync(cancellationToken)
?? throw new ServerConnectionException("Server connection was closed.");
Response.ParseResponseLine(httpStatus, out _, out int statusCode, out string statusDescription); Response.ParseResponseLine(httpStatus, out _, out int statusCode, out string statusDescription);
...@@ -379,18 +411,18 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -379,18 +411,18 @@ namespace Titanium.Web.Proxy.Network.Tcp
{ {
var sslStream = new SslStream(stream, false, proxyServer.ValidateServerCertificate, var sslStream = new SslStream(stream, false, proxyServer.ValidateServerCertificate,
proxyServer.SelectClientCertificate); proxyServer.SelectClientCertificate);
stream = new CustomBufferedStream(sslStream, proxyServer.BufferPool, proxyServer.BufferSize); stream = new CustomBufferedStream(sslStream, proxyServer.BufferPool);
var options = new SslClientAuthenticationOptions var options = new SslClientAuthenticationOptions
{ {
ApplicationProtocols = applicationProtocols, ApplicationProtocols = applicationProtocols,
TargetHost = remoteHostName, TargetHost = remoteHostName,
ClientCertificates = null, ClientCertificates = null!,
EnabledSslProtocols = enabledSslProtocols, EnabledSslProtocols = enabledSslProtocols,
CertificateRevocationCheckMode = proxyServer.CheckCertificateRevocation CertificateRevocationCheckMode = proxyServer.CheckCertificateRevocation
}; };
await sslStream.AuthenticateAsClientAsync(options, cancellationToken); await sslStream.AuthenticateAsClientAsync(options, cancellationToken);
#if NETCOREAPP2_1 #if NETSTANDARD2_1
negotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol; negotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol;
#endif #endif
...@@ -414,19 +446,8 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -414,19 +446,8 @@ namespace Titanium.Web.Proxy.Network.Tcp
throw; throw;
} }
return new TcpServerConnection(proxyServer, tcpClient) return new TcpServerConnection(proxyServer, tcpClient, stream, remoteHostName, remotePort, isHttps,
{ negotiatedApplicationProtocol, httpVersion, useUpstreamProxy, externalProxy, upStreamEndPoint, cacheKey);
UpStreamProxy = externalProxy,
UpStreamEndPoint = upStreamEndPoint,
HostName = remoteHostName,
Port = remotePort,
IsHttps = isHttps,
NegotiatedApplicationProtocol = negotiatedApplicationProtocol,
UseUpstreamProxy = useUpstreamProxy,
StreamWriter = new HttpRequestWriter(stream, proxyServer.BufferPool, proxyServer.BufferSize),
Stream = stream,
Version = httpVersion
};
} }
...@@ -437,11 +458,6 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -437,11 +458,6 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="close">Should we just close the connection instead of reusing?</param> /// <param name="close">Should we just close the connection instead of reusing?</param>
internal async Task Release(TcpServerConnection connection, bool close = false) internal async Task Release(TcpServerConnection connection, bool close = false)
{ {
if (connection == null)
{
return;
}
if (close || connection.IsWinAuthenticated || !Server.EnableConnectionPool || connection.IsClosed) if (close || connection.IsWinAuthenticated || !Server.EnableConnectionPool || connection.IsClosed)
{ {
disposalBag.Add(connection); disposalBag.Add(connection);
...@@ -484,11 +500,11 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -484,11 +500,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
} }
} }
internal async Task Release(Task<TcpServerConnection> connectionCreateTask, bool closeServerConnection) internal async Task Release(Task<TcpServerConnection>? connectionCreateTask, bool closeServerConnection)
{ {
if (connectionCreateTask != null) if (connectionCreateTask != null)
{ {
TcpServerConnection connection = null; TcpServerConnection? connection = null;
try try
{ {
connection = await connectionCreateTask; connection = await connectionCreateTask;
...@@ -496,7 +512,10 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -496,7 +512,10 @@ namespace Titanium.Web.Proxy.Network.Tcp
catch { } catch { }
finally finally
{ {
await Release(connection, closeServerConnection); if (connection != null)
{
await Release(connection, closeServerConnection);
}
} }
} }
} }
......
using System; using System;
using System.Net; using System.Net;
#if NETCOREAPP2_1
using System.Net.Security; using System.Net.Security;
#endif
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
...@@ -17,19 +15,33 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -17,19 +15,33 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary> /// </summary>
internal class TcpServerConnection : IDisposable internal class TcpServerConnection : IDisposable
{ {
internal TcpServerConnection(ProxyServer proxyServer, TcpClient tcpClient) internal TcpServerConnection(ProxyServer proxyServer, TcpClient tcpClient, CustomBufferedStream stream,
string hostName, int port, bool isHttps, SslApplicationProtocol negotiatedApplicationProtocol,
Version version, bool useUpstreamProxy, ExternalProxy? upStreamProxy, IPEndPoint? upStreamEndPoint, string cacheKey)
{ {
this.tcpClient = tcpClient; this.tcpClient = tcpClient;
LastAccess = DateTime.Now; LastAccess = DateTime.Now;
this.proxyServer = proxyServer; this.proxyServer = proxyServer;
this.proxyServer.UpdateServerConnectionCount(true); this.proxyServer.UpdateServerConnectionCount(true);
StreamWriter = new HttpRequestWriter(stream, proxyServer.BufferPool);
Stream = stream;
HostName = hostName;
Port = port;
IsHttps = isHttps;
NegotiatedApplicationProtocol = negotiatedApplicationProtocol;
Version = version;
UseUpstreamProxy = useUpstreamProxy;
UpStreamProxy = upStreamProxy;
UpStreamEndPoint = upStreamEndPoint;
CacheKey = cacheKey;
} }
private ProxyServer proxyServer { get; } private ProxyServer proxyServer { get; }
internal bool IsClosed => Stream.IsClosed; internal bool IsClosed => Stream.IsClosed;
internal ExternalProxy UpStreamProxy { get; set; } internal ExternalProxy? UpStreamProxy { get; set; }
internal string HostName { get; set; } internal string HostName { get; set; }
...@@ -44,12 +56,12 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -44,12 +56,12 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary> /// <summary>
/// Local NIC via connection is made /// Local NIC via connection is made
/// </summary> /// </summary>
internal IPEndPoint UpStreamEndPoint { get; set; } internal IPEndPoint? UpStreamEndPoint { get; set; }
/// <summary> /// <summary>
/// Http version /// Http version
/// </summary> /// </summary>
internal Version Version { get; set; } internal Version Version { get; set; } = HttpHeader.VersionUnknown;
private readonly TcpClient tcpClient; private readonly TcpClient tcpClient;
...@@ -61,12 +73,12 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -61,12 +73,12 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary> /// <summary>
/// Used to write lines to server /// Used to write lines to server
/// </summary> /// </summary>
internal HttpRequestWriter StreamWriter { get; set; } internal HttpRequestWriter StreamWriter { get; }
/// <summary> /// <summary>
/// Server stream /// Server stream
/// </summary> /// </summary>
internal CustomBufferedStream Stream { get; set; } internal CustomBufferedStream Stream { get; }
/// <summary> /// <summary>
/// Last time this connection was used /// Last time this connection was used
......
...@@ -224,9 +224,9 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security ...@@ -224,9 +224,9 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
} }
} }
internal byte[] GetBytes() internal byte[]? GetBytes()
{ {
byte[] buffer = null; byte[]? buffer = null;
if (pBuffers == IntPtr.Zero) if (pBuffers == IntPtr.Zero)
{ {
......
// //
// Nancy.Authentication.Ntlm.Protocol.Type3Message - Authentication // Nancy.Authentication.Ntlm.Protocol.Type3Message - Authentication
// //
// Author: // Author:
...@@ -47,24 +47,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security ...@@ -47,24 +47,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
internal Message(byte[] message) internal Message(byte[] message)
{ {
type = 3; type = 3;
Decode(message);
}
/// <summary>
/// Domain name
/// </summary>
internal string Domain { get; private set; }
/// <summary>
/// Username
/// </summary>
internal string Username { get; private set; }
internal Common.NtlmFlags Flags { get; set; }
// methods
private void Decode(byte[] message)
{
if (message == null) if (message == null)
{ {
throw new ArgumentNullException(nameof(message)); throw new ArgumentNullException(nameof(message));
...@@ -108,6 +91,18 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security ...@@ -108,6 +91,18 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
Username = DecodeString(message, userOff, userLen); Username = DecodeString(message, userOff, userLen);
} }
/// <summary>
/// Domain name
/// </summary>
internal string Domain { get; private set; }
/// <summary>
/// Username
/// </summary>
internal string Username { get; private set; }
internal Common.NtlmFlags Flags { get; set; }
private string DecodeString(byte[] buffer, int offset, int len) private string DecodeString(byte[] buffer, int offset, int len)
{ {
if ((Flags & Common.NtlmFlags.NegotiateUnicode) != 0) if ((Flags & Common.NtlmFlags.NegotiateUnicode) != 0)
......
// http://pinvoke.net/default.aspx/secur32/InitializeSecurityContext.html // http://pinvoke.net/default.aspx/secur32/InitializeSecurityContext.html
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Principal; using System.Security.Principal;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
namespace Titanium.Web.Proxy.Network.WinAuth.Security namespace Titanium.Web.Proxy.Network.WinAuth.Security
...@@ -24,9 +22,9 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security ...@@ -24,9 +22,9 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
/// <param name="authScheme"></param> /// <param name="authScheme"></param>
/// <param name="data"></param> /// <param name="data"></param>
/// <returns></returns> /// <returns></returns>
internal static byte[] AcquireInitialSecurityToken(string hostname, string authScheme, InternalDataStore data) internal static byte[]? AcquireInitialSecurityToken(string hostname, string authScheme, InternalDataStore data)
{ {
byte[] token; byte[]? token;
// null for initial call // null for initial call
var serverToken = new SecurityBufferDesciption(); var serverToken = new SecurityBufferDesciption();
...@@ -91,9 +89,9 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security ...@@ -91,9 +89,9 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
/// <param name="serverChallenge"></param> /// <param name="serverChallenge"></param>
/// <param name="data"></param> /// <param name="data"></param>
/// <returns></returns> /// <returns></returns>
internal static byte[] AcquireFinalSecurityToken(string hostname, byte[] serverChallenge, InternalDataStore data) internal static byte[]? AcquireFinalSecurityToken(string hostname, byte[] serverChallenge, InternalDataStore data)
{ {
byte[] token; byte[]? token;
// user server challenge // user server challenge
var serverToken = new SecurityBufferDesciption(serverChallenge); var serverToken = new SecurityBufferDesciption(serverChallenge);
...@@ -145,19 +143,19 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security ...@@ -145,19 +143,19 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
/// <returns></returns> /// <returns></returns>
internal static bool ValidateWinAuthState(InternalDataStore data, State.WinAuthState expectedAuthState) internal static bool ValidateWinAuthState(InternalDataStore data, State.WinAuthState expectedAuthState)
{ {
bool stateExists = data.TryGetValueAs(authStateKey, out State state); bool stateExists = data.TryGetValueAs(authStateKey, out State? state);
if (expectedAuthState == State.WinAuthState.UNAUTHORIZED) if (expectedAuthState == State.WinAuthState.UNAUTHORIZED)
{ {
return !stateExists || return !stateExists ||
state.AuthState == State.WinAuthState.UNAUTHORIZED || state!.AuthState == State.WinAuthState.UNAUTHORIZED ||
state.AuthState == State.WinAuthState.AUTHORIZED; // Server may require re-authentication on an open connection state.AuthState == State.WinAuthState.AUTHORIZED; // Server may require re-authentication on an open connection
} }
if (expectedAuthState == State.WinAuthState.INITIAL_TOKEN) if (expectedAuthState == State.WinAuthState.INITIAL_TOKEN)
{ {
return stateExists && return stateExists &&
(state.AuthState == State.WinAuthState.INITIAL_TOKEN || (state!.AuthState == State.WinAuthState.INITIAL_TOKEN ||
state.AuthState == State.WinAuthState.AUTHORIZED); // Server may require re-authentication on an open connection state.AuthState == State.WinAuthState.AUTHORIZED); // Server may require re-authentication on an open connection
} }
...@@ -170,9 +168,9 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security ...@@ -170,9 +168,9 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
/// <param name="data"></param> /// <param name="data"></param>
internal static void AuthenticatedResponse(InternalDataStore data) internal static void AuthenticatedResponse(InternalDataStore data)
{ {
if (data.TryGetValueAs(authStateKey, out State state)) if (data.TryGetValueAs(authStateKey, out State? state))
{ {
state.AuthState = State.WinAuthState.AUTHORIZED; state!.AuthState = State.WinAuthState.AUTHORIZED;
state.UpdatePresence(); state.UpdatePresence();
} }
} }
......
...@@ -7,7 +7,6 @@ using Titanium.Web.Proxy.Exceptions; ...@@ -7,7 +7,6 @@ using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions; 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;
using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
...@@ -30,30 +29,35 @@ namespace Titanium.Web.Proxy ...@@ -30,30 +29,35 @@ namespace Titanium.Web.Proxy
try try
{ {
var header = httpHeaders.GetFirstHeader(KnownHeaders.ProxyAuthorization); var headerObj = httpHeaders.GetFirstHeader(KnownHeaders.ProxyAuthorization);
if (header == null) if (headerObj == null)
{ {
session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Required"); session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Required");
return false; return false;
} }
var headerValueParts = header.Value.Split(ProxyConstants.SpaceSplit); string header = headerObj.Value;
int firstSpace = header.IndexOf(' ');
if (headerValueParts.Length != 2) // header value should contain exactly 1 space
if (firstSpace == -1 || header.IndexOf(' ', firstSpace + 1) != -1)
{ {
// Return not authorized // Return not authorized
session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid"); session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false; return false;
} }
var authenticationType = header.AsMemory(0, firstSpace);
var credentials = header.AsMemory(firstSpace + 1);
if (ProxyBasicAuthenticateFunc != null) if (ProxyBasicAuthenticateFunc != null)
{ {
return await authenticateUserBasic(session, headerValueParts); return await authenticateUserBasic(session, authenticationType, credentials, ProxyBasicAuthenticateFunc);
} }
if (ProxySchemeAuthenticateFunc != null) if (ProxySchemeAuthenticateFunc != null)
{ {
var result = await ProxySchemeAuthenticateFunc(session, headerValueParts[0], headerValueParts[1]); var result = await ProxySchemeAuthenticateFunc(session, authenticationType.ToString(), credentials.ToString());
if (result.Result == ProxyAuthenticationResult.ContinuationNeeded) if (result.Result == ProxyAuthenticationResult.ContinuationNeeded)
{ {
...@@ -78,16 +82,18 @@ namespace Titanium.Web.Proxy ...@@ -78,16 +82,18 @@ namespace Titanium.Web.Proxy
} }
} }
private async Task<bool> authenticateUserBasic(SessionEventArgsBase session, string[] headerValueParts) private async Task<bool> authenticateUserBasic(SessionEventArgsBase session,
ReadOnlyMemory<char> authenticationType, ReadOnlyMemory<char> credentials,
Func<SessionEventArgsBase, string, string, Task<bool>> proxyBasicAuthenticateFunc)
{ {
if (!headerValueParts[0].EqualsIgnoreCase(KnownHeaders.ProxyAuthorizationBasic)) if (!KnownHeaders.ProxyAuthorizationBasic.Equals(authenticationType.Span))
{ {
// Return not authorized // Return not authorized
session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid"); session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid");
return false; return false;
} }
string decoded = Encoding.UTF8.GetString(Convert.FromBase64String(headerValueParts[1])); string decoded = Encoding.UTF8.GetString(Convert.FromBase64String(credentials.ToString()));
int colonIndex = decoded.IndexOf(':'); int colonIndex = decoded.IndexOf(':');
if (colonIndex == -1) if (colonIndex == -1)
{ {
...@@ -98,7 +104,7 @@ namespace Titanium.Web.Proxy ...@@ -98,7 +104,7 @@ namespace Titanium.Web.Proxy
string username = decoded.Substring(0, colonIndex); string username = decoded.Substring(0, colonIndex);
string password = decoded.Substring(colonIndex + 1); string password = decoded.Substring(colonIndex + 1);
bool authenticated = await ProxyBasicAuthenticateFunc(session, username, password); bool authenticated = await proxyBasicAuthenticateFunc(session, username, password);
if (!authenticated) if (!authenticated)
{ {
session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid"); session.HttpClient.Response = createAuthentication407Response("Proxy Authentication Invalid");
...@@ -111,8 +117,9 @@ namespace Titanium.Web.Proxy ...@@ -111,8 +117,9 @@ namespace Titanium.Web.Proxy
/// Create an authentication required response. /// Create an authentication required response.
/// </summary> /// </summary>
/// <param name="description">Response description.</param> /// <param name="description">Response description.</param>
/// <param name="continuation">The continuation.</param>
/// <returns></returns> /// <returns></returns>
private Response createAuthentication407Response(string description, string continuation = null) private Response createAuthentication407Response(string description, string? continuation = null)
{ {
var response = new Response var response = new Response
{ {
...@@ -123,7 +130,7 @@ namespace Titanium.Web.Proxy ...@@ -123,7 +130,7 @@ namespace Titanium.Web.Proxy
if (!string.IsNullOrWhiteSpace(continuation)) if (!string.IsNullOrWhiteSpace(continuation))
{ {
return createContinuationResponse(response, continuation); return createContinuationResponse(response, continuation!);
} }
if (ProxyBasicAuthenticateFunc != null) if (ProxyBasicAuthenticateFunc != null)
......
...@@ -32,6 +32,10 @@ namespace Titanium.Web.Proxy ...@@ -32,6 +32,10 @@ namespace Titanium.Web.Proxy
internal static readonly string UriSchemeHttp = Uri.UriSchemeHttp; internal static readonly string UriSchemeHttp = Uri.UriSchemeHttp;
internal static readonly string UriSchemeHttps = Uri.UriSchemeHttps; internal static readonly string UriSchemeHttps = Uri.UriSchemeHttps;
internal static ByteString UriSchemeHttp8 = (ByteString)UriSchemeHttp;
internal static ByteString UriSchemeHttps8 = (ByteString)UriSchemeHttps;
/// <summary> /// <summary>
/// A default exception log func. /// A default exception log func.
/// </summary> /// </summary>
...@@ -45,7 +49,7 @@ namespace Titanium.Web.Proxy ...@@ -45,7 +49,7 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// Backing field for exposed public property. /// Backing field for exposed public property.
/// </summary> /// </summary>
private ExceptionHandler exceptionFunc; private ExceptionHandler? exceptionFunc;
/// <summary> /// <summary>
/// Backing field for exposed public property. /// Backing field for exposed public property.
...@@ -55,7 +59,7 @@ namespace Titanium.Web.Proxy ...@@ -55,7 +59,7 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// Upstream proxy manager. /// Upstream proxy manager.
/// </summary> /// </summary>
private WinHttpWebProxyFinder systemProxyResolver; private WinHttpWebProxyFinder? systemProxyResolver;
/// <inheritdoc /> /// <inheritdoc />
...@@ -91,16 +95,11 @@ namespace Titanium.Web.Proxy ...@@ -91,16 +95,11 @@ namespace Titanium.Web.Proxy
/// Should we attempt to trust certificates with elevated permissions by /// Should we attempt to trust certificates with elevated permissions by
/// prompting for UAC if required? /// prompting for UAC if required?
/// </param> /// </param>
public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, public ProxyServer(string? rootCertificateName, string? rootCertificateIssuerName,
bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false,
bool trustRootCertificateAsAdmin = false) bool trustRootCertificateAsAdmin = false)
{ {
BufferPool = new DefaultBufferPool();
if (BufferPool == null)
{
BufferPool = new DefaultBufferPool();
}
ProxyEndPoints = new List<ProxyEndPoint>(); ProxyEndPoints = new List<ProxyEndPoint>();
tcpConnectionFactory = new TcpConnectionFactory(this); tcpConnectionFactory = new TcpConnectionFactory(this);
if (RunTime.IsWindows && !RunTime.IsUwpOnWindows) if (RunTime.IsWindows && !RunTime.IsUwpOnWindows)
...@@ -120,7 +119,7 @@ namespace Titanium.Web.Proxy ...@@ -120,7 +119,7 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// Manage system proxy settings. /// Manage system proxy settings.
/// </summary> /// </summary>
private SystemProxyManager systemProxySettingsManager { get; } private SystemProxyManager? systemProxySettingsManager { get; }
/// <summary> /// <summary>
/// Number of exception retries when connection pool is enabled. /// Number of exception retries when connection pool is enabled.
...@@ -190,12 +189,6 @@ namespace Titanium.Web.Proxy ...@@ -190,12 +189,6 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public bool NoDelay { get; set; } = true; public bool NoDelay { get; set; } = true;
/// <summary>
/// Buffer size in bytes used throughout this proxy.
/// Default value is 8192 bytes.
/// </summary>
public int BufferSize { get; set; } = 8192;
/// <summary> /// <summary>
/// Seconds client/server connection are to be kept alive when waiting for read/write to complete. /// Seconds client/server connection are to be kept alive when waiting for read/write to complete.
/// This will also determine the pool eviction time when connection pool is enabled. /// This will also determine the pool eviction time when connection pool is enabled.
...@@ -240,12 +233,15 @@ namespace Titanium.Web.Proxy ...@@ -240,12 +233,15 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// List of supported Ssl versions. /// List of supported Ssl versions.
/// </summary> /// </summary>
#pragma warning disable 618
public SslProtocols SupportedSslProtocols { get; set; } = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12; public SslProtocols SupportedSslProtocols { get; set; } = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
#pragma warning restore 618
/// <summary> /// <summary>
/// The buffer pool used throughout this proxy instance. /// The buffer pool used throughout this proxy instance.
/// Set custom implementations by implementing this interface. /// Set custom implementations by implementing this interface.
/// By default this uses DefaultBufferPool implementation available in StreamExtended library package. /// By default this uses DefaultBufferPool implementation available in StreamExtended library package.
/// Buffer size should be at least 10 bytes.
/// </summary> /// </summary>
public IBufferPool BufferPool { get; set; } public IBufferPool BufferPool { get; set; }
...@@ -257,18 +253,18 @@ namespace Titanium.Web.Proxy ...@@ -257,18 +253,18 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// External proxy used for Http requests. /// External proxy used for Http requests.
/// </summary> /// </summary>
public ExternalProxy UpStreamHttpProxy { get; set; } public ExternalProxy? UpStreamHttpProxy { get; set; }
/// <summary> /// <summary>
/// External proxy used for Https requests. /// External proxy used for Https requests.
/// </summary> /// </summary>
public ExternalProxy UpStreamHttpsProxy { get; set; } public ExternalProxy? UpStreamHttpsProxy { get; set; }
/// <summary> /// <summary>
/// Local adapter/NIC endpoint where proxy makes request via. /// Local adapter/NIC endpoint where proxy makes request via.
/// Defaults via any IP addresses of this machine. /// Defaults via any IP addresses of this machine.
/// </summary> /// </summary>
public IPEndPoint UpStreamEndPoint { get; set; } public IPEndPoint? UpStreamEndPoint { get; set; }
/// <summary> /// <summary>
/// A list of IpAddress and port this proxy is listening to. /// A list of IpAddress and port this proxy is listening to.
...@@ -279,7 +275,7 @@ namespace Titanium.Web.Proxy ...@@ -279,7 +275,7 @@ namespace Titanium.Web.Proxy
/// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP(S) requests. /// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP(S) requests.
/// User should return the ExternalProxy object with valid credentials. /// User should return the ExternalProxy object with valid credentials.
/// </summary> /// </summary>
public Func<SessionEventArgsBase, Task<ExternalProxy>> GetCustomUpStreamProxyFunc { get; set; } public Func<SessionEventArgsBase, Task<ExternalProxy?>>? GetCustomUpStreamProxyFunc { get; set; }
/// <summary> /// <summary>
/// Callback for error events in this proxy instance. /// Callback for error events in this proxy instance.
...@@ -299,14 +295,14 @@ namespace Titanium.Web.Proxy ...@@ -299,14 +295,14 @@ namespace Titanium.Web.Proxy
/// Parameters are username and password as provided by client. /// Parameters are username and password as provided by client.
/// Should return true for successful authentication. /// Should return true for successful authentication.
/// </summary> /// </summary>
public Func<SessionEventArgsBase, string, string, Task<bool>> ProxyBasicAuthenticateFunc { get; set; } public Func<SessionEventArgsBase, string, string, Task<bool>>? ProxyBasicAuthenticateFunc { get; set; }
/// <summary> /// <summary>
/// A pluggable callback to authenticate clients by scheme instead of requiring basic authentication through ProxyBasicAuthenticateFunc. /// A pluggable callback to authenticate clients by scheme instead of requiring basic authentication through ProxyBasicAuthenticateFunc.
/// Parameters are current working session, schemeType, and token as provided by a calling client. /// Parameters are current working session, schemeType, and token as provided by a calling client.
/// Should return success for successful authentication, continuation if the package requests, or failure. /// Should return success for successful authentication, continuation if the package requests, or failure.
/// </summary> /// </summary>
public Func<SessionEventArgsBase, string, string, Task<ProxyAuthenticationContext>> ProxySchemeAuthenticateFunc { get; set; } public Func<SessionEventArgsBase, string, string, Task<ProxyAuthenticationContext>>? ProxySchemeAuthenticateFunc { get; set; }
/// <summary> /// <summary>
/// A collection of scheme types, e.g. basic, NTLM, Kerberos, Negotiate, to return if scheme authentication is required. /// A collection of scheme types, e.g. basic, NTLM, Kerberos, Negotiate, to return if scheme authentication is required.
...@@ -317,47 +313,47 @@ namespace Titanium.Web.Proxy ...@@ -317,47 +313,47 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// Event occurs when client connection count changed. /// Event occurs when client connection count changed.
/// </summary> /// </summary>
public event EventHandler ClientConnectionCountChanged; public event EventHandler? ClientConnectionCountChanged;
/// <summary> /// <summary>
/// Event occurs when server connection count changed. /// Event occurs when server connection count changed.
/// </summary> /// </summary>
public event EventHandler ServerConnectionCountChanged; public event EventHandler? ServerConnectionCountChanged;
/// <summary> /// <summary>
/// Event to override the default verification logic of remote SSL certificate received during authentication. /// Event to override the default verification logic of remote SSL certificate received during authentication.
/// </summary> /// </summary>
public event AsyncEventHandler<CertificateValidationEventArgs> ServerCertificateValidationCallback; public event AsyncEventHandler<CertificateValidationEventArgs>? ServerCertificateValidationCallback;
/// <summary> /// <summary>
/// Event to override client certificate selection during mutual SSL authentication. /// Event to override client certificate selection during mutual SSL authentication.
/// </summary> /// </summary>
public event AsyncEventHandler<CertificateSelectionEventArgs> ClientCertificateSelectionCallback; public event AsyncEventHandler<CertificateSelectionEventArgs>? ClientCertificateSelectionCallback;
/// <summary> /// <summary>
/// Intercept request event to server. /// Intercept request event to server.
/// </summary> /// </summary>
public event AsyncEventHandler<SessionEventArgs> BeforeRequest; public event AsyncEventHandler<SessionEventArgs>? BeforeRequest;
/// <summary> /// <summary>
/// Intercept response event from server. /// Intercept response event from server.
/// </summary> /// </summary>
public event AsyncEventHandler<SessionEventArgs> BeforeResponse; public event AsyncEventHandler<SessionEventArgs>? BeforeResponse;
/// <summary> /// <summary>
/// Intercept after response event from server. /// Intercept after response event from server.
/// </summary> /// </summary>
public event AsyncEventHandler<SessionEventArgs> AfterResponse; public event AsyncEventHandler<SessionEventArgs>? AfterResponse;
/// <summary> /// <summary>
/// Customize TcpClient used for client connection upon create. /// Customize TcpClient used for client connection upon create.
/// </summary> /// </summary>
public event AsyncEventHandler<TcpClient> OnClientConnectionCreate; public event AsyncEventHandler<TcpClient>? OnClientConnectionCreate;
/// <summary> /// <summary>
/// Customize TcpClient used for server connection upon create. /// Customize TcpClient used for server connection upon create.
/// </summary> /// </summary>
public event AsyncEventHandler<TcpClient> OnServerConnectionCreate; public event AsyncEventHandler<TcpClient>? OnServerConnectionCreate;
/// <summary> /// <summary>
/// Customize the minimum ThreadPool size (increase it on a server) /// Customize the minimum ThreadPool size (increase it on a server)
...@@ -429,7 +425,7 @@ namespace Titanium.Web.Proxy ...@@ -429,7 +425,7 @@ namespace Titanium.Web.Proxy
/// <param name="protocolType">The proxy protocol type.</param> /// <param name="protocolType">The proxy protocol type.</param>
public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType) public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType)
{ {
if (!RunTime.IsWindows) if (systemProxySettingsManager == null)
{ {
throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows. throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows.
Please manually confugure you operating system to use this proxy's port and address."); Please manually confugure you operating system to use this proxy's port and address.");
...@@ -481,7 +477,7 @@ namespace Titanium.Web.Proxy ...@@ -481,7 +477,7 @@ namespace Titanium.Web.Proxy
endPoint.IsSystemHttpsProxy = true; endPoint.IsSystemHttpsProxy = true;
} }
string proxyType = null; string? proxyType = null;
switch (protocolType) switch (protocolType)
{ {
case ProxyProtocolType.Http: case ProxyProtocolType.Http:
...@@ -523,7 +519,7 @@ namespace Titanium.Web.Proxy ...@@ -523,7 +519,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public void RestoreOriginalProxySettings() public void RestoreOriginalProxySettings()
{ {
if (!RunTime.IsWindows) if (systemProxySettingsManager == null)
{ {
throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows. throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows.
Please manually configure your operating system to use this proxy's port and address."); Please manually configure your operating system to use this proxy's port and address.");
...@@ -537,7 +533,7 @@ namespace Titanium.Web.Proxy ...@@ -537,7 +533,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public void DisableSystemProxy(ProxyProtocolType protocolType) public void DisableSystemProxy(ProxyProtocolType protocolType)
{ {
if (!RunTime.IsWindows) if (systemProxySettingsManager == null)
{ {
throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows. throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows.
Please manually configure your operating system to use this proxy's port and address."); Please manually configure your operating system to use this proxy's port and address.");
...@@ -551,7 +547,7 @@ namespace Titanium.Web.Proxy ...@@ -551,7 +547,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public void DisableAllSystemProxies() public void DisableAllSystemProxies()
{ {
if (!RunTime.IsWindows) if (systemProxySettingsManager == null)
{ {
throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows. throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows.
Please manually confugure you operating system to use this proxy's port and address."); Please manually confugure you operating system to use this proxy's port and address.");
...@@ -582,7 +578,7 @@ namespace Titanium.Web.Proxy ...@@ -582,7 +578,7 @@ namespace Titanium.Web.Proxy
if (systemProxySettingsManager != null && RunTime.IsWindows && !RunTime.IsUwpOnWindows) if (systemProxySettingsManager != null && RunTime.IsWindows && !RunTime.IsUwpOnWindows)
{ {
var proxyInfo = systemProxySettingsManager.GetProxyInfoFromRegistry(); var proxyInfo = systemProxySettingsManager.GetProxyInfoFromRegistry();
if (proxyInfo.Proxies != null) if (proxyInfo?.Proxies != null)
{ {
var protocolToRemove = ProxyProtocolType.None; var protocolToRemove = ProxyProtocolType.None;
foreach (var proxy in proxyInfo.Proxies.Values) foreach (var proxy in proxyInfo.Proxies.Values)
...@@ -630,7 +626,7 @@ namespace Titanium.Web.Proxy ...@@ -630,7 +626,7 @@ namespace Titanium.Web.Proxy
throw new Exception("Proxy is not running."); throw new Exception("Proxy is not running.");
} }
if (RunTime.IsWindows && !RunTime.IsUwpOnWindows) if (systemProxySettingsManager != null)
{ {
bool setAsSystemProxy = ProxyEndPoints.OfType<ExplicitProxyEndPoint>() bool setAsSystemProxy = ProxyEndPoints.OfType<ExplicitProxyEndPoint>()
.Any(x => x.IsSystemHttpProxy || x.IsSystemHttpsProxy); .Any(x => x.IsSystemHttpProxy || x.IsSystemHttpsProxy);
...@@ -662,8 +658,7 @@ namespace Titanium.Web.Proxy ...@@ -662,8 +658,7 @@ namespace Titanium.Web.Proxy
{ {
endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port); endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port);
// linux/macOS has a bug with socket reuse in .net core. if (ReuseSocket && RunTime.IsSocketReuseAvailable)
if (ReuseSocket && RunTime.IsWindows)
{ {
endPoint.Listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); endPoint.Listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
} }
...@@ -714,9 +709,9 @@ namespace Titanium.Web.Proxy ...@@ -714,9 +709,9 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="sessionEventArgs">The session.</param> /// <param name="sessionEventArgs">The session.</param>
/// <returns>The external proxy as task result.</returns> /// <returns>The external proxy as task result.</returns>
private Task<ExternalProxy> getSystemUpStreamProxy(SessionEventArgsBase sessionEventArgs) private Task<ExternalProxy?> getSystemUpStreamProxy(SessionEventArgsBase sessionEventArgs)
{ {
var proxy = systemProxyResolver.GetProxy(sessionEventArgs.HttpClient.Request.RequestUri); var proxy = systemProxyResolver!.GetProxy(sessionEventArgs.HttpClient.Request.RequestUri);
return Task.FromResult(proxy); return Task.FromResult(proxy);
} }
...@@ -727,7 +722,7 @@ namespace Titanium.Web.Proxy ...@@ -727,7 +722,7 @@ namespace Titanium.Web.Proxy
{ {
var endPoint = (ProxyEndPoint)asyn.AsyncState; var endPoint = (ProxyEndPoint)asyn.AsyncState;
TcpClient tcpClient = null; TcpClient? tcpClient = null;
try try
{ {
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net;
using System.Net.Sockets;
#if NETCOREAPP2_1
using System.Net.Security; using System.Net.Security;
#endif using System.Net.Sockets;
using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
...@@ -27,9 +23,6 @@ namespace Titanium.Web.Proxy ...@@ -27,9 +23,6 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public partial class ProxyServer public partial class ProxyServer
{ {
private bool isWindowsAuthenticationEnabledAndSupported =>
EnableWinAuth && RunTime.IsWindows;
/// <summary> /// <summary>
/// This is the core request handler method for a particular connection from client. /// This is the core request handler method for a particular connection from client.
/// Will create new session (request/response) sequence until /// Will create new session (request/response) sequence until
...@@ -40,21 +33,17 @@ namespace Titanium.Web.Proxy ...@@ -40,21 +33,17 @@ namespace Titanium.Web.Proxy
/// <param name="clientStream">The client stream.</param> /// <param name="clientStream">The client stream.</param>
/// <param name="clientStreamWriter">The client stream writer.</param> /// <param name="clientStreamWriter">The client stream writer.</param>
/// <param name="cancellationTokenSource">The cancellation token source for this async task.</param> /// <param name="cancellationTokenSource">The cancellation token source for this async task.</param>
/// <param name="httpsConnectHostname">
/// The https hostname as appeared in 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="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, TcpClientConnection clientConnection,
CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter, CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter,
CancellationTokenSource cancellationTokenSource, string httpsConnectHostname, TunnelConnectSessionEventArgs connectArgs, CancellationTokenSource cancellationTokenSource, TunnelConnectSessionEventArgs? connectArgs = null,
Task<TcpServerConnection> prefetchConnectionTask = null) Task<TcpServerConnection>? prefetchConnectionTask = null)
{ {
var connectRequest = connectArgs?.HttpClient.ConnectRequest; var connectRequest = connectArgs?.HttpClient.ConnectRequest;
var prefetchTask = prefetchConnectionTask; var prefetchTask = prefetchConnectionTask;
TcpServerConnection connection = null; TcpServerConnection? connection = null;
bool closeServerConnection = false; bool closeServerConnection = false;
try try
...@@ -71,17 +60,14 @@ namespace Titanium.Web.Proxy ...@@ -71,17 +60,14 @@ namespace Titanium.Web.Proxy
} }
// read the request line // read the request line
string httpCmd = await clientStream.ReadLineAsync(cancellationToken); string? httpCmd = await clientStream.ReadLineAsync(cancellationToken);
if (string.IsNullOrEmpty(httpCmd)) if (string.IsNullOrEmpty(httpCmd))
{ {
return; return;
} }
var args = new SessionEventArgs(this, endPoint, cancellationTokenSource) var args = new SessionEventArgs(this, endPoint, new ProxyClient(clientConnection, clientStream, clientStreamWriter), connectRequest, cancellationTokenSource)
{ {
ProxyClient = { Connection = clientConnection },
HttpClient = { ConnectRequest = connectRequest },
UserData = connectArgs?.UserData UserData = connectArgs?.UserData
}; };
...@@ -89,61 +75,30 @@ namespace Titanium.Web.Proxy ...@@ -89,61 +75,30 @@ namespace Titanium.Web.Proxy
{ {
try try
{ {
Request.ParseRequestLine(httpCmd, out string httpMethod, out string httpUrl, Request.ParseRequestLine(httpCmd!, out string httpMethod, out string httpUrl, out var version);
out var version);
// Read the request headers in to unique and non-unique header collections // Read the request headers in to unique and non-unique header collections
await HeaderParser.ReadHeaders(clientStream, args.HttpClient.Request.Headers, await HeaderParser.ReadHeaders(clientStream, args.HttpClient.Request.Headers,
cancellationToken); cancellationToken);
Uri httpRemoteUri; var request = args.HttpClient.Request;
if (ProxyConstants.UriSchemeRegex.IsMatch(httpUrl)) if (connectRequest != null)
{
try
{
httpRemoteUri = new Uri(httpUrl);
}
catch (Exception ex)
{
throw new Exception($"Invalid URI: '{httpUrl}'", ex);
}
}
else
{ {
string host = args.HttpClient.Request.Host ?? httpsConnectHostname; request.IsHttps = connectRequest.IsHttps;
string hostAndPath = host; request.Authority = connectRequest.Authority;
if (httpUrl.StartsWith("/"))
{
hostAndPath += httpUrl;
}
string url = string.Concat(httpsConnectHostname == null ? "http://" : "https://",
hostAndPath);
try
{
httpRemoteUri = new Uri(url);
}
catch (Exception ex)
{
throw new Exception($"Invalid URI: '{url}'", ex);
}
} }
var request = args.HttpClient.Request; request.OriginalUrlData = HttpHeader.Encoding.GetBytes(httpUrl);
request.RequestUri = httpRemoteUri;
request.OriginalUrl = httpUrl;
request.Method = httpMethod; request.Method = httpMethod;
request.HttpVersion = version; request.HttpVersion = version;
args.ProxyClient.ClientStream = clientStream;
args.ProxyClient.ClientStreamWriter = clientStreamWriter;
if (!args.IsTransparent) if (!args.IsTransparent)
{ {
// proxy authorization check // proxy authorization check
if (httpsConnectHostname == null && await checkAuthorization(args) == false) if (connectRequest == null && await checkAuthorization(args) == false)
{ {
await invokeBeforeResponse(args); await onBeforeResponse(args);
// send the response // send the response
await clientStreamWriter.WriteResponseAsync(args.HttpClient.Response, await clientStreamWriter.WriteResponseAsync(args.HttpClient.Response,
...@@ -158,7 +113,7 @@ namespace Titanium.Web.Proxy ...@@ -158,7 +113,7 @@ namespace Titanium.Web.Proxy
// if win auth is enabled // if win auth is enabled
// we need a cache of request body // we need a cache of request body
// so that we can send it after authentication in WinAuthHandler.cs // so that we can send it after authentication in WinAuthHandler.cs
if (isWindowsAuthenticationEnabledAndSupported && request.HasBody) if (args.EnableWinAuth && request.HasBody)
{ {
await args.GetRequestBody(cancellationToken); await args.GetRequestBody(cancellationToken);
} }
...@@ -166,10 +121,8 @@ namespace Titanium.Web.Proxy ...@@ -166,10 +121,8 @@ namespace Titanium.Web.Proxy
// we need this to syphon out data from connection if API user changes them. // we need this to syphon out data from connection if API user changes them.
request.SetOriginalHeaders(); request.SetOriginalHeaders();
args.TimeLine["Request Received"] = DateTime.Now;
// If user requested interception do it // If user requested interception do it
await invokeBeforeRequest(args); await onBeforeRequest(args);
var response = args.HttpClient.Response; var response = args.HttpClient.Response;
...@@ -222,7 +175,7 @@ namespace Titanium.Web.Proxy ...@@ -222,7 +175,7 @@ namespace Titanium.Web.Proxy
connection = null; connection = null;
} }
var result = await handleHttpSessionRequest(httpCmd, args, connection, var result = await handleHttpSessionRequest(httpMethod, httpUrl, version, args, connection,
clientConnection.NegotiatedApplicationProtocol, clientConnection.NegotiatedApplicationProtocol,
cancellationToken, cancellationTokenSource); cancellationToken, cancellationTokenSource);
...@@ -231,7 +184,7 @@ namespace Titanium.Web.Proxy ...@@ -231,7 +184,7 @@ namespace Titanium.Web.Proxy
closeServerConnection = !result.Continue; closeServerConnection = !result.Continue;
// throw if exception happened // throw if exception happened
if (!result.IsSuccess) if (result.Exception != null)
{ {
throw result.Exception; throw result.Exception;
} }
...@@ -286,22 +239,24 @@ namespace Titanium.Web.Proxy ...@@ -286,22 +239,24 @@ namespace Titanium.Web.Proxy
} }
finally finally
{ {
await invokeAfterResponse(args); await onAfterResponse(args);
args.Dispose(); args.Dispose();
} }
} }
} }
finally finally
{ {
await tcpConnectionFactory.Release(connection, if (connection != null)
closeServerConnection); {
await tcpConnectionFactory.Release(connection, closeServerConnection);
}
await tcpConnectionFactory.Release(prefetchTask, closeServerConnection); await tcpConnectionFactory.Release(prefetchTask, closeServerConnection);
} }
} }
private async Task<RetryResult> handleHttpSessionRequest(string httpCmd, SessionEventArgs args, private async Task<RetryResult> handleHttpSessionRequest(string requestHttpMethod, string requestHttpUrl, Version requestVersion, SessionEventArgs args,
TcpServerConnection serverConnection, SslApplicationProtocol sslApplicationProtocol, TcpServerConnection? serverConnection, SslApplicationProtocol sslApplicationProtocol,
CancellationToken cancellationToken, CancellationTokenSource cancellationTokenSource) CancellationToken cancellationToken, CancellationTokenSource cancellationTokenSource)
{ {
// a connection generator task with captured parameters via closure. // a connection generator task with captured parameters via closure.
...@@ -317,10 +272,10 @@ namespace Titanium.Web.Proxy ...@@ -317,10 +272,10 @@ namespace Titanium.Web.Proxy
if (args.HttpClient.Request.UpgradeToWebSocket) if (args.HttpClient.Request.UpgradeToWebSocket)
{ {
args.HttpClient.ConnectRequest.TunnelType = TunnelType.Websocket; args.HttpClient.ConnectRequest!.TunnelType = TunnelType.Websocket;
// if upgrading to websocket then relay the request without reading the contents // if upgrading to websocket then relay the request without reading the contents
await handleWebSocketUpgrade(httpCmd, args, args.HttpClient.Request, await handleWebSocketUpgrade(requestHttpMethod, requestHttpUrl, requestVersion, args, args.HttpClient.Request,
args.HttpClient.Response, args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamWriter, args.HttpClient.Response, args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamWriter,
connection, cancellationTokenSource, cancellationToken); connection, cancellationTokenSource, cancellationToken);
return false; return false;
...@@ -351,9 +306,12 @@ namespace Titanium.Web.Proxy ...@@ -351,9 +306,12 @@ namespace Titanium.Web.Proxy
{ {
var clientStreamWriter = args.ProxyClient.ClientStreamWriter; var clientStreamWriter = args.ProxyClient.ClientStreamWriter;
var response = args.HttpClient.Response; var response = args.HttpClient.Response;
await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, response.StatusCode,
response.StatusDescription, cancellationToken); var headerBuilder = new HeaderBuilder();
await clientStreamWriter.WriteHeadersAsync(response.Headers, cancellationToken: cancellationToken); headerBuilder.WriteResponseLine(response.HttpVersion, response.StatusCode, response.StatusDescription);
headerBuilder.WriteHeaders(response.Headers);
await clientStreamWriter.WriteHeadersAsync(headerBuilder, cancellationToken);
await args.ClearResponse(cancellationToken); await args.ClearResponse(cancellationToken);
} }
...@@ -363,12 +321,12 @@ namespace Titanium.Web.Proxy ...@@ -363,12 +321,12 @@ namespace Titanium.Web.Proxy
if (request.IsBodyRead) if (request.IsBodyRead)
{ {
var writer = args.HttpClient.Connection.StreamWriter; var writer = args.HttpClient.Connection.StreamWriter;
await writer.WriteBodyAsync(body, request.IsChunked, cancellationToken); await writer.WriteBodyAsync(body!, request.IsChunked, cancellationToken);
} }
else if (!request.ExpectationFailed) else if (!request.ExpectationFailed)
{ {
// get the request body unless an unsuccessful 100 continue request was made // get the request body unless an unsuccessful 100 continue request was made
HttpWriter writer = args.HttpClient.Connection.StreamWriter; HttpWriter writer = args.HttpClient.Connection.StreamWriter!;
await args.CopyRequestBodyAsync(writer, TransformationMode.None, cancellationToken); await args.CopyRequestBodyAsync(writer, TransformationMode.None, cancellationToken);
} }
} }
...@@ -384,7 +342,7 @@ namespace Titanium.Web.Proxy ...@@ -384,7 +342,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
private void prepareRequestHeaders(HeaderCollection requestHeaders) private void prepareRequestHeaders(HeaderCollection requestHeaders)
{ {
string acceptEncoding = requestHeaders.GetHeaderValueOrNull(KnownHeaders.AcceptEncoding); string? acceptEncoding = requestHeaders.GetHeaderValueOrNull(KnownHeaders.AcceptEncoding);
if (acceptEncoding != null) if (acceptEncoding != null)
{ {
...@@ -410,8 +368,10 @@ namespace Titanium.Web.Proxy ...@@ -410,8 +368,10 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="args">The session event arguments.</param> /// <param name="args">The session event arguments.</param>
/// <returns></returns> /// <returns></returns>
private async Task invokeBeforeRequest(SessionEventArgs args) private async Task onBeforeRequest(SessionEventArgs args)
{ {
args.TimeLine["Request Received"] = DateTime.Now;
if (BeforeRequest != null) if (BeforeRequest != null)
{ {
await BeforeRequest.InvokeAsync(this, args, ExceptionFunc); await BeforeRequest.InvokeAsync(this, args, ExceptionFunc);
......
...@@ -39,7 +39,7 @@ namespace Titanium.Web.Proxy ...@@ -39,7 +39,7 @@ namespace Titanium.Web.Proxy
args.ReRequest = false; args.ReRequest = false;
// check for windows authentication // check for windows authentication
if (isWindowsAuthenticationEnabledAndSupported) if (args.EnableWinAuth)
{ {
if (response.StatusCode == (int)HttpStatusCode.Unauthorized) if (response.StatusCode == (int)HttpStatusCode.Unauthorized)
{ {
...@@ -58,7 +58,7 @@ namespace Titanium.Web.Proxy ...@@ -58,7 +58,7 @@ namespace Titanium.Web.Proxy
// if user requested call back then do it // if user requested call back then do it
if (!response.Locked) if (!response.Locked)
{ {
await invokeBeforeResponse(args); await onBeforeResponse(args);
} }
// it may changed in the user event // it may changed in the user event
...@@ -72,8 +72,7 @@ namespace Titanium.Web.Proxy ...@@ -72,8 +72,7 @@ namespace Titanium.Web.Proxy
// write custom user response with body and return. // write custom user response with body and return.
await clientStreamWriter.WriteResponseAsync(response, cancellationToken: cancellationToken); await clientStreamWriter.WriteResponseAsync(response, cancellationToken: cancellationToken);
if (args.HttpClient.Connection != null if (args.HttpClient.HasConnection && !args.HttpClient.CloseServerConnection)
&& !args.HttpClient.CloseServerConnection)
{ {
// syphon out the original response body from server connection // syphon out the original response body from server connection
// so that connection will be good to be reused. // so that connection will be good to be reused.
...@@ -87,13 +86,15 @@ namespace Titanium.Web.Proxy ...@@ -87,13 +86,15 @@ namespace Titanium.Web.Proxy
// likely after making modifications from User Response Handler // likely after making modifications from User Response Handler
if (args.ReRequest) if (args.ReRequest)
{ {
await tcpConnectionFactory.Release(args.HttpClient.Connection); if (args.HttpClient.HasConnection)
{
await tcpConnectionFactory.Release(args.HttpClient.Connection);
}
// clear current response // clear current response
await args.ClearResponse(cancellationToken); await args.ClearResponse(cancellationToken);
var httpCmd = Request.CreateRequestLine(args.HttpClient.Request.Method, await handleHttpSessionRequest(args.HttpClient.Request.Method, args.HttpClient.Request.Url, args.HttpClient.Request.HttpVersion,
args.HttpClient.Request.RequestUriString, args.HttpClient.Request.HttpVersion); args, null, args.ClientConnection.NegotiatedApplicationProtocol,
await handleHttpSessionRequest(httpCmd, args, null, args.ClientConnection.NegotiatedApplicationProtocol,
cancellationToken, args.CancellationTokenSource); cancellationToken, args.CancellationTokenSource);
return; return;
} }
...@@ -112,9 +113,10 @@ namespace Titanium.Web.Proxy ...@@ -112,9 +113,10 @@ namespace Titanium.Web.Proxy
else else
{ {
// Write back response status to client // Write back response status to client
await clientStreamWriter.WriteResponseStatusAsync(response.HttpVersion, response.StatusCode, var headerBuilder = new HeaderBuilder();
response.StatusDescription, cancellationToken); headerBuilder.WriteResponseLine(response.HttpVersion, response.StatusCode, response.StatusDescription);
await clientStreamWriter.WriteHeadersAsync(response.Headers, cancellationToken: cancellationToken); headerBuilder.WriteHeaders(response.Headers);
await clientStreamWriter.WriteHeadersAsync(headerBuilder, cancellationToken);
// Write body if exists // Write body if exists
if (response.HasBody) if (response.HasBody)
...@@ -132,7 +134,7 @@ namespace Titanium.Web.Proxy ...@@ -132,7 +134,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="args"></param> /// <param name="args"></param>
/// <returns></returns> /// <returns></returns>
private async Task invokeBeforeResponse(SessionEventArgs args) private async Task onBeforeResponse(SessionEventArgs args)
{ {
if (BeforeResponse != null) if (BeforeResponse != null)
{ {
...@@ -145,7 +147,7 @@ namespace Titanium.Web.Proxy ...@@ -145,7 +147,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="args"></param> /// <param name="args"></param>
/// <returns></returns> /// <returns></returns>
private async Task invokeAfterResponse(SessionEventArgs args) private async Task onAfterResponse(SessionEventArgs args)
{ {
if (AfterResponse != null) if (AfterResponse != null)
{ {
......
...@@ -12,23 +12,15 @@ namespace Titanium.Web.Proxy.Shared ...@@ -12,23 +12,15 @@ namespace Titanium.Web.Proxy.Shared
{ {
internal static readonly char DotSplit = '.'; internal static readonly char DotSplit = '.';
internal static readonly char[] SpaceSplit = { ' ' };
internal static readonly char[] ColonSplit = { ':' };
internal static readonly char[] SemiColonSplit = { ';' };
internal static readonly char[] EqualSplit = { '=' };
internal static readonly string NewLine = "\r\n"; internal static readonly string NewLine = "\r\n";
internal static readonly byte[] NewLineBytes = { (byte)'\r', (byte)'\n' }; internal static readonly byte[] NewLineBytes = { (byte)'\r', (byte)'\n' };
internal static readonly Regex UriSchemeRegex =
new Regex("^[a-z]*://", RegexOptions.IgnoreCase | RegexOptions.Compiled);
internal static readonly HashSet<string> ProxySupportedCompressions = internal static readonly HashSet<string> ProxySupportedCompressions =
new HashSet<string>(StringComparer.OrdinalIgnoreCase) new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{ {
KnownHeaders.ContentEncodingGzip, KnownHeaders.ContentEncodingGzip.String,
KnownHeaders.ContentEncodingDeflate, KnownHeaders.ContentEncodingDeflate.String,
KnownHeaders.ContentEncodingBrotli KnownHeaders.ContentEncodingBrotli.String
}; };
internal static readonly Regex CNRemoverRegex = internal static readonly Regex CNRemoverRegex =
......
using System.Buffers; using System.Buffers;
using System.Collections.Concurrent;
namespace Titanium.Web.Proxy.StreamExtended.BufferPool namespace Titanium.Web.Proxy.StreamExtended.BufferPool
{ {
...@@ -9,8 +8,23 @@ namespace Titanium.Web.Proxy.StreamExtended.BufferPool ...@@ -9,8 +8,23 @@ namespace Titanium.Web.Proxy.StreamExtended.BufferPool
/// Works well when all consumers ask for buffers with the same size. /// Works well when all consumers ask for buffers with the same size.
/// If your application would use variable size buffers consider implementing IBufferPool using System.Buffers library from Microsoft. /// If your application would use variable size buffers consider implementing IBufferPool using System.Buffers library from Microsoft.
/// </summary> /// </summary>
public class DefaultBufferPool : IBufferPool internal class DefaultBufferPool : IBufferPool
{ {
/// <summary>
/// Buffer size in bytes used throughout this proxy.
/// Default value is 8192 bytes.
/// </summary>
public int BufferSize { get; set; } = 8192;
/// <summary>
/// Gets a buffer with a default size.
/// </summary>
/// <returns></returns>
public byte[] GetBuffer()
{
return ArrayPool<byte>.Shared.Rent(BufferSize);
}
/// <summary> /// <summary>
/// Gets a buffer. /// Gets a buffer.
/// </summary> /// </summary>
......
...@@ -8,6 +8,10 @@ namespace Titanium.Web.Proxy.StreamExtended.BufferPool ...@@ -8,6 +8,10 @@ namespace Titanium.Web.Proxy.StreamExtended.BufferPool
/// </summary> /// </summary>
public interface IBufferPool : IDisposable public interface IBufferPool : IDisposable
{ {
int BufferSize { get; }
byte[] GetBuffer();
byte[] GetBuffer(int bufferSize); byte[] GetBuffer(int bufferSize);
void ReturnBuffer(byte[] buffer); void ReturnBuffer(byte[] buffer);
......
...@@ -17,19 +17,19 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -17,19 +17,19 @@ namespace Titanium.Web.Proxy.StreamExtended
"DEFLATE" "DEFLATE"
}; };
public int HandshakeVersion { get; set; } public int HandshakeVersion { get; }
public int MajorVersion { get; set; } public int MajorVersion { get; }
public int MinorVersion { get; set; } public int MinorVersion { get; }
public byte[] Random { get; set; } public byte[] Random { get; }
public DateTime Time public DateTime Time
{ {
get get
{ {
DateTime time = DateTime.MinValue; var time = DateTime.MinValue;
if (Random.Length > 3) if (Random.Length > 3)
{ {
time = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) time = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)
...@@ -40,17 +40,17 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -40,17 +40,17 @@ namespace Titanium.Web.Proxy.StreamExtended
} }
} }
public byte[] SessionId { get; set; } public byte[] SessionId { get; }
public int[] Ciphers { get; set; } public int[] Ciphers { get; }
public byte[] CompressionData { get; set; } public byte[]? CompressionData { get; internal set; }
internal int ClientHelloLength { get; set; } internal int ClientHelloLength { get; }
internal int EntensionsStartPosition { get; set; } internal int ExtensionsStartPosition { get; set; }
public Dictionary<string, SslExtension> Extensions { get; set; } public Dictionary<string, SslExtension>? Extensions { get; set; }
public SslProtocols SslProtocol public SslProtocols SslProtocol
{ {
...@@ -79,6 +79,17 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -79,6 +79,17 @@ namespace Titanium.Web.Proxy.StreamExtended
} }
} }
internal ClientHelloInfo(int handshakeVersion, int majorVersion, int minorVersion, byte[] random, byte[] sessionId, int[] ciphers, int clientHelloLength)
{
HandshakeVersion = handshakeVersion;
MajorVersion = majorVersion;
MinorVersion = minorVersion;
Random = random;
SessionId = sessionId;
Ciphers = ciphers;
ClientHelloLength = clientHelloLength;
}
private static string SslVersionToString(int major, int minor) private static string SslVersionToString(int major, int minor)
{ {
string str = "Unknown"; string str = "Unknown";
......
...@@ -9,68 +9,38 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -9,68 +9,38 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// Copies the source stream to destination stream. /// Copies the source stream to destination stream.
/// But this let users to peek and read the copying process. /// But this let users to peek and read the copying process.
/// </summary> /// </summary>
public class CopyStream : ICustomStreamReader, IDisposable internal class CopyStream : ILineStream, IDisposable
{ {
private readonly ICustomStreamReader reader; private readonly CustomBufferedStream reader;
private readonly ICustomStreamWriter writer; private readonly ICustomStreamWriter writer;
private readonly IBufferPool bufferPool; private readonly IBufferPool bufferPool;
public int BufferSize { get; }
private int bufferLength; private int bufferLength;
private byte[] buffer; private readonly byte[] buffer;
private bool disposed; private bool disposed;
public int Available => reader.Available;
public bool DataAvailable => reader.DataAvailable; public bool DataAvailable => reader.DataAvailable;
public long ReadBytes { get; private set; } public long ReadBytes { get; private set; }
public CopyStream(ICustomStreamReader reader, ICustomStreamWriter writer, IBufferPool bufferPool, int bufferSize) public CopyStream(CustomBufferedStream reader, ICustomStreamWriter writer, IBufferPool bufferPool)
{ {
this.reader = reader; this.reader = reader;
this.writer = writer; this.writer = writer;
BufferSize = bufferSize; buffer = bufferPool.GetBuffer();
buffer = bufferPool.GetBuffer(bufferSize);
this.bufferPool = bufferPool; this.bufferPool = bufferPool;
} }
public async Task<bool> FillBufferAsync(CancellationToken cancellationToken = default) public async ValueTask<bool> FillBufferAsync(CancellationToken cancellationToken = default)
{ {
await FlushAsync(cancellationToken); await FlushAsync(cancellationToken);
return await reader.FillBufferAsync(cancellationToken); return await reader.FillBufferAsync(cancellationToken);
} }
public byte PeekByteFromBuffer(int index)
{
return reader.PeekByteFromBuffer(index);
}
public Task<int> PeekByteAsync(int index, CancellationToken cancellationToken = default)
{
return reader.PeekByteAsync(index, cancellationToken);
}
public Task<int> PeekBytesAsync(byte[] buffer, int offset, int index, int size, CancellationToken cancellationToken = default)
{
return reader.PeekBytesAsync(buffer, offset, index, size, cancellationToken);
}
public void Flush()
{
// send out the current data from from the buffer
if (bufferLength > 0)
{
writer.Write(buffer, 0, bufferLength);
bufferLength = 0;
}
}
public async Task FlushAsync(CancellationToken cancellationToken = default) public async Task FlushAsync(CancellationToken cancellationToken = default)
{ {
// send out the current data from from the buffer // send out the current data from from the buffer
...@@ -89,45 +59,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -89,45 +59,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
return b; return b;
} }
public int Read(byte[] buffer, int offset, int count) public ValueTask<string?> ReadLineAsync(CancellationToken cancellationToken = default)
{
int result = reader.Read(buffer, offset, count);
if (result > 0)
{
if (bufferLength + result > BufferSize)
{
Flush();
}
Buffer.BlockCopy(buffer, offset, this.buffer, bufferLength, result);
bufferLength += result;
ReadBytes += result;
Flush();
}
return result;
}
public async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default)
{
int result = await reader.ReadAsync(buffer, offset, count, cancellationToken);
if (result > 0)
{
if (bufferLength + result > BufferSize)
{
await FlushAsync(cancellationToken);
}
Buffer.BlockCopy(buffer, offset, this.buffer, bufferLength, result);
bufferLength += result;
ReadBytes += result;
await FlushAsync(cancellationToken);
}
return result;
}
public Task<string> ReadLineAsync(CancellationToken cancellationToken = default)
{ {
return CustomBufferedStream.ReadLineInternalAsync(this, bufferPool, cancellationToken); return CustomBufferedStream.ReadLineInternalAsync(this, bufferPool, cancellationToken);
} }
...@@ -137,9 +69,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -137,9 +69,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
if (!disposed) if (!disposed)
{ {
disposed = true; disposed = true;
var b = buffer; bufferPool.ReturnBuffer(buffer);
buffer = null;
bufferPool.ReturnBuffer(b);
} }
} }
} }
......
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
internal class CustomBufferedPeekStream : ICustomStreamReader
{
private readonly IBufferPool bufferPool;
private readonly ICustomStreamReader baseStream;
internal int Position { get; private set; }
internal CustomBufferedPeekStream(ICustomStreamReader baseStream, IBufferPool bufferPool, int startPosition = 0)
{
this.bufferPool = bufferPool;
this.baseStream = baseStream;
Position = startPosition;
}
int ICustomStreamReader.BufferSize => baseStream.BufferSize;
/// <summary>
/// Gets a value indicating whether data is available.
/// </summary>
bool ICustomStreamReader.DataAvailable => Available > 0;
/// <summary>
/// Gets the available data size.
/// </summary>
public int Available => baseStream.Available - Position;
internal async Task<bool> EnsureBufferLength(int length, CancellationToken cancellationToken)
{
var val = await baseStream.PeekByteAsync(Position + length - 1, cancellationToken);
return val != -1;
}
internal byte ReadByte()
{
return baseStream.PeekByteFromBuffer(Position++);
}
internal int ReadInt16()
{
int i1 = ReadByte();
int i2 = ReadByte();
return (i1 << 8) + i2;
}
internal int ReadInt24()
{
int i1 = ReadByte();
int i2 = ReadByte();
int i3 = ReadByte();
return (i1 << 16) + (i2 << 8) + i3;
}
internal byte[] ReadBytes(int length)
{
var buffer = new byte[length];
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = ReadByte();
}
return buffer;
}
/// <summary>
/// Fills the buffer asynchronous.
/// </summary>
/// <returns></returns>
Task<bool> ICustomStreamReader.FillBufferAsync(CancellationToken cancellationToken)
{
return baseStream.FillBufferAsync(cancellationToken);
}
/// <summary>
/// Peeks a byte from buffer.
/// </summary>
/// <param name="index">The index.</param>
/// <returns></returns>
byte ICustomStreamReader.PeekByteFromBuffer(int index)
{
return baseStream.PeekByteFromBuffer(index);
}
/// <summary>
/// Peeks bytes asynchronous.
/// </summary>
/// <param name="buffer">The buffer to copy.</param>
/// <param name="offset">The offset where copying.</param>
/// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
Task<int> ICustomStreamReader.PeekBytesAsync(byte[] buffer, int offset, int index, int size, CancellationToken cancellationToken)
{
return baseStream.PeekBytesAsync(buffer, offset, index, size, cancellationToken);
}
/// <summary>
/// Peeks a byte asynchronous.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
Task<int> ICustomStreamReader.PeekByteAsync(int index, CancellationToken cancellationToken)
{
return baseStream.PeekByteAsync(index, cancellationToken);
}
/// <summary>
/// Reads a byte from buffer.
/// </summary>
/// <returns></returns>
/// <exception cref="Exception">Buffer is empty</exception>
byte ICustomStreamReader.ReadByteFromBuffer()
{
return ReadByte();
}
int ICustomStreamReader.Read(byte[] buffer, int offset, int count)
{
return baseStream.Read(buffer, offset, count);
}
/// <summary>
/// Reads the asynchronous.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The offset.</param>
/// <param name="count">The count.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
Task<int> ICustomStreamReader.ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return baseStream.ReadAsync(buffer, offset, count, cancellationToken);
}
/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<string> ICustomStreamReader.ReadLineAsync(CancellationToken cancellationToken)
{
return CustomBufferedStream.ReadLineInternalAsync(this, bufferPool, cancellationToken);
}
}
}
...@@ -5,6 +5,8 @@ using System.Net.Sockets; ...@@ -5,6 +5,8 @@ using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.StreamExtended.BufferPool; using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.StreamExtended.Network namespace Titanium.Web.Proxy.StreamExtended.Network
...@@ -15,13 +17,12 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -15,13 +17,12 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// of UTF-8 encoded string or raw bytes asynchronously from last read position. /// of UTF-8 encoded string or raw bytes asynchronously from last read position.
/// </summary> /// </summary>
/// <seealso cref="System.IO.Stream" /> /// <seealso cref="System.IO.Stream" />
public class CustomBufferedStream : Stream, ICustomStreamReader internal class CustomBufferedStream : Stream, IPeekStream, ILineStream
{ {
private readonly bool leaveOpen; private readonly bool leaveOpen;
private byte[] streamBuffer; private readonly byte[] streamBuffer;
// default to UTF-8 private static Encoding encoding => HttpHeader.Encoding;
private static readonly Encoding encoding = Encoding.UTF8;
private static readonly bool networkStreamHack = true; private static readonly bool networkStreamHack = true;
...@@ -35,11 +36,9 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -35,11 +36,9 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
private readonly IBufferPool bufferPool; private readonly IBufferPool bufferPool;
public int BufferSize { get; } public event EventHandler<DataEventArgs>? DataRead;
public event EventHandler<DataEventArgs> DataRead; public event EventHandler<DataEventArgs>? DataWrite;
public event EventHandler<DataEventArgs> DataWrite;
public Stream BaseStream { get; } public Stream BaseStream { get; }
...@@ -68,14 +67,12 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -68,14 +67,12 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// </summary> /// </summary>
/// <param name="baseStream">The base stream.</param> /// <param name="baseStream">The base stream.</param>
/// <param name="bufferPool">Bufferpool.</param> /// <param name="bufferPool">Bufferpool.</param>
/// <param name="bufferSize">Size of the buffer.</param>
/// <param name="leaveOpen"><see langword="true" /> to leave the stream open after disposing the <see cref="T:CustomBufferedStream" /> object; otherwise, <see langword="false" />.</param> /// <param name="leaveOpen"><see langword="true" /> to leave the stream open after disposing the <see cref="T:CustomBufferedStream" /> object; otherwise, <see langword="false" />.</param>
public CustomBufferedStream(Stream baseStream, IBufferPool bufferPool, int bufferSize, bool leaveOpen = false) public CustomBufferedStream(Stream baseStream, IBufferPool bufferPool, bool leaveOpen = false)
{ {
BaseStream = baseStream; BaseStream = baseStream;
BufferSize = bufferSize;
this.leaveOpen = leaveOpen; this.leaveOpen = leaveOpen;
streamBuffer = bufferPool.GetBuffer(bufferSize); streamBuffer = bufferPool.GetBuffer();
this.bufferPool = bufferPool; this.bufferPool = bufferPool;
} }
...@@ -160,7 +157,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -160,7 +157,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// <returns> /// <returns>
/// A task that represents the asynchronous copy operation. /// A task that represents the asynchronous copy operation.
/// </returns> /// </returns>
public override async Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken = default) public override async Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{ {
if (bufferLength > 0) if (bufferLength > 0)
{ {
...@@ -179,7 +176,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -179,7 +176,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// <returns> /// <returns>
/// A task that represents the asynchronous flush operation. /// A task that represents the asynchronous flush operation.
/// </returns> /// </returns>
public override Task FlushAsync(CancellationToken cancellationToken = default) public override Task FlushAsync(CancellationToken cancellationToken)
{ {
return BaseStream.FlushAsync(cancellationToken); return BaseStream.FlushAsync(cancellationToken);
} }
...@@ -204,7 +201,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -204,7 +201,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// less than the requested number, or it can be 0 (zero) /// less than the requested number, or it can be 0 (zero)
/// if the end of the stream has been reached. /// if the end of the stream has been reached.
/// </returns> /// </returns>
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default) public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{ {
if (bufferLength == 0) if (bufferLength == 0)
{ {
...@@ -222,6 +219,45 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -222,6 +219,45 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
return available; return available;
} }
/// <summary>
/// Asynchronously reads a sequence of bytes from the current stream,
/// advances the position within the stream by the number of bytes read,
/// and monitors cancellation requests.
/// </summary>
/// <param name="buffer">The buffer to write the data into.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.
/// The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param>
/// <returns>
/// A task that represents the asynchronous read operation.
/// The value of the parameter contains the total
/// number of bytes read into the buffer.
/// The result value can be less than the number of bytes
/// requested if the number of bytes currently available is
/// less than the requested number, or it can be 0 (zero)
/// if the end of the stream has been reached.
/// </returns>
#if NETSTANDARD2_1
public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
#else
public async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
#endif
{
if (bufferLength == 0)
{
await FillBufferAsync(cancellationToken);
}
int available = Math.Min(bufferLength, buffer.Length);
if (available > 0)
{
new Span<byte>(streamBuffer, bufferPos, available).CopyTo(buffer.Span);
bufferPos += available;
bufferLength -= available;
}
return available;
}
/// <summary> /// <summary>
/// Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream. /// Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream.
/// </summary> /// </summary>
...@@ -250,25 +286,24 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -250,25 +286,24 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// <param name="index">The index.</param> /// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns> /// <returns></returns>
public async Task<int> PeekByteAsync(int index, CancellationToken cancellationToken = default) public async ValueTask<int> PeekByteAsync(int index, CancellationToken cancellationToken = default)
{ {
if (Available <= index)
{
await FillBufferAsync(cancellationToken);
}
// When index is greater than the buffer size // When index is greater than the buffer size
if (streamBuffer.Length <= index) if (streamBuffer.Length <= index)
{ {
throw new Exception("Requested Peek index exceeds the buffer size. Consider increasing the buffer size."); throw new Exception("Requested Peek index exceeds the buffer size. Consider increasing the buffer size.");
} }
// When index is greater than the buffer size while (Available <= index)
if (Available <= index)
{ {
return -1; // When index is greater than the buffer size
bool fillResult = await FillBufferAsync(cancellationToken);
if (!fillResult)
{
return -1;
}
} }
return streamBuffer[bufferPos + index]; return streamBuffer[bufferPos + index];
} }
...@@ -278,29 +313,33 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -278,29 +313,33 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// <param name="buffer">The buffer to copy.</param> /// <param name="buffer">The buffer to copy.</param>
/// <param name="offset">The offset where copying.</param> /// <param name="offset">The offset where copying.</param>
/// <param name="index">The index.</param> /// <param name="index">The index.</param>
/// <param name="count">The count.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns> /// <returns></returns>
public async Task<int> PeekBytesAsync(byte[] buffer, int offset, int index, int size, CancellationToken cancellationToken = default) public async ValueTask<int> PeekBytesAsync(byte[] buffer, int offset, int index, int count, CancellationToken cancellationToken = default)
{ {
if (Available <= index)
{
await FillBufferAsync(cancellationToken);
}
// When index is greater than the buffer size // When index is greater than the buffer size
if (streamBuffer.Length <= (index + size)) if (streamBuffer.Length <= index + count)
{ {
throw new Exception("Requested Peek index and size exceeds the buffer size. Consider increasing the buffer size."); throw new Exception("Requested Peek index and size exceeds the buffer size. Consider increasing the buffer size.");
} }
if (Available <= (index + size)) while (Available <= index)
{ {
return -1; bool fillResult = await FillBufferAsync(cancellationToken);
if (!fillResult)
{
return 0;
}
} }
Buffer.BlockCopy(streamBuffer, index, buffer, offset, size); if (Available - index < count)
{
count = Available - index;
}
return size; Buffer.BlockCopy(streamBuffer, index, buffer, offset, count);
return count;
} }
/// <summary> /// <summary>
...@@ -346,7 +385,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -346,7 +385,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// A task that represents the asynchronous write operation. /// A task that represents the asynchronous write operation.
/// </returns> /// </returns>
[DebuggerStepThrough] [DebuggerStepThrough]
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default) public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{ {
OnDataWrite(buffer, offset, count); OnDataWrite(buffer, offset, count);
...@@ -359,7 +398,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -359,7 +398,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// <param name="value">The byte to write to the stream.</param> /// <param name="value">The byte to write to the stream.</param>
public override void WriteByte(byte value) public override void WriteByte(byte value)
{ {
var buffer = bufferPool.GetBuffer(BufferSize); var buffer = bufferPool.GetBuffer();
try try
{ {
buffer[0] = value; buffer[0] = value;
...@@ -397,9 +436,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -397,9 +436,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
BaseStream.Dispose(); BaseStream.Dispose();
} }
var buffer = streamBuffer; bufferPool.ReturnBuffer(streamBuffer);
streamBuffer = null;
bufferPool.ReturnBuffer(buffer);
} }
} }
...@@ -512,13 +549,19 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -512,13 +549,19 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// </summary> /// </summary>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns> /// <returns></returns>
public async Task<bool> FillBufferAsync(CancellationToken cancellationToken = default) public async ValueTask<bool> FillBufferAsync(CancellationToken cancellationToken = default)
{ {
if (closed) if (closed)
{ {
throw new Exception("Stream is already closed"); throw new Exception("Stream is already closed");
} }
int bytesToRead = streamBuffer.Length - bufferLength;
if (bytesToRead == 0)
{
return false;
}
if (bufferLength > 0) if (bufferLength > 0)
{ {
// normally we fill the buffer only when it is empty, but sometimes we need more data // normally we fill the buffer only when it is empty, but sometimes we need more data
...@@ -526,12 +569,6 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -526,12 +569,6 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
Buffer.BlockCopy(streamBuffer, bufferPos, streamBuffer, 0, bufferLength); Buffer.BlockCopy(streamBuffer, bufferPos, streamBuffer, 0, bufferLength);
} }
int bytesToRead = streamBuffer.Length - bufferLength;
if (bytesToRead == 0)
{
return false;
}
bufferPos = 0; bufferPos = 0;
bool result = false; bool result = false;
...@@ -560,7 +597,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -560,7 +597,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// Read a line from the byte stream /// Read a line from the byte stream
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public Task<string> ReadLineAsync(CancellationToken cancellationToken = default) public ValueTask<string?> ReadLineAsync(CancellationToken cancellationToken = default)
{ {
return ReadLineInternalAsync(this, bufferPool, cancellationToken); return ReadLineInternalAsync(this, bufferPool, cancellationToken);
} }
...@@ -569,14 +606,14 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -569,14 +606,14 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// Read a line from the byte stream /// Read a line from the byte stream
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
internal static async Task<string> ReadLineInternalAsync(ICustomStreamReader reader, IBufferPool bufferPool, CancellationToken cancellationToken = default) internal static async ValueTask<string?> ReadLineInternalAsync(ILineStream reader, IBufferPool bufferPool, CancellationToken cancellationToken = default)
{ {
byte lastChar = default; byte lastChar = default;
int bufferDataLength = 0; int bufferDataLength = 0;
// try to use buffer from the buffer pool, usually it is enough // try to use buffer from the buffer pool, usually it is enough
var bufferPoolBuffer = bufferPool.GetBuffer(reader.BufferSize); var bufferPoolBuffer = bufferPool.GetBuffer();
var buffer = bufferPoolBuffer; var buffer = bufferPoolBuffer;
try try
......
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
/// <summary>
/// This concrete implemetation of interface acts as the source stream for CopyStream class.
/// </summary>
public interface ICustomStreamReader
{
int BufferSize { get; }
int Available { get; }
bool DataAvailable { get; }
/// <summary>
/// Fills the buffer asynchronous.
/// </summary>
/// <returns></returns>
Task<bool> FillBufferAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Peeks a byte from buffer.
/// </summary>
/// <param name="index">The index.</param>
/// <returns></returns>
/// <exception cref="Exception">Index is out of buffer size</exception>
byte PeekByteFromBuffer(int index);
/// <summary>
/// Peeks a byte asynchronous.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
Task<int> PeekByteAsync(int index, CancellationToken cancellationToken = default);
/// <summary>
/// Peeks bytes asynchronous.
/// </summary>
/// <param name="buffer">The buffer to copy.</param>
/// <param name="offset">The offset where copying.</param>
/// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
Task<int> PeekBytesAsync(byte[] buffer, int offset, int index, int size, CancellationToken cancellationToken = default);
byte ReadByteFromBuffer();
/// <summary>
/// When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
/// </summary>
/// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between <paramref name="offset" /> and (<paramref name="offset" /> + <paramref name="count" /> - 1) replaced by the bytes read from the current source.</param>
/// <param name="offset">The zero-based byte offset in <paramref name="buffer" /> at which to begin storing the data read from the current stream.</param>
/// <param name="count">The maximum number of bytes to be read from the current stream.</param>
/// <returns>
/// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
/// </returns>
int Read(byte[] buffer, int offset, int count);
/// <summary>
/// Read the specified number (or less) of raw bytes from the base stream to the given buffer to the specified offset
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="bytesToRead"></param>
/// <param name="cancellationToken"></param>
/// <returns>The number of bytes read</returns>
Task<int> ReadAsync(byte[] buffer, int offset, int bytesToRead,
CancellationToken cancellationToken = default);
/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <returns></returns>
Task<string> ReadLineAsync(CancellationToken cancellationToken = default);
}
}
using System.Threading;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
public interface ILineStream
{
bool DataAvailable { get; }
/// <summary>
/// Fills the buffer asynchronous.
/// </summary>
/// <returns></returns>
ValueTask<bool> FillBufferAsync(CancellationToken cancellationToken = default);
byte ReadByteFromBuffer();
/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <returns></returns>
ValueTask<string?> ReadLineAsync(CancellationToken cancellationToken = default);
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
public interface IPeekStream
{
/// <summary>
/// Peeks a byte from buffer.
/// </summary>
/// <param name="index">The index.</param>
/// <returns></returns>
/// <exception cref="Exception">Index is out of buffer size</exception>
byte PeekByteFromBuffer(int index);
/// <summary>
/// Peeks a byte asynchronous.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
ValueTask<int> PeekByteAsync(int index, CancellationToken cancellationToken = default);
/// <summary>
/// Peeks bytes asynchronous.
/// </summary>
/// <param name="buffer">The buffer to copy.</param>
/// <param name="offset">The offset where copying.</param>
/// <param name="index">The index.</param>
/// <param name="count">The count.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
ValueTask<int> PeekBytesAsync(byte[] buffer, int offset, int index, int count, CancellationToken cancellationToken = default);
}
}
\ No newline at end of file
using System;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
internal class PeekStreamReader
{
private readonly IPeekStream baseStream;
public int Position { get; private set; }
public PeekStreamReader(IPeekStream baseStream, int startPosition = 0)
{
this.baseStream = baseStream;
Position = startPosition;
}
public async ValueTask<bool> EnsureBufferLength(int length, CancellationToken cancellationToken)
{
var val = await baseStream.PeekByteAsync(Position + length - 1, cancellationToken);
return val != -1;
}
public byte ReadByte()
{
return baseStream.PeekByteFromBuffer(Position++);
}
public int ReadInt16()
{
int i1 = ReadByte();
int i2 = ReadByte();
return (i1 << 8) + i2;
}
public int ReadInt24()
{
int i1 = ReadByte();
int i2 = ReadByte();
int i3 = ReadByte();
return (i1 << 16) + (i2 << 8) + i3;
}
public byte[] ReadBytes(int length)
{
var buffer = new byte[length];
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = ReadByte();
}
return buffer;
}
}
}
...@@ -7,7 +7,6 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -7,7 +7,6 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
/// <summary> /// <summary>
/// Mimic a Task but you can set AsyncState /// Mimic a Task but you can set AsyncState
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam>
public class TaskResult : IAsyncResult public class TaskResult : IAsyncResult
{ {
Task Task; Task Task;
...@@ -31,7 +30,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network ...@@ -31,7 +30,7 @@ namespace Titanium.Web.Proxy.StreamExtended.Network
} }
/// <summary> /// <summary>
/// Mimic a Task<T> but you can set AsyncState /// Mimic a Task&lt;T&gt; but you can set AsyncState
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public class TaskResult<T> : IAsyncResult public class TaskResult<T> : IAsyncResult
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
...@@ -16,13 +16,25 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -16,13 +16,25 @@ namespace Titanium.Web.Proxy.StreamExtended
"DEFLATE" "DEFLATE"
}; };
public int HandshakeVersion { get; set; } public ServerHelloInfo(int handshakeVersion, int majorVersion, int minorVersion, byte[] random,
byte[] sessionId, int cipherSuite, int serverHelloLength)
{
HandshakeVersion = handshakeVersion;
MajorVersion = majorVersion;
MinorVersion = minorVersion;
Random = random;
SessionId = sessionId;
CipherSuite = cipherSuite;
ServerHelloLength = serverHelloLength;
}
public int HandshakeVersion { get; }
public int MajorVersion { get; set; } public int MajorVersion { get; }
public int MinorVersion { get; set; } public int MinorVersion { get; }
public byte[] Random { get; set; } public byte[] Random { get; }
public DateTime Time public DateTime Time
{ {
...@@ -39,17 +51,17 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -39,17 +51,17 @@ namespace Titanium.Web.Proxy.StreamExtended
} }
} }
public byte[] SessionId { get; set; } public byte[] SessionId { get; }
public int CipherSuite { get; set; } public int CipherSuite { get; }
public byte CompressionMethod { get; set; } public byte CompressionMethod { get; set; }
internal int ServerHelloLength { get; set; } internal int ServerHelloLength { get; }
internal int EntensionsStartPosition { get; set; } internal int EntensionsStartPosition { get; set; }
public Dictionary<string, SslExtension> Extensions { get; set; } public Dictionary<string, SslExtension>? Extensions { get; set; }
private static string SslVersionToString(int major, int minor) private static string SslVersionToString(int major, int minor)
{ {
...@@ -109,4 +121,4 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -109,4 +121,4 @@ namespace Titanium.Web.Proxy.StreamExtended
return sb.ToString(); return sb.ToString();
} }
} }
} }
\ No newline at end of file
...@@ -10,21 +10,8 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -10,21 +10,8 @@ namespace Titanium.Web.Proxy.StreamExtended
/// <summary> /// <summary>
/// Use this class to peek SSL client/server hello information. /// Use this class to peek SSL client/server hello information.
/// </summary> /// </summary>
public class SslTools internal class SslTools
{ {
/// <summary>
/// Is the given stream starts with an SSL client hello?
/// </summary>
/// <param name="stream"></param>
/// <param name="bufferPool"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<bool> IsClientHello(CustomBufferedStream stream, IBufferPool bufferPool, CancellationToken cancellationToken)
{
var clientHello = await PeekClientHello(stream, bufferPool, cancellationToken);
return clientHello != null;
}
/// <summary> /// <summary>
/// Peek the SSL client hello information. /// Peek the SSL client hello information.
/// </summary> /// </summary>
...@@ -32,7 +19,7 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -32,7 +19,7 @@ namespace Titanium.Web.Proxy.StreamExtended
/// <param name="bufferPool"></param> /// <param name="bufferPool"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
public static async Task<ClientHelloInfo> PeekClientHello(CustomBufferedStream clientStream, IBufferPool bufferPool, CancellationToken cancellationToken = default) public static async Task<ClientHelloInfo?> PeekClientHello(CustomBufferedStream clientStream, IBufferPool bufferPool, CancellationToken cancellationToken = default)
{ {
// detects the HTTPS ClientHello message as it is described in the following url: // detects the HTTPS ClientHello message as it is described in the following url:
// https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format // https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format
...@@ -46,7 +33,7 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -46,7 +33,7 @@ namespace Titanium.Web.Proxy.StreamExtended
if ((recordType & 0x80) == 0x80) if ((recordType & 0x80) == 0x80)
{ {
// SSL 2 // SSL 2
var peekStream = new CustomBufferedPeekStream(clientStream, bufferPool, 1); var peekStream = new PeekStreamReader(clientStream, 1);
// length value + minimum length // length value + minimum length
if (!await peekStream.EnsureBufferLength(10, cancellationToken)) if (!await peekStream.EnsureBufferLength(10, cancellationToken))
...@@ -88,22 +75,14 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -88,22 +75,14 @@ namespace Titanium.Web.Proxy.StreamExtended
byte[] sessionId = peekStream.ReadBytes(sessionIdLength); byte[] sessionId = peekStream.ReadBytes(sessionIdLength);
byte[] random = peekStream.ReadBytes(randomLength); byte[] random = peekStream.ReadBytes(randomLength);
var clientHelloInfo = new ClientHelloInfo var clientHelloInfo = new ClientHelloInfo(2, majorVersion, minorVersion, random, sessionId, ciphers,
{ peekStream.Position);
HandshakeVersion = 2,
MajorVersion = majorVersion,
MinorVersion = minorVersion,
Random = random,
SessionId = sessionId,
Ciphers = ciphers,
ClientHelloLength = peekStream.Position,
};
return clientHelloInfo; return clientHelloInfo;
} }
else if (recordType == 0x16) else if (recordType == 0x16)
{ {
var peekStream = new CustomBufferedPeekStream(clientStream, bufferPool, 1); var peekStream = new PeekStreamReader(clientStream, 1);
// should contain at least 43 bytes // should contain at least 43 bytes
// 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length // 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length
...@@ -169,26 +148,19 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -169,26 +148,19 @@ namespace Titanium.Web.Proxy.StreamExtended
byte[] compressionData = peekStream.ReadBytes(length); byte[] compressionData = peekStream.ReadBytes(length);
int extenstionsStartPosition = peekStream.Position; int extensionsStartPosition = peekStream.Position;
Dictionary<string, SslExtension> extensions = null; Dictionary<string, SslExtension>? extensions = null;
if(extenstionsStartPosition < recordLength + 5) if(extensionsStartPosition < recordLength + 5)
{ {
extensions = await ReadExtensions(majorVersion, minorVersion, peekStream, bufferPool, cancellationToken); extensions = await ReadExtensions(majorVersion, minorVersion, peekStream, bufferPool, cancellationToken);
} }
var clientHelloInfo = new ClientHelloInfo var clientHelloInfo = new ClientHelloInfo(3, majorVersion, minorVersion, random, sessionId, ciphers, peekStream.Position)
{ {
HandshakeVersion = 3, ExtensionsStartPosition = extensionsStartPosition,
MajorVersion = majorVersion,
MinorVersion = minorVersion,
Random = random,
SessionId = sessionId,
Ciphers = ciphers,
CompressionData = compressionData, CompressionData = compressionData,
ClientHelloLength = peekStream.Position,
EntensionsStartPosition = extenstionsStartPosition,
Extensions = extensions, Extensions = extensions,
}; };
...@@ -218,7 +190,7 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -218,7 +190,7 @@ namespace Titanium.Web.Proxy.StreamExtended
/// <param name="bufferPool"></param> /// <param name="bufferPool"></param>
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
public static async Task<ServerHelloInfo> PeekServerHello(CustomBufferedStream serverStream, IBufferPool bufferPool, CancellationToken cancellationToken = default) public static async Task<ServerHelloInfo?> PeekServerHello(CustomBufferedStream serverStream, IBufferPool bufferPool, CancellationToken cancellationToken = default)
{ {
// detects the HTTPS ClientHello message as it is described in the following url: // detects the HTTPS ClientHello message as it is described in the following url:
// https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format // https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format
...@@ -233,7 +205,7 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -233,7 +205,7 @@ namespace Titanium.Web.Proxy.StreamExtended
{ {
// SSL 2 // SSL 2
// not tested. SSL2 is deprecated // not tested. SSL2 is deprecated
var peekStream = new CustomBufferedPeekStream(serverStream, bufferPool, 1); var peekStream = new PeekStreamReader(serverStream, 1);
// length value + minimum length // length value + minimum length
if (!await peekStream.EnsureBufferLength(39, cancellationToken)) if (!await peekStream.EnsureBufferLength(39, cancellationToken))
...@@ -267,22 +239,14 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -267,22 +239,14 @@ namespace Titanium.Web.Proxy.StreamExtended
byte[] sessionId = peekStream.ReadBytes(1); byte[] sessionId = peekStream.ReadBytes(1);
int cipherSuite = peekStream.ReadInt16(); int cipherSuite = peekStream.ReadInt16();
var serverHelloInfo = new ServerHelloInfo var serverHelloInfo = new ServerHelloInfo(2, majorVersion, minorVersion, random, sessionId, cipherSuite,
{ peekStream.Position);
HandshakeVersion = 2,
MajorVersion = majorVersion,
MinorVersion = minorVersion,
Random = random,
SessionId = sessionId,
CipherSuite = cipherSuite,
ServerHelloLength = peekStream.Position,
};
return serverHelloInfo; return serverHelloInfo;
} }
else if (recordType == 0x16) else if (recordType == 0x16)
{ {
var peekStream = new CustomBufferedPeekStream(serverStream, bufferPool, 1); var peekStream = new PeekStreamReader(serverStream, 1);
// should contain at least 43 bytes // should contain at least 43 bytes
// 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length // 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length
...@@ -324,23 +288,16 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -324,23 +288,16 @@ namespace Titanium.Web.Proxy.StreamExtended
int extenstionsStartPosition = peekStream.Position; int extenstionsStartPosition = peekStream.Position;
Dictionary<string, SslExtension> extensions = null; Dictionary<string, SslExtension>? extensions = null;
if (extenstionsStartPosition < recordLength + 5) if (extenstionsStartPosition < recordLength + 5)
{ {
extensions = await ReadExtensions(majorVersion, minorVersion, peekStream, bufferPool, cancellationToken); extensions = await ReadExtensions(majorVersion, minorVersion, peekStream, bufferPool, cancellationToken);
} }
var serverHelloInfo = new ServerHelloInfo var serverHelloInfo = new ServerHelloInfo(3, majorVersion, minorVersion, random, sessionId, cipherSuite, peekStream.Position)
{ {
HandshakeVersion = 3,
MajorVersion = majorVersion,
MinorVersion = minorVersion,
Random = random,
SessionId = sessionId,
CipherSuite = cipherSuite,
CompressionMethod = compressionMethod, CompressionMethod = compressionMethod,
ServerHelloLength = peekStream.Position,
EntensionsStartPosition = extenstionsStartPosition, EntensionsStartPosition = extenstionsStartPosition,
Extensions = extensions, Extensions = extensions,
}; };
...@@ -351,24 +308,24 @@ namespace Titanium.Web.Proxy.StreamExtended ...@@ -351,24 +308,24 @@ namespace Titanium.Web.Proxy.StreamExtended
return null; return null;
} }
private static async Task<Dictionary<string, SslExtension>> ReadExtensions(int majorVersion, int minorVersion, CustomBufferedPeekStream peekStream, IBufferPool bufferPool, CancellationToken cancellationToken) private static async Task<Dictionary<string, SslExtension>?> ReadExtensions(int majorVersion, int minorVersion, PeekStreamReader peekStreamReader, IBufferPool bufferPool, CancellationToken cancellationToken)
{ {
Dictionary<string, SslExtension> extensions = null; Dictionary<string, SslExtension>? extensions = null;
if (majorVersion > 3 || majorVersion == 3 && minorVersion >= 1) if (majorVersion > 3 || majorVersion == 3 && minorVersion >= 1)
{ {
if (await peekStream.EnsureBufferLength(2, cancellationToken)) if (await peekStreamReader.EnsureBufferLength(2, cancellationToken))
{ {
int extensionsLength = peekStream.ReadInt16(); int extensionsLength = peekStreamReader.ReadInt16();
if (await peekStream.EnsureBufferLength(extensionsLength, cancellationToken)) if (await peekStreamReader.EnsureBufferLength(extensionsLength, cancellationToken))
{ {
extensions = new Dictionary<string, SslExtension>(); extensions = new Dictionary<string, SslExtension>();
int idx = 0; int idx = 0;
while (extensionsLength > 3) while (extensionsLength > 3)
{ {
int id = peekStream.ReadInt16(); int id = peekStreamReader.ReadInt16();
int length = peekStream.ReadInt16(); int length = peekStreamReader.ReadInt16();
byte[] data = peekStream.ReadBytes(length); byte[] data = peekStreamReader.ReadBytes(length);
var extension = SslExtensions.GetExtension(id, data, idx++); var extension = SslExtensions.GetExtension(id, data, idx++);
extensions[extension.Name] = extension; extensions[extension.Name] = extension;
extensionsLength -= 4 + length; extensionsLength -= 4 + length;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<SignAssembly>True</SignAssembly> <SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<LangVersion>7.1</LangVersion> <LangVersion>8.0</LangVersion>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
</PropertyGroup> </PropertyGroup>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign> <DelaySign>False</DelaySign>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<LangVersion>7.1</LangVersion> <LangVersion>8.0</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
...@@ -19,19 +19,19 @@ ...@@ -19,19 +19,19 @@
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.Win32.Registry"> <PackageReference Include="Microsoft.Win32.Registry">
<Version>4.5.0</Version> <Version>4.6.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.Security.Principal.Windows"> <PackageReference Include="System.Security.Principal.Windows">
<Version>4.5.1</Version> <Version>4.6.0</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'"> <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
<PackageReference Include="Microsoft.Win32.Registry"> <PackageReference Include="Microsoft.Win32.Registry">
<Version>4.5.0</Version> <Version>4.6.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.Security.Principal.Windows"> <PackageReference Include="System.Security.Principal.Windows">
<Version>4.5.1</Version> <Version>4.6.0</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
......
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;netcoreapp2.1</TargetFrameworks> <TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<RootNamespace>Titanium.Web.Proxy</RootNamespace> <RootNamespace>Titanium.Web.Proxy</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<SignAssembly>True</SignAssembly> <SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign> <DelaySign>False</DelaySign>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<LangVersion>7.1</LangVersion> <Nullable>enable</Nullable>
<LangVersion>8.0</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.3" /> <PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5" /> <PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
<PackageReference Include="System.Buffers" Version="4.5.0" /> <PackageReference Include="System.Buffers" Version="4.5.0" />
<PackageReference Include="System.Memory" Version="4.5.3" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.3" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.Win32.Registry"> <PackageReference Include="Microsoft.Win32.Registry">
<Version>4.5.0</Version> <Version>4.6.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.Security.Principal.Windows"> <PackageReference Include="System.Security.Principal.Windows">
<Version>4.5.1</Version> <Version>4.6.0</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'"> <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
<PackageReference Include="Microsoft.Win32.Registry"> <PackageReference Include="Microsoft.Win32.Registry">
<Version>4.5.0</Version> <Version>4.6.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="System.Security.Principal.Windows"> <PackageReference Include="System.Security.Principal.Windows">
<Version>4.5.1</Version> <Version>4.6.0</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
......
...@@ -17,21 +17,25 @@ ...@@ -17,21 +17,25 @@
<group targetFramework="netstandard2.0"> <group targetFramework="netstandard2.0">
<dependency id="Portable.BouncyCastle" version="1.8.5" /> <dependency id="Portable.BouncyCastle" version="1.8.5" />
<dependency id="BrotliSharpLib" version="0.3.3" /> <dependency id="BrotliSharpLib" version="0.3.3" />
<dependency id="Microsoft.Win32.Registry" version="4.5.0" /> <dependency id="Microsoft.Win32.Registry" version="4.6.0" />
<dependency id="System.Buffers" version="4.5.0" /> <dependency id="System.Buffers" version="4.5.0" />
<dependency id="System.Security.Principal.Windows" version="4.5.1" /> <dependency id="System.Memory" version="4.5.3" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3" />
<dependency id="System.Security.Principal.Windows" version="4.6.0" />
</group> </group>
<group targetFramework="netcoreapp2.1"> <group targetFramework="netstandard2.1">
<dependency id="Portable.BouncyCastle" version="1.8.5" /> <dependency id="Portable.BouncyCastle" version="1.8.5" />
<dependency id="BrotliSharpLib" version="0.3.3" /> <dependency id="BrotliSharpLib" version="0.3.3" />
<dependency id="Microsoft.Win32.Registry" version="4.5.0" /> <dependency id="Microsoft.Win32.Registry" version="4.6.0" />
<dependency id="System.Buffers" version="4.5.0" /> <dependency id="System.Buffers" version="4.5.0" />
<dependency id="System.Security.Principal.Windows" version="4.5.1" /> <dependency id="System.Memory" version="4.5.3" />
<dependency id="System.Threading.Tasks.Extensions" version="4.5.3" />
<dependency id="System.Security.Principal.Windows" version="4.6.0" />
</group> </group>
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>
<file src="bin\$configuration$\netstandard2.0\Titanium.Web.Proxy.dll" target="lib\netstandard2.0" /> <file src="bin\$configuration$\netstandard2.0\Titanium.Web.Proxy.dll" target="lib\netstandard2.0" />
<file src="bin\$configuration$\netcoreapp2.1\Titanium.Web.Proxy.dll" target="lib\netcoreapp2.1" /> <file src="bin\$configuration$\netstandard2.1\Titanium.Web.Proxy.dll" target="lib\netstandard2.1" />
</files> </files>
</package> </package>
...@@ -12,6 +12,7 @@ using Titanium.Web.Proxy.Exceptions; ...@@ -12,6 +12,7 @@ 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; using Titanium.Web.Proxy.StreamExtended.Network;
...@@ -32,26 +33,22 @@ namespace Titanium.Web.Proxy ...@@ -32,26 +33,22 @@ namespace Titanium.Web.Proxy
var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferPool, BufferSize); var clientStream = new CustomBufferedStream(clientConnection.GetStream(), BufferPool);
var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize); var clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool);
SslStream sslStream = null; SslStream? sslStream = null;
try try
{ {
var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken); var clientHelloInfo = await SslTools.PeekClientHello(clientStream, BufferPool, cancellationToken);
bool isHttps = clientHelloInfo != null; string? httpsHostName = null;
string httpsHostName = null;
if (isHttps) if (clientHelloInfo != null)
{ {
httpsHostName = clientHelloInfo.GetServerName() ?? endPoint.GenericCertificateName; httpsHostName = clientHelloInfo.GetServerName() ?? endPoint.GenericCertificateName;
var args = new BeforeSslAuthenticateEventArgs(cancellationTokenSource) var args = new BeforeSslAuthenticateEventArgs(cancellationTokenSource, httpsHostName);
{
SniHostName = httpsHostName
};
await endPoint.InvokeBeforeSslAuthenticate(this, args, ExceptionFunc); await endPoint.InvokeBeforeSslAuthenticate(this, args, ExceptionFunc);
...@@ -65,7 +62,7 @@ namespace Titanium.Web.Proxy ...@@ -65,7 +62,7 @@ namespace Titanium.Web.Proxy
clientConnection.SslProtocol = clientHelloInfo.SslProtocol; clientConnection.SslProtocol = clientHelloInfo.SslProtocol;
// do client authentication using certificate // do client authentication using certificate
X509Certificate2 certificate = null; X509Certificate2? certificate = null;
try try
{ {
sslStream = new SslStream(clientStream, false); sslStream = new SslStream(clientStream, false);
...@@ -78,18 +75,15 @@ namespace Titanium.Web.Proxy ...@@ -78,18 +75,15 @@ 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 CustomBufferedStream(sslStream, BufferPool, BufferSize); clientStream = new CustomBufferedStream(sslStream, BufferPool);
clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool, BufferSize); clientStreamWriter = new HttpResponseWriter(clientStream, BufferPool);
} }
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, cancellationTokenSource) var session = new SessionEventArgs(this, endPoint, new ProxyClient(clientConnection, clientStream, clientStreamWriter), null,
{ cancellationTokenSource);
ProxyClient = { Connection = clientConnection },
HttpClient = { ConnectRequest = null }
};
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);
} }
...@@ -98,7 +92,7 @@ namespace Titanium.Web.Proxy ...@@ -98,7 +92,7 @@ namespace Titanium.Web.Proxy
else else
{ {
var connection = await tcpConnectionFactory.GetServerConnection(httpsHostName, endPoint.Port, var connection = await tcpConnectionFactory.GetServerConnection(httpsHostName, endPoint.Port,
httpVersion: null, isHttps: false, applicationProtocols: null, httpVersion: HttpHeader.VersionUnknown, isHttps: false, applicationProtocols: null,
isConnect: true, proxyServer: this, session:null, upStreamEndPoint: UpStreamEndPoint, isConnect: true, proxyServer: this, session:null, upStreamEndPoint: UpStreamEndPoint,
externalProxy: UpStreamHttpsProxy, noCache: true, cancellationToken: cancellationToken); externalProxy: UpStreamHttpsProxy, noCache: true, cancellationToken: cancellationToken);
...@@ -109,7 +103,7 @@ namespace Titanium.Web.Proxy ...@@ -109,7 +103,7 @@ namespace Titanium.Web.Proxy
if (available > 0) if (available > 0)
{ {
// send the buffered data // send the buffered data
var data = BufferPool.GetBuffer(BufferSize); var data = BufferPool.GetBuffer();
try try
{ {
// clientStream.Available should be at most BufferSize because it is using the same buffer size // clientStream.Available should be at most BufferSize because it is using the same buffer size
...@@ -124,7 +118,7 @@ namespace Titanium.Web.Proxy ...@@ -124,7 +118,7 @@ namespace Titanium.Web.Proxy
if (!clientStream.IsClosed && !connection.Stream.IsClosed) if (!clientStream.IsClosed && !connection.Stream.IsClosed)
{ {
await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool, BufferSize, await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool,
null, null, cancellationTokenSource, ExceptionFunc); null, null, cancellationTokenSource, ExceptionFunc);
} }
} }
...@@ -136,10 +130,10 @@ namespace Titanium.Web.Proxy ...@@ -136,10 +130,10 @@ namespace Titanium.Web.Proxy
return; return;
} }
} }
// 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, clientStreamWriter, await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientStreamWriter, cancellationTokenSource);
cancellationTokenSource, isHttps ? httpsHostName : null, null, null);
} }
catch (ProxyException e) catch (ProxyException e)
{ {
......
...@@ -16,25 +16,23 @@ namespace Titanium.Web.Proxy ...@@ -16,25 +16,23 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// Handle upgrade to websocket /// Handle upgrade to websocket
/// </summary> /// </summary>
private async Task handleWebSocketUpgrade(string httpCmd, private async Task handleWebSocketUpgrade(string requestHttpMethod, string requestHttpUrl, Version requestVersion,
SessionEventArgs args, Request request, Response response, SessionEventArgs args, Request request, Response response,
CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter, CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter,
TcpServerConnection serverConnection, TcpServerConnection serverConnection,
CancellationTokenSource cancellationTokenSource, CancellationToken cancellationToken) CancellationTokenSource cancellationTokenSource, CancellationToken cancellationToken)
{ {
// prepare the prefix content // prepare the prefix content
await serverConnection.StreamWriter.WriteLineAsync(httpCmd, cancellationToken); var headerBuilder = new HeaderBuilder();
await serverConnection.StreamWriter.WriteHeadersAsync(request.Headers, headerBuilder.WriteRequestLine(requestHttpMethod, requestHttpUrl, requestVersion);
cancellationToken: cancellationToken); headerBuilder.WriteHeaders(request.Headers);
await serverConnection.StreamWriter.WriteHeadersAsync(headerBuilder, cancellationToken);
string httpStatus; string httpStatus;
try try
{ {
httpStatus = await serverConnection.Stream.ReadLineAsync(cancellationToken); httpStatus = await serverConnection.Stream.ReadLineAsync(cancellationToken)
if (httpStatus == null) ?? throw new ServerConnectionException("Server connection was closed.");
{
throw new ServerConnectionException("Server connection was closed.");
}
} }
catch (Exception e) when (!(e is ServerConnectionException)) catch (Exception e) when (!(e is ServerConnectionException))
{ {
...@@ -60,13 +58,11 @@ namespace Titanium.Web.Proxy ...@@ -60,13 +58,11 @@ namespace Titanium.Web.Proxy
// If user requested call back then do it // If user requested call back then do it
if (!args.HttpClient.Response.Locked) if (!args.HttpClient.Response.Locked)
{ {
await invokeBeforeResponse(args); await onBeforeResponse(args);
} }
await TcpHelper.SendRaw(clientStream, serverConnection.Stream, BufferPool, BufferSize, await TcpHelper.SendRaw(clientStream, serverConnection.Stream, BufferPool,
(buffer, offset, count) => { args.OnDataSent(buffer, offset, count); }, args.OnDataSent, args.OnDataReceived, cancellationTokenSource, ExceptionFunc);
(buffer, offset, count) => { args.OnDataReceived(buffer, offset, count); },
cancellationTokenSource, ExceptionFunc);
} }
} }
} }
...@@ -47,8 +47,8 @@ namespace Titanium.Web.Proxy ...@@ -47,8 +47,8 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
private async Task handle401UnAuthorized(SessionEventArgs args) private async Task handle401UnAuthorized(SessionEventArgs args)
{ {
string headerName = null; string? headerName = null;
HttpHeader authHeader = null; HttpHeader? authHeader = null;
var response = args.HttpClient.Response; var response = args.HttpClient.Response;
...@@ -91,7 +91,7 @@ namespace Titanium.Web.Proxy ...@@ -91,7 +91,7 @@ namespace Titanium.Web.Proxy
if (authHeader != null) if (authHeader != null)
{ {
string scheme = authSchemes.Contains(authHeader.Value) ? authHeader.Value : null; string? scheme = authSchemes.Contains(authHeader.Value) ? authHeader.Value : null;
var expectedAuthState = var expectedAuthState =
scheme == null ? State.WinAuthState.INITIAL_TOKEN : State.WinAuthState.UNAUTHORIZED; scheme == null ? State.WinAuthState.INITIAL_TOKEN : State.WinAuthState.UNAUTHORIZED;
...@@ -111,7 +111,7 @@ namespace Titanium.Web.Proxy ...@@ -111,7 +111,7 @@ namespace Titanium.Web.Proxy
// initial value will match exactly any of the schemes // initial value will match exactly any of the schemes
if (scheme != null) if (scheme != null)
{ {
string clientToken = WinAuthHandler.GetInitialAuthToken(request.Host, scheme, args.HttpClient.Data); string clientToken = WinAuthHandler.GetInitialAuthToken(request.Host!, scheme, args.HttpClient.Data);
string auth = string.Concat(scheme, clientToken); string auth = string.Concat(scheme, clientToken);
...@@ -127,13 +127,12 @@ namespace Titanium.Web.Proxy ...@@ -127,13 +127,12 @@ namespace Titanium.Web.Proxy
else else
{ {
// challenge value will start with any of the scheme selected // challenge value will start with any of the scheme selected
scheme = authSchemes.First(x => scheme = authSchemes.First(x =>
authHeader.Value.StartsWith(x, StringComparison.OrdinalIgnoreCase) && authHeader.Value.StartsWith(x, StringComparison.OrdinalIgnoreCase) &&
authHeader.Value.Length > x.Length + 1); authHeader.Value.Length > x.Length + 1);
string serverToken = authHeader.Value.Substring(scheme.Length + 1); string serverToken = authHeader.Value.Substring(scheme.Length + 1);
string clientToken = WinAuthHandler.GetFinalAuthToken(request.Host, serverToken, args.HttpClient.Data); string clientToken = WinAuthHandler.GetFinalAuthToken(request.Host!, serverToken, args.HttpClient.Data);
string auth = string.Concat(scheme, clientToken); string auth = string.Concat(scheme, clientToken);
......
using Microsoft.AspNetCore.Http; using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Buffers; using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
...@@ -10,7 +8,7 @@ using System.Net.Http; ...@@ -10,7 +8,7 @@ using System.Net.Http;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.IntegrationTests.Helpers; using Titanium.Web.Proxy.IntegrationTests.Helpers;
...@@ -24,7 +22,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -24,7 +22,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
{ {
var testSuite = new TestSuite(); var testSuite = new TestSuite();
var server = testSuite.GetServer(); var server = testSuite.GetServer();
var continueServer = new HttpContinueServer() var continueServer = new HttpContinueServer
{ {
ExpectationResponse = HttpStatusCode.Continue, ExpectationResponse = HttpStatusCode.Continue,
ResponseBody = "I am server. I received your greetings." ResponseBody = "I am server. I received your greetings."
...@@ -35,7 +33,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -35,7 +33,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
proxy.Enable100ContinueBehaviour = true; proxy.Enable100ContinueBehaviour = true;
proxy.BeforeRequest += (sender, e) => proxy.BeforeRequest += (sender, e) =>
{ {
e.HttpClient.Request.RequestUri = new Uri(server.ListeningTcpUrl); e.HttpClient.Request.Url = server.ListeningTcpUrl;
return Task.CompletedTask; return Task.CompletedTask;
}; };
...@@ -52,14 +50,14 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -52,14 +50,14 @@ namespace Titanium.Web.Proxy.IntegrationTests
{ {
var testSuite = new TestSuite(); var testSuite = new TestSuite();
var server = testSuite.GetServer(); var server = testSuite.GetServer();
var continueServer = new HttpContinueServer() { ExpectationResponse = HttpStatusCode.ExpectationFailed }; var continueServer = new HttpContinueServer { ExpectationResponse = HttpStatusCode.ExpectationFailed };
server.HandleTcpRequest(continueServer.HandleRequest); server.HandleTcpRequest(continueServer.HandleRequest);
var proxy = testSuite.GetReverseProxy(); var proxy = testSuite.GetReverseProxy();
proxy.Enable100ContinueBehaviour = true; proxy.Enable100ContinueBehaviour = true;
proxy.BeforeRequest += (sender, e) => proxy.BeforeRequest += (sender, e) =>
{ {
e.HttpClient.Request.RequestUri = new Uri(server.ListeningTcpUrl); e.HttpClient.Request.Url = server.ListeningTcpUrl;
return Task.CompletedTask; return Task.CompletedTask;
}; };
...@@ -75,14 +73,14 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -75,14 +73,14 @@ namespace Titanium.Web.Proxy.IntegrationTests
{ {
var testSuite = new TestSuite(); var testSuite = new TestSuite();
var server = testSuite.GetServer(); var server = testSuite.GetServer();
var continueServer = new HttpContinueServer() { ExpectationResponse = HttpStatusCode.NotFound }; var continueServer = new HttpContinueServer { ExpectationResponse = HttpStatusCode.NotFound };
server.HandleTcpRequest(continueServer.HandleRequest); server.HandleTcpRequest(continueServer.HandleRequest);
var proxy = testSuite.GetReverseProxy(); var proxy = testSuite.GetReverseProxy();
proxy.Enable100ContinueBehaviour = true; proxy.Enable100ContinueBehaviour = true;
proxy.BeforeRequest += (sender, e) => proxy.BeforeRequest += (sender, e) =>
{ {
e.HttpClient.Request.RequestUri = new Uri(server.ListeningTcpUrl); e.HttpClient.Request.Url = server.ListeningTcpUrl;
return Task.CompletedTask; return Task.CompletedTask;
}; };
...@@ -98,7 +96,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -98,7 +96,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
{ {
var testSuite = new TestSuite(); var testSuite = new TestSuite();
var server = testSuite.GetServer(); var server = testSuite.GetServer();
var continueServer = new HttpContinueServer() { ExpectationResponse = HttpStatusCode.Continue }; var continueServer = new HttpContinueServer { ExpectationResponse = HttpStatusCode.Continue };
server.HandleTcpRequest(continueServer.HandleRequest); server.HandleTcpRequest(continueServer.HandleRequest);
var dbzEx = new DivideByZeroException("Undefined"); var dbzEx = new DivideByZeroException("Undefined");
...@@ -110,7 +108,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -110,7 +108,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
{ {
try try
{ {
e.HttpClient.Request.RequestUri = new Uri(server.ListeningTcpUrl); e.HttpClient.Request.Url = server.ListeningTcpUrl;
throw dbzEx; throw dbzEx;
} }
catch catch
...@@ -124,6 +122,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -124,6 +122,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
e.Respond(serverError); e.Respond(serverError);
} }
return Task.CompletedTask; return Task.CompletedTask;
}; };
......
...@@ -9,6 +9,8 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -9,6 +9,8 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
{ {
class HttpContinueClient class HttpContinueClient
{ {
private const int waitTimeout = 200;
private static Encoding MsgEncoding = HttpHelper.GetEncodingFromContentType(null); private static Encoding MsgEncoding = HttpHelper.GetEncodingFromContentType(null);
public async Task<Response> Post(string server, int port, string content) public async Task<Response> Post(string server, int port, string content)
...@@ -20,7 +22,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -20,7 +22,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
var request = new Request var request = new Request
{ {
Method = "POST", Method = "POST",
RequestUriString = "/", Url = "/",
HttpVersion = new Version(1, 1) HttpVersion = new Version(1, 1)
}; };
request.Headers.AddHeader(KnownHeaders.Host, server); request.Headers.AddHeader(KnownHeaders.Host, server);
...@@ -32,13 +34,14 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -32,13 +34,14 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
var buffer = new byte[1024]; var buffer = new byte[1024];
var responseMsg = string.Empty; var responseMsg = string.Empty;
Response response = null; Response response;
while ((response = HttpMessageParsing.ParseResponse(responseMsg)) == null) while ((response = HttpMessageParsing.ParseResponse(responseMsg)) == null)
{ {
var readTask = client.GetStream().ReadAsync(buffer, 0, 1024); var readTask = client.GetStream().ReadAsync(buffer, 0, 1024);
if (!readTask.Wait(200)) if (!readTask.Wait(waitTimeout))
return null; return null;
responseMsg += MsgEncoding.GetString(buffer, 0, readTask.Result); responseMsg += MsgEncoding.GetString(buffer, 0, readTask.Result);
} }
...@@ -51,17 +54,15 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -51,17 +54,15 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
while ((response = HttpMessageParsing.ParseResponse(responseMsg)) == null) while ((response = HttpMessageParsing.ParseResponse(responseMsg)) == null)
{ {
var readTask = client.GetStream().ReadAsync(buffer, 0, 1024); var readTask = client.GetStream().ReadAsync(buffer, 0, 1024);
if (!readTask.Wait(200)) if (!readTask.Wait(waitTimeout))
return null; return null;
responseMsg += MsgEncoding.GetString(buffer, 0, readTask.Result); responseMsg += MsgEncoding.GetString(buffer, 0, readTask.Result);
} }
return response; return response;
} }
else
{ return response;
return response;
}
} }
} }
} }
...@@ -66,6 +66,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -66,6 +66,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
{ {
Console.WriteLine($"{ex.GetType()}: {ex.Message}"); Console.WriteLine($"{ex.GetType()}: {ex.Message}");
} }
return request; return request;
} }
...@@ -87,6 +88,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -87,6 +88,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
{ {
Console.WriteLine($"{ex.GetType()}: {ex.Message}"); Console.WriteLine($"{ex.GetType()}: {ex.Message}");
} }
return request; return request;
} }
} }
......
...@@ -7,11 +7,14 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -7,11 +7,14 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
{ {
internal static class HttpMessageParsing internal static class HttpMessageParsing
{ {
private static readonly char[] colonSplit = { ':' };
/// <summary> /// <summary>
/// This is a terribly inefficient way of reading & parsing an /// This is a terribly inefficient way of reading & parsing an
/// http request, but it's good enough for testing purposes. /// http request, but it's good enough for testing purposes.
/// </summary> /// </summary>
/// <param name="messageText">The request message</param> /// <param name="messageText">The request message</param>
/// <param name="requireBody"></param>
/// <returns>Request object if message complete, null otherwise</returns> /// <returns>Request object if message complete, null otherwise</returns>
internal static Request ParseRequest(string messageText, bool requireBody) internal static Request ParseRequest(string messageText, bool requireBody)
{ {
...@@ -23,16 +26,14 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -23,16 +26,14 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
try try
{ {
Request.ParseRequestLine(line, out var method, out var url, out var version); Request.ParseRequestLine(line, out var method, out var url, out var version);
RequestResponseBase request = new Request() var request = new Request
{ {
Method = method, Method = method, Url = url, HttpVersion = version
RequestUriString = url,
HttpVersion = version
}; };
while (!string.IsNullOrEmpty(line = reader.ReadLine())) while (!string.IsNullOrEmpty(line = reader.ReadLine()))
{ {
var header = line.Split(ProxyConstants.ColonSplit, 2); var header = line.Split(colonSplit, 2);
request.Headers.AddHeader(header[0], header[1]); request.Headers.AddHeader(header[0].Trim(), header[1].Trim());
} }
// First zero-length line denotes end of headers. If we // First zero-length line denotes end of headers. If we
...@@ -41,12 +42,15 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -41,12 +42,15 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
return null; return null;
if (!requireBody) if (!requireBody)
return request as Request; return request;
if (parseBody(reader, ref request)) if (parseBody(reader, request))
return request as Request; return request;
}
catch
{
// ignore
} }
catch { }
return null; return null;
} }
...@@ -63,19 +67,18 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -63,19 +67,18 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
var line = reader.ReadLine(); var line = reader.ReadLine();
if (string.IsNullOrEmpty(line)) if (string.IsNullOrEmpty(line))
return null; return null;
try try
{ {
Response.ParseResponseLine(line, out var version, out var status, out var desc); Response.ParseResponseLine(line, out var version, out var status, out var desc);
RequestResponseBase response = new Response() var response = new Response
{ {
HttpVersion = version, HttpVersion = version, StatusCode = status, StatusDescription = desc
StatusCode = status,
StatusDescription = desc
}; };
while (!string.IsNullOrEmpty(line = reader.ReadLine())) while (!string.IsNullOrEmpty(line = reader.ReadLine()))
{ {
var header = line.Split(ProxyConstants.ColonSplit, 2); var header = line.Split(colonSplit, 2);
response.Headers.AddHeader(header[0], header[1]); response.Headers.AddHeader(header[0], header[1]);
} }
...@@ -84,15 +87,18 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -84,15 +87,18 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
if (line?.Length != 0) if (line?.Length != 0)
return null; return null;
if (parseBody(reader, ref response)) if (parseBody(reader, response))
return response as Response; return response;
}
catch
{
// ignore
} }
catch { }
return null; return null;
} }
private static bool parseBody(StringReader reader, ref RequestResponseBase obj) private static bool parseBody(StringReader reader, RequestResponseBase obj)
{ {
obj.OriginalContentLength = obj.ContentLength; obj.OriginalContentLength = obj.ContentLength;
if (obj.ContentLength <= 0) if (obj.ContentLength <= 0)
...@@ -100,14 +106,11 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers ...@@ -100,14 +106,11 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
// no body, done // no body, done
return true; return true;
} }
else
{ obj.Body = Encoding.ASCII.GetBytes(reader.ReadToEnd());
obj.Body = Encoding.ASCII.GetBytes(reader.ReadToEnd());
if (obj.ContentLength == obj.OriginalContentLength) // done reading body
return true; // done reading body return obj.ContentLength == obj.OriginalContentLength;
else
return false; // not done reading body
}
} }
} }
} }
...@@ -47,7 +47,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -47,7 +47,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
var proxy = testSuite.GetProxy(); var proxy = testSuite.GetProxy();
proxy.BeforeRequest += async (sender, e) => proxy.BeforeRequest += async (sender, e) =>
{ {
e.HttpClient.Request.RequestUri = new Uri(server.ListeningHttpUrl); e.HttpClient.Request.Url = server.ListeningHttpUrl;
await Task.FromResult(0); await Task.FromResult(0);
}; };
......
using Microsoft.AspNetCore.Http; using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Titanium.Web.Proxy.IntegrationTests namespace Titanium.Web.Proxy.IntegrationTests
{ {
...@@ -61,7 +61,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -61,7 +61,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
{ {
Assert.AreEqual("Test", session.UserData); Assert.AreEqual("Test", session.UserData);
return await Task.FromResult(new Models.ExternalProxy() return await Task.FromResult(new Models.ExternalProxy
{ {
HostName = "localhost", HostName = "localhost",
Port = proxy2.ProxyEndPoints[0].Port Port = proxy2.ProxyEndPoints[0].Port
......
using Microsoft.AspNetCore.Http; using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Titanium.Web.Proxy.IntegrationTests namespace Titanium.Web.Proxy.IntegrationTests
{ {
...@@ -24,7 +24,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -24,7 +24,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
var proxy = testSuite.GetReverseProxy(); var proxy = testSuite.GetReverseProxy();
proxy.BeforeRequest += async (sender, e) => proxy.BeforeRequest += async (sender, e) =>
{ {
e.HttpClient.Request.RequestUri = new Uri(server.ListeningHttpUrl); e.HttpClient.Request.Url = server.ListeningHttpUrl;
await Task.FromResult(0); await Task.FromResult(0);
}; };
...@@ -53,7 +53,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -53,7 +53,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
var proxy = testSuite.GetReverseProxy(); var proxy = testSuite.GetReverseProxy();
proxy.BeforeRequest += async (sender, e) => proxy.BeforeRequest += async (sender, e) =>
{ {
e.HttpClient.Request.RequestUri = new Uri(server.ListeningHttpUrl); e.HttpClient.Request.Url = server.ListeningHttpUrl;
await Task.FromResult(0); await Task.FromResult(0);
}; };
...@@ -82,7 +82,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -82,7 +82,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
var proxy = testSuite.GetReverseProxy(); var proxy = testSuite.GetReverseProxy();
proxy.BeforeRequest += async (sender, e) => proxy.BeforeRequest += async (sender, e) =>
{ {
e.HttpClient.Request.RequestUri = new Uri(server.ListeningHttpsUrl); e.HttpClient.Request.Url = server.ListeningHttpsUrl;
await Task.FromResult(0); await Task.FromResult(0);
}; };
...@@ -111,7 +111,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -111,7 +111,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
var proxy = testSuite.GetReverseProxy(); var proxy = testSuite.GetReverseProxy();
proxy.BeforeRequest += async (sender, e) => proxy.BeforeRequest += async (sender, e) =>
{ {
e.HttpClient.Request.RequestUri = new Uri(server.ListeningHttpsUrl); e.HttpClient.Request.Url = server.ListeningHttpsUrl;
await Task.FromResult(0); await Task.FromResult(0);
}; };
......
...@@ -18,7 +18,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Setup ...@@ -18,7 +18,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Setup
public TestProxyServer(bool isReverseProxy, ProxyServer upStreamProxy = null) public TestProxyServer(bool isReverseProxy, ProxyServer upStreamProxy = null)
{ {
ProxyServer = new ProxyServer(); ProxyServer = new ProxyServer();
ProxyEndPoint explicitEndPoint = isReverseProxy ? var explicitEndPoint = isReverseProxy ?
(ProxyEndPoint)new TransparentProxyEndPoint(IPAddress.Any, 0, true) : (ProxyEndPoint)new TransparentProxyEndPoint(IPAddress.Any, 0, true) :
new ExplicitProxyEndPoint(IPAddress.Any, 0, true); new ExplicitProxyEndPoint(IPAddress.Any, 0, true);
...@@ -26,13 +26,13 @@ namespace Titanium.Web.Proxy.IntegrationTests.Setup ...@@ -26,13 +26,13 @@ namespace Titanium.Web.Proxy.IntegrationTests.Setup
if (upStreamProxy != null) if (upStreamProxy != null)
{ {
ProxyServer.UpStreamHttpProxy = new ExternalProxy() ProxyServer.UpStreamHttpProxy = new ExternalProxy
{ {
HostName = "localhost", HostName = "localhost",
Port = upStreamProxy.ProxyEndPoints[0].Port Port = upStreamProxy.ProxyEndPoints[0].Port
}; };
ProxyServer.UpStreamHttpsProxy = new ExternalProxy() ProxyServer.UpStreamHttpsProxy = new ExternalProxy
{ {
HostName = "localhost", HostName = "localhost",
Port = upStreamProxy.ProxyEndPoints[0].Port Port = upStreamProxy.ProxyEndPoints[0].Port
......
...@@ -62,14 +62,9 @@ namespace Titanium.Web.Proxy.IntegrationTests.Setup ...@@ -62,14 +62,9 @@ namespace Titanium.Web.Proxy.IntegrationTests.Setup
.Get<IServerAddressesFeature>() .Get<IServerAddressesFeature>()
.Addresses.ToArray(); .Addresses.ToArray();
string httpAddress = addresses[0]; HttpListeningPort = new Uri(addresses[0]).Port;
HttpListeningPort = int.Parse(httpAddress.Split(':')[2]); HttpsListeningPort = new Uri(addresses[1]).Port;
TcpListeningPort = new Uri(addresses[2]).Port;
string httpsAddress = addresses[1];
HttpsListeningPort = int.Parse(httpsAddress.Split(':')[2]);
string tcpAddress = addresses[2];
TcpListeningPort = int.Parse(tcpAddress.Split(':')[2]);
} }
Func<HttpContext, Task> requestHandler = null; Func<HttpContext, Task> requestHandler = null;
......
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp3.0</TargetFramework>
<AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>StrongNameKey.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
</PropertyGroup> </PropertyGroup>
...@@ -13,13 +13,13 @@ ...@@ -13,13 +13,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" /> <FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> <PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> <PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
......
...@@ -7,9 +7,9 @@ ...@@ -7,9 +7,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" /> <PackageReference Include="MSTest.TestAdapter" Version="2.0.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" /> <PackageReference Include="MSTest.TestFramework" Version="2.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
......
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