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
......
...@@ -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>
......
This diff is collapsed.
...@@ -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,11 +226,11 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -226,11 +226,11 @@ 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; var session = (SessionEventArgsBase)sender;
...@@ -243,6 +243,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -243,6 +243,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf
} }
li.ReceivedDataCount += args.Count; li.ReceivedDataCount += args.Count;
AppendTransferLog(session.GetHashCode() + (isTunnelConnect ? "_tunnel" : "") + "_received",
args.Buffer, args.Offset, args.Count);
} }
}; };
...@@ -258,14 +261,41 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -258,14 +261,41 @@ namespace Titanium.Web.Proxy.Examples.Wpf
} }
li.SentDataCount += args.Count; 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;
AppendTransferLog(session.GetHashCode() + "_decrypted_received", args.Buffer, args.Offset,
args.Count);
};
te.DecryptedDataSent += (sender, args) =>
{
var session = (SessionEventArgsBase)sender;
AppendTransferLog(session.GetHashCode() + "_decrypted_sent", args.Buffer, args.Offset, args.Count);
};
} }
item.Update(); item.Update();
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);
......
...@@ -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; }
} }
} }
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
{ {
......
...@@ -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();
foreach (var header in headers)
{
headerBuilder.Append($"{header.ToString()}{ProxyConstants.NewLine}");
}
headerBuilder.Append(ProxyConstants.NewLine);
await WriteAsync(headerBuilder.ToString(), cancellationToken);
if (flush)
{ {
await stream.FlushAsync(cancellationToken); var buffer = headerBuilder.GetBuffer();
} await WriteAsync(buffer.Array, buffer.Offset, buffer.Count, true, 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
{ {
...@@ -42,6 +44,62 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -42,6 +44,62 @@ namespace Titanium.Web.Proxy.Helpers
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,17 +116,21 @@ namespace Titanium.Web.Proxy.Http ...@@ -100,17 +116,21 @@ 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 = "/";
}
} }
// prepare the request & headers var headerBuilder = new HeaderBuilder();
await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method, url, Request.HttpVersion), cancellationToken);
var headerBuilder = new StringBuilder(); // prepare the request & headers
headerBuilder.WriteRequestLine(Request.Method, url, Request.HttpVersion);
// Send Authentication to Upstream proxy if needed // Send Authentication to Upstream proxy if needed
if (!isTransparent && upstreamProxy != null if (!isTransparent && upstreamProxy != null
...@@ -118,22 +138,22 @@ namespace Titanium.Web.Proxy.Http ...@@ -118,22 +138,22 @@ namespace Titanium.Web.Proxy.Http
&& !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,12 +186,9 @@ namespace Titanium.Web.Proxy.Http ...@@ -166,12 +186,9 @@ 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))
{ {
throw new ServerConnectionException("Server connection was closed."); throw new ServerConnectionException("Server connection was closed.");
...@@ -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;
......
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
{ {
get => originalUrl; string url = UrlData.GetString();
internal set if (getUriScheme(UrlData).Length == 0)
{ {
originalUrl = value; string? hostAndPath = Host ?? Authority;
RequestUriString = value;
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();
if (httpVersion.EqualsIgnoreCase("HTTP/1.0")) // parse the HTTP version
var httpVersion = httpCmd.AsSpan(lastSpace + 1);
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);
} }
} }
...@@ -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;
} }
} }
} }
This diff is collapsed.
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>
......
This diff is collapsed.
...@@ -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.
......
...@@ -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);
} }
} }
...@@ -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);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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