Unverified Commit 8b890fe3 authored by honfika's avatar honfika Committed by GitHub

Merge pull request #613 from justcoding121/beta

Beta to stable
parents 4d635967 d58edd61
Doneness: Doneness:
- [ ] Build is okay - I made sure that this change is building successfully. - [ ] Build is okay - I made sure that this change is building successfully.
- [ ] No Bugs - I made sure that this change is working properly as expected. It doesn't have any bugs that you are aware of. - [ ] No Bugs - I made sure that this change is working properly as expected. It doesn't have any bugs that you are aware of.
- [ ] Branching - If this is not a hotfix, I am making this request against master branch - [ ] Branching - If this is not a hotfix, I am making this request against the master branch
## Titanium Web Proxy ## Titanium Web Proxy
### Note: This Project is no longer maintained. Any pull requests for fixes are welcome.
A lightweight HTTP(S) proxy server written in C#. A lightweight HTTP(S) proxy server written in C#.
<a href="https://ci.appveyor.com/project/justcoding121/titanium-web-proxy">![Build Status](https://ci.appveyor.com/api/projects/status/p5vvtbpx9yp250ol?svg=true)</a> [![Join the chat at https://gitter.im/Titanium-Web-Proxy/Lobby](https://badges.gitter.im/Titanium-Web-Proxy/Lobby.svg)](https://gitter.im/Titanium-Web-Proxy/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) <a href="https://ci.appveyor.com/project/justcoding121/titanium-web-proxy">![Build Status](https://ci.appveyor.com/api/projects/status/p5vvtbpx9yp250ol?svg=true)</a> [![Join the chat at https://gitter.im/Titanium-Web-Proxy/Lobby](https://badges.gitter.im/Titanium-Web-Proxy/Lobby.svg)](https://gitter.im/Titanium-Web-Proxy/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
...@@ -36,7 +38,7 @@ Supports ...@@ -36,7 +38,7 @@ Supports
#### Windows #### Windows
* Visual Studio Code as IDE for .NET core * Visual Studio Code as IDE for .NET core
* Visual Studio 2017 as IDE for .NET framework/.NET core * Visual Studio 2017/2019 as IDE for .NET framework/.NET core
#### Mac OS #### Mac OS
* Visual Studio Code as IDE for .NET core * Visual Studio Code as IDE for .NET core
......
...@@ -136,7 +136,7 @@ ...@@ -136,7 +136,7 @@
</span> </span>
<a id="Titanium_Web_Proxy_EventArguments_CertificateSelectionEventArgs_AcceptableIssuers_" data-uid="Titanium.Web.Proxy.EventArguments.CertificateSelectionEventArgs.AcceptableIssuers*"></a> <a id="Titanium_Web_Proxy_EventArguments_CertificateSelectionEventArgs_AcceptableIssuers_" data-uid="Titanium.Web.Proxy.EventArguments.CertificateSelectionEventArgs.AcceptableIssuers*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_CertificateSelectionEventArgs_AcceptableIssuers" data-uid="Titanium.Web.Proxy.EventArguments.CertificateSelectionEventArgs.AcceptableIssuers">AcceptableIssuers</h4> <h4 id="Titanium_Web_Proxy_EventArguments_CertificateSelectionEventArgs_AcceptableIssuers" data-uid="Titanium.Web.Proxy.EventArguments.CertificateSelectionEventArgs.AcceptableIssuers">AcceptableIssuers</h4>
<div class="markdown level1 summary"><p>Acceptable issuers as listed by remoted server.</p> <div class="markdown level1 summary"><p>Acceptable issuers as listed by remote server.</p>
</div> </div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
......
...@@ -100,13 +100,13 @@ ...@@ -100,13 +100,13 @@
<div class="inheritedMembers"> <div class="inheritedMembers">
<h5>Inherited Members</h5> <h5>Inherited Members</h5>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferSize">SessionEventArgsBase.bufferSize</a> <a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize">SessionEventArgsBase.BufferSize</a>
</div> </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>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_exceptionFunc">SessionEventArgsBase.exceptionFunc</a> <a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ExceptionFunc">SessionEventArgsBase.ExceptionFunc</a>
</div> </div>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TimeLine">SessionEventArgsBase.TimeLine</a> <a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TimeLine">SessionEventArgsBase.TimeLine</a>
...@@ -255,7 +255,7 @@ Default is true.</p> ...@@ -255,7 +255,7 @@ Default is true.</p>
</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>
<div class="markdown level1 summary"><p>Is this a connect request to secure HTTP server? Or is it to someother protocol.</p> <div class="markdown level1 summary"><p>Is this a connect request to secure HTTP server? Or is it to some other protocol.</p>
</div> </div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
......
...@@ -236,7 +236,7 @@ ...@@ -236,7 +236,7 @@
<tr> <tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.string">String</a></td> <td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.string">String</a></td>
<td><span class="parametername">message</span></td> <td><span class="parametername">message</span></td>
<td><p>Excception message</p> <td><p>Exception message</p>
</td> </td>
</tr> </tr>
<tr> <tr>
......
...@@ -107,6 +107,9 @@ ...@@ -107,6 +107,9 @@
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.Http.Request.html#Titanium_Web_Proxy_Http_Request_OriginalUrl">Request.OriginalUrl</a> <a class="xref" href="Titanium.Web.Proxy.Http.Request.html#Titanium_Web_Proxy_Http_Request_OriginalUrl">Request.OriginalUrl</a>
</div> </div>
<div>
<a class="xref" href="Titanium.Web.Proxy.Http.Request.html#Titanium_Web_Proxy_Http_Request_RequestUriString">Request.RequestUriString</a>
</div>
<div> <div>
<a class="xref" href="Titanium.Web.Proxy.Http.Request.html#Titanium_Web_Proxy_Http_Request_HasBody">Request.HasBody</a> <a class="xref" href="Titanium.Web.Proxy.Http.Request.html#Titanium_Web_Proxy_Http_Request_HasBody">Request.HasBody</a>
</div> </div>
...@@ -222,7 +225,7 @@ ...@@ -222,7 +225,7 @@
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_ConnectRequest_ClientHelloInfo.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.ConnectRequest.ClientHelloInfo%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_Http_ConnectRequest_ClientHelloInfo.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.ConnectRequest.ClientHelloInfo%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/Http/ConnectRequest.cs/#L15">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/ConnectRequest.cs/#L17">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_Http_ConnectRequest_ClientHelloInfo_" data-uid="Titanium.Web.Proxy.Http.ConnectRequest.ClientHelloInfo*"></a> <a id="Titanium_Web_Proxy_Http_ConnectRequest_ClientHelloInfo_" data-uid="Titanium.Web.Proxy.Http.ConnectRequest.ClientHelloInfo*"></a>
<h4 id="Titanium_Web_Proxy_Http_ConnectRequest_ClientHelloInfo" data-uid="Titanium.Web.Proxy.Http.ConnectRequest.ClientHelloInfo">ClientHelloInfo</h4> <h4 id="Titanium_Web_Proxy_Http_ConnectRequest_ClientHelloInfo" data-uid="Titanium.Web.Proxy.Http.ConnectRequest.ClientHelloInfo">ClientHelloInfo</h4>
...@@ -242,7 +245,37 @@ ...@@ -242,7 +245,37 @@
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td><span class="xref">StreamExtended.ClientHelloInfo</span></td> <td><span class="xref">ClientHelloInfo</span></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_Http_ConnectRequest_TunnelType.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.ConnectRequest.TunnelType%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/Http/ConnectRequest.cs/#L15">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_ConnectRequest_TunnelType_" data-uid="Titanium.Web.Proxy.Http.ConnectRequest.TunnelType*"></a>
<h4 id="Titanium_Web_Proxy_Http_ConnectRequest_TunnelType" data-uid="Titanium.Web.Proxy.Http.ConnectRequest.TunnelType">TunnelType</h4>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public TunnelType TunnelType { 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><span class="xref">TunnelType</span></td>
<td></td> <td></td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -201,7 +201,7 @@ ...@@ -201,7 +201,7 @@
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td><span class="xref">StreamExtended.ServerHelloInfo</span></td> <td><span class="xref">ServerHelloInfo</span></td>
<td></td> <td></td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -517,7 +517,7 @@ public class HeaderCollection : IEnumerable&lt;HttpHeader&gt;, IEnumerable</code ...@@ -517,7 +517,7 @@ public class HeaderCollection : IEnumerable&lt;HttpHeader&gt;, IEnumerable</code
<a id="Titanium_Web_Proxy_Http_HeaderCollection_GetHeaders_" data-uid="Titanium.Web.Proxy.Http.HeaderCollection.GetHeaders*"></a> <a id="Titanium_Web_Proxy_Http_HeaderCollection_GetHeaders_" data-uid="Titanium.Web.Proxy.Http.HeaderCollection.GetHeaders*"></a>
<h4 id="Titanium_Web_Proxy_Http_HeaderCollection_GetHeaders_System_String_" data-uid="Titanium.Web.Proxy.Http.HeaderCollection.GetHeaders(System.String)">GetHeaders(String)</h4> <h4 id="Titanium_Web_Proxy_Http_HeaderCollection_GetHeaders_System_String_" data-uid="Titanium.Web.Proxy.Http.HeaderCollection.GetHeaders(System.String)">GetHeaders(String)</h4>
<div class="markdown level1 summary"><p>Returns all headers with given name if exists <div class="markdown level1 summary"><p>Returns all headers with given name if exists
Returns null if does&apos;nt exist</p> Returns null if doesn&apos;t exist</p>
</div> </div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
......
...@@ -135,7 +135,7 @@ ...@@ -135,7 +135,7 @@
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string AcceptEncoding = &quot;accept-encoding&quot;</code></pre> <pre><code class="lang-csharp hljs">public const string AcceptEncoding = &quot;Accept-Encoding&quot;</code></pre>
</div> </div>
<h5 class="fieldValue">Field Value</h5> <h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -193,7 +193,7 @@ ...@@ -193,7 +193,7 @@
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Connection = &quot;connection&quot;</code></pre> <pre><code class="lang-csharp hljs">public const string Connection = &quot;Connection&quot;</code></pre>
</div> </div>
<h5 class="fieldValue">Field Value</h5> <h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -280,7 +280,7 @@ ...@@ -280,7 +280,7 @@
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string ContentEncoding = &quot;content-encoding&quot;</code></pre> <pre><code class="lang-csharp hljs">public const string ContentEncoding = &quot;Content-Encoding&quot;</code></pre>
</div> </div>
<h5 class="fieldValue">Field Value</h5> <h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -396,7 +396,7 @@ ...@@ -396,7 +396,7 @@
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string ContentLength = &quot;content-length&quot;</code></pre> <pre><code class="lang-csharp hljs">public const string ContentLength = &quot;Content-Length&quot;</code></pre>
</div> </div>
<h5 class="fieldValue">Field Value</h5> <h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -425,7 +425,7 @@ ...@@ -425,7 +425,7 @@
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string ContentType = &quot;content-type&quot;</code></pre> <pre><code class="lang-csharp hljs">public const string ContentType = &quot;Content-Type&quot;</code></pre>
</div> </div>
<h5 class="fieldValue">Field Value</h5> <h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -512,7 +512,7 @@ ...@@ -512,7 +512,7 @@
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Expect = &quot;expect&quot;</code></pre> <pre><code class="lang-csharp hljs">public const string Expect = &quot;Expect&quot;</code></pre>
</div> </div>
<h5 class="fieldValue">Field Value</h5> <h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -570,7 +570,7 @@ ...@@ -570,7 +570,7 @@
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Host = &quot;host&quot;</code></pre> <pre><code class="lang-csharp hljs">public const string Host = &quot;Host&quot;</code></pre>
</div> </div>
<h5 class="fieldValue">Field Value</h5> <h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -773,7 +773,7 @@ ...@@ -773,7 +773,7 @@
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string TransferEncoding = &quot;transfer-encoding&quot;</code></pre> <pre><code class="lang-csharp hljs">public const string TransferEncoding = &quot;Transfer-Encoding&quot;</code></pre>
</div> </div>
<h5 class="fieldValue">Field Value</h5> <h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -831,7 +831,7 @@ ...@@ -831,7 +831,7 @@
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">public const string Upgrade = &quot;upgrade&quot;</code></pre> <pre><code class="lang-csharp hljs">public const string Upgrade = &quot;Upgrade&quot;</code></pre>
</div> </div>
<h5 class="fieldValue">Field Value</h5> <h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
......
...@@ -194,19 +194,19 @@ ...@@ -194,19 +194,19 @@
</h3> </h3>
<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_Http2_Hpack_Encoder_EncodeHeader_System_IO_BinaryWriter_System_String_System_String_System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http2.Hpack.Encoder.EncodeHeader(System.IO.BinaryWriter%2CSystem.String%2CSystem.String%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http2_Hpack_Encoder_EncodeHeader_System_IO_BinaryWriter_System_String_System_String_System_Boolean_Titanium_Web_Proxy_Http2_Hpack_HpackUtil_IndexType_System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http2.Hpack.Encoder.EncodeHeader(System.IO.BinaryWriter%2CSystem.String%2CSystem.String%2CSystem.Boolean%2CTitanium.Web.Proxy.Http2.Hpack.HpackUtil.IndexType%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http2/Hpack/Encoder.cs/#L64">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http2/Hpack/Encoder.cs/#L66">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_Http2_Hpack_Encoder_EncodeHeader_" data-uid="Titanium.Web.Proxy.Http2.Hpack.Encoder.EncodeHeader*"></a> <a id="Titanium_Web_Proxy_Http2_Hpack_Encoder_EncodeHeader_" data-uid="Titanium.Web.Proxy.Http2.Hpack.Encoder.EncodeHeader*"></a>
<h4 id="Titanium_Web_Proxy_Http2_Hpack_Encoder_EncodeHeader_System_IO_BinaryWriter_System_String_System_String_System_Boolean_" data-uid="Titanium.Web.Proxy.Http2.Hpack.Encoder.EncodeHeader(System.IO.BinaryWriter,System.String,System.String,System.Boolean)">EncodeHeader(BinaryWriter, String, String, Boolean)</h4> <h4 id="Titanium_Web_Proxy_Http2_Hpack_Encoder_EncodeHeader_System_IO_BinaryWriter_System_String_System_String_System_Boolean_Titanium_Web_Proxy_Http2_Hpack_HpackUtil_IndexType_System_Boolean_" data-uid="Titanium.Web.Proxy.Http2.Hpack.Encoder.EncodeHeader(System.IO.BinaryWriter,System.String,System.String,System.Boolean,Titanium.Web.Proxy.Http2.Hpack.HpackUtil.IndexType,System.Boolean)">EncodeHeader(BinaryWriter, String, String, Boolean, HpackUtil.IndexType, Boolean)</h4>
<div class="markdown level1 summary"><p>Encode the header field into the header block.</p> <div class="markdown level1 summary"><p>Encode the header field into the header block.</p>
</div> </div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">public void EncodeHeader(BinaryWriter output, string name, string value, bool sensitive = false)</code></pre> <pre><code class="lang-csharp hljs">public void EncodeHeader(BinaryWriter output, string name, string value, bool sensitive = false, HpackUtil.IndexType indexType = HpackUtil.IndexType.Incremental, bool useStaticName = true)</code></pre>
</div> </div>
<h5 class="parameters">Parameters</h5> <h5 class="parameters">Parameters</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -240,6 +240,18 @@ ...@@ -240,6 +240,18 @@
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.boolean">Boolean</a></td> <td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.boolean">Boolean</a></td>
<td><span class="parametername">sensitive</span></td> <td><span class="parametername">sensitive</span></td>
<td><p>If set to <code>true</code> sensitive.</p> <td><p>If set to <code>true</code> sensitive.</p>
</td>
</tr>
<tr>
<td><a class="xref" href="Titanium.Web.Proxy.Http2.Hpack.HpackUtil.IndexType.html">HpackUtil.IndexType</a></td>
<td><span class="parametername">indexType</span></td>
<td><p>Index type.</p>
</td>
</tr>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.boolean">Boolean</a></td>
<td><span class="parametername">useStaticName</span></td>
<td><p>Use static name.</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
...@@ -249,7 +261,7 @@ ...@@ -249,7 +261,7 @@
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http2_Hpack_Encoder_SetMaxHeaderTableSize_System_IO_BinaryWriter_System_Int32_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http2.Hpack.Encoder.SetMaxHeaderTableSize(System.IO.BinaryWriter%2CSystem.Int32)%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_Http2_Hpack_Encoder_SetMaxHeaderTableSize_System_IO_BinaryWriter_System_Int32_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http2.Hpack.Encoder.SetMaxHeaderTableSize(System.IO.BinaryWriter%2CSystem.Int32)%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/Http2/Hpack/Encoder.cs/#L134">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http2/Hpack/Encoder.cs/#L135">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_Http2_Hpack_Encoder_SetMaxHeaderTableSize_" data-uid="Titanium.Web.Proxy.Http2.Hpack.Encoder.SetMaxHeaderTableSize*"></a> <a id="Titanium_Web_Proxy_Http2_Hpack_Encoder_SetMaxHeaderTableSize_" data-uid="Titanium.Web.Proxy.Http2.Hpack.Encoder.SetMaxHeaderTableSize*"></a>
<h4 id="Titanium_Web_Proxy_Http2_Hpack_Encoder_SetMaxHeaderTableSize_System_IO_BinaryWriter_System_Int32_" data-uid="Titanium.Web.Proxy.Http2.Hpack.Encoder.SetMaxHeaderTableSize(System.IO.BinaryWriter,System.Int32)">SetMaxHeaderTableSize(BinaryWriter, Int32)</h4> <h4 id="Titanium_Web_Proxy_Http2_Hpack_Encoder_SetMaxHeaderTableSize_System_IO_BinaryWriter_System_Int32_" data-uid="Titanium.Web.Proxy.Http2.Hpack.Encoder.SetMaxHeaderTableSize(System.IO.BinaryWriter,System.Int32)">SetMaxHeaderTableSize(BinaryWriter, Int32)</h4>
......
...@@ -199,7 +199,7 @@ So client application know that it is communicating with a proxy server.</p> ...@@ -199,7 +199,7 @@ So client application know that it is communicating with a proxy server.</p>
<div class="markdown level1 summary"><p>Intercept tunnel connect request. <div class="markdown level1 summary"><p>Intercept tunnel connect request.
Valid only for explicit endpoints. Valid only for explicit endpoints.
Set the <a class="xref" href="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html#Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptSsl">DecryptSsl</a> property to false if this HTTP connect request Set the <a class="xref" href="Titanium.Web.Proxy.EventArguments.TunnelConnectSessionEventArgs.html#Titanium_Web_Proxy_EventArguments_TunnelConnectSessionEventArgs_DecryptSsl">DecryptSsl</a> property to false if this HTTP connect request
should&apos;nt be decrypted and instead be relayed.</p> shouldn&apos;t be decrypted and instead be relayed.</p>
</div> </div>
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
......
...@@ -160,6 +160,48 @@ ...@@ -160,6 +160,48 @@
</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_HttpHeader__ctor_System_String_System_String_System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.HttpHeader.%23ctor(System.String%2CSystem.String%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Models/HttpHeader.cs/#L45">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Models_HttpHeader__ctor_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.#ctor*"></a>
<h4 id="Titanium_Web_Proxy_Models_HttpHeader__ctor_System_String_System_String_System_Boolean_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.#ctor(System.String,System.String,System.Boolean)">HttpHeader(String, String, Boolean)</h4>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected HttpHeader(string name, string value, bool headerEntry)</code></pre>
</div>
<h5 class="parameters">Parameters</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.string">String</a></td>
<td><span class="parametername">name</span></td>
<td></td>
</tr>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.string">String</a></td>
<td><span class="parametername">value</span></td>
<td></td>
</tr>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.boolean">Boolean</a></td>
<td><span class="parametername">headerEntry</span></td>
<td></td>
</tr>
</tbody>
</table>
<h3 id="fields">Fields <h3 id="fields">Fields
</h3> </h3>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
...@@ -201,7 +243,7 @@ The additional 32 octets account for an estimated overhead associated with an en ...@@ -201,7 +243,7 @@ The additional 32 octets account for an estimated overhead associated with an en
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Models_HttpHeader_Name.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.HttpHeader.Name%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_HttpHeader_Name.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.HttpHeader.Name%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/HttpHeader.cs/#L48">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Models/HttpHeader.cs/#L55">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_Models_HttpHeader_Name_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Name*"></a> <a id="Titanium_Web_Proxy_Models_HttpHeader_Name_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Name*"></a>
<h4 id="Titanium_Web_Proxy_Models_HttpHeader_Name" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Name">Name</h4> <h4 id="Titanium_Web_Proxy_Models_HttpHeader_Name" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Name">Name</h4>
...@@ -210,7 +252,7 @@ The additional 32 octets account for an estimated overhead associated with an en ...@@ -210,7 +252,7 @@ The additional 32 octets account for an estimated overhead associated with an en
<div class="markdown level1 conceptual"></div> <div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5> <h5 class="decalaration">Declaration</h5>
<div class="codewrapper"> <div class="codewrapper">
<pre><code class="lang-csharp hljs">public string Name { get; set; }</code></pre> <pre><code class="lang-csharp hljs">public string Name { get; }</code></pre>
</div> </div>
<h5 class="propertyValue">Property Value</h5> <h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed"> <table class="table table-bordered table-striped table-condensed">
...@@ -232,7 +274,7 @@ The additional 32 octets account for an estimated overhead associated with an en ...@@ -232,7 +274,7 @@ The additional 32 octets account for an estimated overhead associated with an en
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Models_HttpHeader_Size.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.HttpHeader.Size%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_HttpHeader_Size.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.HttpHeader.Size%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/HttpHeader.cs/#L55">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Models/HttpHeader.cs/#L62">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_Models_HttpHeader_Size_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Size*"></a> <a id="Titanium_Web_Proxy_Models_HttpHeader_Size_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Size*"></a>
<h4 id="Titanium_Web_Proxy_Models_HttpHeader_Size" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Size">Size</h4> <h4 id="Titanium_Web_Proxy_Models_HttpHeader_Size" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Size">Size</h4>
...@@ -262,7 +304,7 @@ The additional 32 octets account for an estimated overhead associated with an en ...@@ -262,7 +304,7 @@ The additional 32 octets account for an estimated overhead associated with an en
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Models_HttpHeader_Value.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.HttpHeader.Value%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_HttpHeader_Value.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.HttpHeader.Value%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/HttpHeader.cs/#L53">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Models/HttpHeader.cs/#L60">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_Models_HttpHeader_Value_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Value*"></a> <a id="Titanium_Web_Proxy_Models_HttpHeader_Value_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Value*"></a>
<h4 id="Titanium_Web_Proxy_Models_HttpHeader_Value" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Value">Value</h4> <h4 id="Titanium_Web_Proxy_Models_HttpHeader_Value" data-uid="Titanium.Web.Proxy.Models.HttpHeader.Value">Value</h4>
...@@ -295,7 +337,7 @@ The additional 32 octets account for an estimated overhead associated with an en ...@@ -295,7 +337,7 @@ The additional 32 octets account for an estimated overhead associated with an en
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Models_HttpHeader_SizeOf_System_String_System_String_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.HttpHeader.SizeOf(System.String%2CSystem.String)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Models_HttpHeader_SizeOf_System_String_System_String_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.HttpHeader.SizeOf(System.String%2CSystem.String)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span> </span>
<span class="small pull-right mobile-hide"> <span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Models/HttpHeader.cs/#L57">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Models/HttpHeader.cs/#L64">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_Models_HttpHeader_SizeOf_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.SizeOf*"></a> <a id="Titanium_Web_Proxy_Models_HttpHeader_SizeOf_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.SizeOf*"></a>
<h4 id="Titanium_Web_Proxy_Models_HttpHeader_SizeOf_System_String_System_String_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.SizeOf(System.String,System.String)">SizeOf(String, String)</h4> <h4 id="Titanium_Web_Proxy_Models_HttpHeader_SizeOf_System_String_System_String_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.SizeOf(System.String,System.String)">SizeOf(String, String)</h4>
...@@ -347,7 +389,7 @@ The additional 32 octets account for an estimated overhead associated with an en ...@@ -347,7 +389,7 @@ The additional 32 octets account for an estimated overhead associated with an en
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Models_HttpHeader_ToString.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.HttpHeader.ToString%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_HttpHeader_ToString.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Models.HttpHeader.ToString%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/HttpHeader.cs/#L66">View Source</a> <a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Models/HttpHeader.cs/#L73">View Source</a>
</span> </span>
<a id="Titanium_Web_Proxy_Models_HttpHeader_ToString_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.ToString*"></a> <a id="Titanium_Web_Proxy_Models_HttpHeader_ToString_" data-uid="Titanium.Web.Proxy.Models.HttpHeader.ToString*"></a>
<h4 id="Titanium_Web_Proxy_Models_HttpHeader_ToString" data-uid="Titanium.Web.Proxy.Models.HttpHeader.ToString">ToString()</h4> <h4 id="Titanium_Web_Proxy_Models_HttpHeader_ToString" data-uid="Titanium.Web.Proxy.Models.HttpHeader.ToString">ToString()</h4>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
...@@ -4,7 +4,7 @@ using System.Runtime.InteropServices; ...@@ -4,7 +4,7 @@ using System.Runtime.InteropServices;
namespace Titanium.Web.Proxy.Examples.Basic.Helpers namespace Titanium.Web.Proxy.Examples.Basic.Helpers
{ {
/// <summary> /// <summary>
/// Adapated from /// Adapted from
/// http://stackoverflow.com/questions/13656846/how-to-programmatic-disable-c-sharp-console-applications-quick-edit-mode /// http://stackoverflow.com/questions/13656846/how-to-programmatic-disable-c-sharp-console-applications-quick-edit-mode
/// </summary> /// </summary>
internal static class ConsoleHelper internal static class ConsoleHelper
......
...@@ -9,7 +9,7 @@ using System.Runtime.InteropServices; ...@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Demo")] [assembly: AssemblyProduct("Demo")]
[assembly: AssemblyCopyright("Copyright © Titanium 2015-2017")] [assembly: AssemblyCopyright("Copyright © Titanium 2015-2019")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
......
...@@ -32,11 +32,11 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -32,11 +32,11 @@ namespace Titanium.Web.Proxy.Examples.Basic
{ {
if (exception is ProxyHttpException phex) if (exception is ProxyHttpException phex)
{ {
await WriteToConsole(exception.Message + ": " + phex.InnerException?.Message, true); await writeToConsole(exception.Message + ": " + phex.InnerException?.Message, true);
} }
else else
{ {
await WriteToConsole(exception.Message, true); await writeToConsole(exception.Message, true);
} }
}; };
proxyServer.ForwardToUpstreamGateway = true; proxyServer.ForwardToUpstreamGateway = true;
...@@ -52,8 +52,8 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -52,8 +52,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
public void StartProxy() public void StartProxy()
{ {
proxyServer.BeforeRequest += OnRequest; proxyServer.BeforeRequest += onRequest;
proxyServer.BeforeResponse += OnResponse; proxyServer.BeforeResponse += onResponse;
proxyServer.ServerCertificateValidationCallback += OnCertificateValidation; proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection; proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
...@@ -63,8 +63,8 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -63,8 +63,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000); explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000);
// Fired when a CONNECT request is received // Fired when a CONNECT request is received
explicitEndPoint.BeforeTunnelConnectRequest += OnBeforeTunnelConnectRequest; explicitEndPoint.BeforeTunnelConnectRequest += onBeforeTunnelConnectRequest;
explicitEndPoint.BeforeTunnelConnectResponse += OnBeforeTunnelConnectResponse; explicitEndPoint.BeforeTunnelConnectResponse += onBeforeTunnelConnectResponse;
// An explicit endpoint is where the client knows about the existence of a proxy // An explicit endpoint is where the client knows about the existence of a proxy
// So client sends request in a proxy friendly manner // So client sends request in a proxy friendly manner
...@@ -102,11 +102,11 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -102,11 +102,11 @@ namespace Titanium.Web.Proxy.Examples.Basic
public void Stop() public void Stop()
{ {
explicitEndPoint.BeforeTunnelConnectRequest -= OnBeforeTunnelConnectRequest; explicitEndPoint.BeforeTunnelConnectRequest -= onBeforeTunnelConnectRequest;
explicitEndPoint.BeforeTunnelConnectResponse -= OnBeforeTunnelConnectResponse; explicitEndPoint.BeforeTunnelConnectResponse -= onBeforeTunnelConnectResponse;
proxyServer.BeforeRequest -= OnRequest; proxyServer.BeforeRequest -= onRequest;
proxyServer.BeforeResponse -= OnResponse; proxyServer.BeforeResponse -= onResponse;
proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation; proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection; proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;
...@@ -116,10 +116,10 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -116,10 +116,10 @@ namespace Titanium.Web.Proxy.Examples.Basic
//proxyServer.CertificateManager.RemoveTrustedRootCertificates(); //proxyServer.CertificateManager.RemoveTrustedRootCertificates();
} }
private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) private async Task onBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{ {
string hostname = e.HttpClient.Request.RequestUri.Host; string hostname = e.HttpClient.Request.RequestUri.Host;
await WriteToConsole("Tunnel to: " + hostname); await writeToConsole("Tunnel to: " + hostname);
if (hostname.Contains("dropbox.com")) if (hostname.Contains("dropbox.com"))
{ {
...@@ -130,16 +130,16 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -130,16 +130,16 @@ namespace Titanium.Web.Proxy.Examples.Basic
} }
} }
private Task OnBeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e) private Task onBeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e)
{ {
return Task.FromResult(false); return Task.FromResult(false);
} }
// intecept & cancel redirect or update requests // intecept & cancel redirect or update requests
private async Task OnRequest(object sender, SessionEventArgs e) private async Task onRequest(object sender, SessionEventArgs e)
{ {
await WriteToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount); await writeToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
await WriteToConsole(e.HttpClient.Request.Url); await writeToConsole(e.HttpClient.Request.Url);
// store it in the UserData property // store it in the UserData property
// It can be a simple integer, Guid, or any type // It can be a simple integer, Guid, or any type
...@@ -177,19 +177,19 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -177,19 +177,19 @@ namespace Titanium.Web.Proxy.Examples.Basic
} }
// Modify response // Modify response
private async Task MultipartRequestPartSent(object sender, MultipartRequestPartSentEventArgs e) private async Task multipartRequestPartSent(object sender, MultipartRequestPartSentEventArgs e)
{ {
var session = (SessionEventArgs)sender; var session = (SessionEventArgs)sender;
await WriteToConsole("Multipart form data headers:"); await writeToConsole("Multipart form data headers:");
foreach (var header in e.Headers) foreach (var header in e.Headers)
{ {
await WriteToConsole(header.ToString()); await writeToConsole(header.ToString());
} }
} }
private async Task OnResponse(object sender, SessionEventArgs e) private async Task onResponse(object sender, SessionEventArgs e)
{ {
await WriteToConsole("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount); await writeToConsole("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount);
string ext = System.IO.Path.GetExtension(e.HttpClient.Request.RequestUri.AbsolutePath); string ext = System.IO.Path.GetExtension(e.HttpClient.Request.RequestUri.AbsolutePath);
...@@ -261,7 +261,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -261,7 +261,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
return Task.FromResult(0); return Task.FromResult(0);
} }
private async Task WriteToConsole(string message, bool useRedColor = false) private async Task writeToConsole(string message, bool useRedColor = false)
{ {
await @lock.WaitAsync(); await @lock.WaitAsync();
......
...@@ -36,13 +36,20 @@ ...@@ -36,13 +36,20 @@
</ListView> </ListView>
<TabControl Grid.Column="2" Grid.Row="0"> <TabControl Grid.Column="2" Grid.Row="0">
<TabItem Header="Session"> <TabItem Header="Session">
<Grid Background="Red" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
<RowDefinition /> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBox x:Name="TextBoxRequest" Grid.Row="0" /> <TextBox x:Name="TextBoxRequest" Grid.Row="0" />
<TextBox x:Name="TextBoxResponse" Grid.Row="1" /> <TabControl Grid.Row="1">
<TabItem Header="Text">
<TextBox x:Name="TextBoxResponse" />
</TabItem>
<TabItem Header="Image">
<Image x:Name="ImageResponse" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="None" />
</TabItem>
</TabControl>
</Grid> </Grid>
</TabItem> </TabItem>
</TabControl> </TabControl>
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text; using System.Text;
...@@ -8,6 +9,7 @@ using System.Threading.Tasks; ...@@ -8,6 +9,7 @@ using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media.Imaging;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
...@@ -36,6 +38,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -36,6 +38,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf
public MainWindow() public MainWindow()
{ {
proxyServer = new ProxyServer(); proxyServer = new ProxyServer();
proxyServer.EnableHttp2 = true;
//proxyServer.CertificateManager.CertificateEngine = CertificateEngine.DefaultWindows; //proxyServer.CertificateManager.CertificateEngine = CertificateEngine.DefaultWindows;
////Set a password for the .pfx file ////Set a password for the .pfx file
...@@ -53,6 +58,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -53,6 +58,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf
proxyServer.ForwardToUpstreamGateway = true; proxyServer.ForwardToUpstreamGateway = true;
//increase the ThreadPool (for server prod)
//proxyServer.ThreadPoolWorkerThread = Environment.ProcessorCount * 6;
////if you need Load or Create Certificate now. ////// "true" if you need Enable===> Trust the RootCertificate used by this proxy server ////if you need Load or Create Certificate now. ////// "true" if you need Enable===> Trust the RootCertificate used by this proxy server
//proxyServer.CertificateManager.EnsureRootCertificate(true); //proxyServer.CertificateManager.EnsureRootCertificate(true);
...@@ -93,7 +101,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -93,7 +101,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
InitializeComponent(); InitializeComponent();
} }
public ObservableCollection<SessionListItem> Sessions { get; } = new ObservableCollection<SessionListItem>(); public ObservableCollectionEx<SessionListItem> Sessions { get; } = new ObservableCollectionEx<SessionListItem>();
public SessionListItem SelectedSession public SessionListItem SelectedSession
{ {
...@@ -103,7 +111,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -103,7 +111,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
if (value != selectedSession) if (value != selectedSession)
{ {
selectedSession = value; selectedSession = value;
SelectedSessionChanged(); selectedSessionChanged();
} }
} }
} }
...@@ -128,7 +136,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -128,7 +136,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
e.DecryptSsl = false; e.DecryptSsl = false;
} }
await Dispatcher.InvokeAsync(() => { AddSession(e); }); await Dispatcher.InvokeAsync(() => { addSession(e); });
} }
private async Task ProxyServer_BeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e) private async Task ProxyServer_BeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e)
...@@ -144,8 +152,20 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -144,8 +152,20 @@ namespace Titanium.Web.Proxy.Examples.Wpf
private async Task ProxyServer_BeforeRequest(object sender, SessionEventArgs e) private async Task ProxyServer_BeforeRequest(object sender, SessionEventArgs e)
{ {
if (e.HttpClient.ConnectRequest?.TunnelType != TunnelType.Http2)
{
return;
}
SessionListItem item = null; SessionListItem item = null;
await Dispatcher.InvokeAsync(() => { item = AddSession(e); }); await Dispatcher.InvokeAsync(() => { item = addSession(e); });
//if (e.HttpClient.ConnectRequest?.TunnelType == TunnelType.Http2)
//{
//}
//if (!e.HttpClient.Request.RequestUri.ToString().Contains("/mail/u/"))
// return;
if (e.HttpClient.Request.HasBody) if (e.HttpClient.Request.HasBody)
{ {
...@@ -156,6 +176,11 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -156,6 +176,11 @@ namespace Titanium.Web.Proxy.Examples.Wpf
private async Task ProxyServer_BeforeResponse(object sender, SessionEventArgs e) private async Task ProxyServer_BeforeResponse(object sender, SessionEventArgs e)
{ {
if (e.HttpClient.ConnectRequest?.TunnelType != TunnelType.Http2)
{
return;
}
SessionListItem item = null; SessionListItem item = null;
await Dispatcher.InvokeAsync(() => await Dispatcher.InvokeAsync(() =>
{ {
...@@ -165,6 +190,10 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -165,6 +190,10 @@ namespace Titanium.Web.Proxy.Examples.Wpf
} }
}); });
//e.HttpClient.Response.Headers.AddHeader("X-Titanium-Header", "HTTP/2 works");
//e.SetResponseBody(Encoding.ASCII.GetBytes("TITANIUMMMM!!!!"));
if (item != null) if (item != null)
{ {
if (e.HttpClient.Response.HasBody) if (e.HttpClient.Response.HasBody)
...@@ -188,15 +217,15 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -188,15 +217,15 @@ namespace Titanium.Web.Proxy.Examples.Wpf
}); });
} }
private SessionListItem AddSession(SessionEventArgsBase e) private SessionListItem addSession(SessionEventArgsBase e)
{ {
var item = CreateSessionListItem(e); var item = createSessionListItem(e);
Sessions.Add(item); Sessions.Add(item);
sessionDictionary.Add(e.HttpClient, item); sessionDictionary.Add(e.HttpClient, item);
return item; return item;
} }
private SessionListItem CreateSessionListItem(SessionEventArgsBase e) private SessionListItem createSessionListItem(SessionEventArgsBase e)
{ {
lastSessionNumber++; lastSessionNumber++;
bool isTunnelConnect = e is TunnelConnectSessionEventArgs; bool isTunnelConnect = e is TunnelConnectSessionEventArgs;
...@@ -211,18 +240,30 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -211,18 +240,30 @@ namespace Titanium.Web.Proxy.Examples.Wpf
{ {
e.DataReceived += (sender, args) => e.DataReceived += (sender, args) =>
{ {
var session = (SessionEventArgs)sender; var session = (SessionEventArgsBase)sender;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li)) if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{ {
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
if (tunnelType != TunnelType.Unknown)
{
li.Protocol = TunnelTypeToString(tunnelType);
}
li.ReceivedDataCount += args.Count; li.ReceivedDataCount += args.Count;
} }
}; };
e.DataSent += (sender, args) => e.DataSent += (sender, args) =>
{ {
var session = (SessionEventArgs)sender; var session = (SessionEventArgsBase)sender;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li)) if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{ {
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
if (tunnelType != TunnelType.Unknown)
{
li.Protocol = TunnelTypeToString(tunnelType);
}
li.SentDataCount += args.Count; li.SentDataCount += args.Count;
} }
}; };
...@@ -232,20 +273,38 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -232,20 +273,38 @@ namespace Titanium.Web.Proxy.Examples.Wpf
return item; return item;
} }
private string TunnelTypeToString(TunnelType tunnelType)
{
switch (tunnelType)
{
case TunnelType.Https:
return "https";
case TunnelType.Websocket:
return "websocket";
case TunnelType.Http2:
return "http2";
}
return null;
}
private void ListViewSessions_OnKeyDown(object sender, KeyEventArgs e) private void ListViewSessions_OnKeyDown(object sender, KeyEventArgs e)
{ {
if (e.Key == Key.Delete) if (e.Key == Key.Delete)
{ {
var selectedItems = ((ListView)sender).SelectedItems; var selectedItems = ((ListView)sender).SelectedItems;
Sessions.SuppressNotification = true;
foreach (var item in selectedItems.Cast<SessionListItem>().ToArray()) foreach (var item in selectedItems.Cast<SessionListItem>().ToArray())
{ {
Sessions.Remove(item); Sessions.Remove(item);
sessionDictionary.Remove(item.HttpClient); sessionDictionary.Remove(item.HttpClient);
} }
Sessions.SuppressNotification = false;
} }
} }
private void SelectedSessionChanged() private void selectedSessionChanged()
{ {
if (SelectedSession == null) if (SelectedSession == null)
{ {
...@@ -256,7 +315,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -256,7 +315,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf
var session = SelectedSession.HttpClient; var session = SelectedSession.HttpClient;
var request = session.Request; var request = session.Request;
var data = (request.IsBodyRead ? request.Body : null) ?? new byte[0]; var fullData = (request.IsBodyRead ? request.Body : null) ?? new byte[0];
var data = fullData;
bool truncated = data.Length > truncateLimit; bool truncated = data.Length > truncateLimit;
if (truncated) if (truncated)
{ {
...@@ -272,7 +332,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -272,7 +332,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf
TextBoxRequest.Text = sb.ToString(); TextBoxRequest.Text = sb.ToString();
var response = session.Response; var response = session.Response;
data = (response.IsBodyRead ? response.Body : null) ?? new byte[0]; fullData = (response.IsBodyRead ? response.Body : null) ?? new byte[0];
data = fullData;
truncated = data.Length > truncateLimit; truncated = data.Length > truncateLimit;
if (truncated) if (truncated)
{ {
...@@ -292,6 +353,19 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -292,6 +353,19 @@ namespace Titanium.Web.Proxy.Examples.Wpf
} }
TextBoxResponse.Text = sb.ToString(); TextBoxResponse.Text = sb.ToString();
try
{
using (MemoryStream stream = new MemoryStream(fullData))
{
ImageResponse.Source =
BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
}
catch
{
ImageResponse.Source = null;
}
} }
} }
} }
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace Titanium.Web.Proxy.Examples.Wpf
{
public class ObservableCollectionEx<T> : ObservableCollection<T>
{
private bool notificationSuppressed;
private bool suppressNotification;
public bool SuppressNotification
{
get => suppressNotification;
set
{
suppressNotification = value;
if (suppressNotification == false && notificationSuppressed)
{
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
notificationSuppressed = false;
}
}
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (SuppressNotification)
{
notificationSuppressed = true;
return;
}
base.OnCollectionChanged(e);
}
}
}
\ No newline at end of file
...@@ -73,7 +73,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf.Annotations ...@@ -73,7 +73,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf.Annotations
} }
/// <summary> /// <summary>
/// Can be appplied to symbols of types derived from IEnumerable as well as to symbols of Task /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task
/// and Lazy classes to indicate that the value of a collection item, of the Task.Result property /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property
/// or of the Lazy.Value property can never be null. /// or of the Lazy.Value property can never be null.
/// </summary> /// </summary>
...@@ -85,7 +85,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf.Annotations ...@@ -85,7 +85,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf.Annotations
} }
/// <summary> /// <summary>
/// Can be appplied to symbols of types derived from IEnumerable as well as to symbols of Task /// Can be applied to symbols of types derived from IEnumerable as well as to symbols of Task
/// and Lazy classes to indicate that the value of a collection item, of the Task.Result property /// and Lazy classes to indicate that the value of a collection item, of the Task.Result property
/// or of the Lazy.Value property can be null. /// or of the Lazy.Value property can be null.
/// </summary> /// </summary>
...@@ -251,7 +251,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf.Annotations ...@@ -251,7 +251,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf.Annotations
/// </list> /// </list>
/// If method has single input parameter, it's name could be omitted.<br /> /// If method has single input parameter, it's name could be omitted.<br />
/// Using <c>halt</c> (or <c>void</c>/<c>nothing</c>, which is the same) for method output /// Using <c>halt</c> (or <c>void</c>/<c>nothing</c>, which is the same) for method output
/// means that the methos doesn't return normally (throws or terminates the process).<br /> /// means that the method doesn't return normally (throws or terminates the process).<br />
/// Value <c>canbenull</c> is only applicable for output parameters.<br /> /// Value <c>canbenull</c> is only applicable for output parameters.<br />
/// You can use multiple <c>[ContractAnnotation]</c> for each FDT row, or use single attribute /// You can use multiple <c>[ContractAnnotation]</c> for each FDT row, or use single attribute
/// with rows separated by semicolon. There is no notion of order rows, all rows are checked /// with rows separated by semicolon. There is no notion of order rows, all rows are checked
......
...@@ -10,7 +10,7 @@ using System.Windows; ...@@ -10,7 +10,7 @@ using System.Windows;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Demo WPF")] [assembly: AssemblyProduct("Demo WPF")]
[assembly: AssemblyCopyright("Copyright ©2017 Titanium")] [assembly: AssemblyCopyright("Copyright © Titanium 2015-2019")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
......
...@@ -11,7 +11,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -11,7 +11,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
private long? bodySize; private long? bodySize;
private Exception exception; private Exception exception;
private string host; private string host;
private string process; private int processId;
private string protocol; private string protocol;
private long receivedDataCount; private long receivedDataCount;
private long sentDataCount; private long sentDataCount;
...@@ -54,10 +54,32 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -54,10 +54,32 @@ namespace Titanium.Web.Proxy.Examples.Wpf
set => SetField(ref bodySize, value); set => SetField(ref bodySize, value);
} }
public int ProcessId
{
get => processId;
set
{
if (SetField(ref processId, value))
{
OnPropertyChanged(nameof(Process));
}
}
}
public string Process public string Process
{ {
get => process; get
set => SetField(ref process, value); {
try
{
var process = System.Diagnostics.Process.GetProcessById(processId);
return process.ProcessName + ":" + processId;
}
catch (Exception)
{
return string.Empty;
}
}
} }
public long ReceivedDataCount public long ReceivedDataCount
...@@ -80,13 +102,16 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -80,13 +102,16 @@ namespace Titanium.Web.Proxy.Examples.Wpf
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
protected void SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null) protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{ {
if (!Equals(field, value)) if (!Equals(field, value))
{ {
field = value; field = value;
OnPropertyChanged(propertyName); OnPropertyChanged(propertyName);
return true;
} }
return false;
} }
[NotifyPropertyChangedInvocator] [NotifyPropertyChangedInvocator]
...@@ -132,20 +157,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -132,20 +157,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
BodySize = responseSize; BodySize = responseSize;
} }
Process = GetProcessDescription(HttpClient.ProcessId.Value); ProcessId = HttpClient.ProcessId.Value;
}
private string GetProcessDescription(int processId)
{
try
{
var process = System.Diagnostics.Process.GetProcessById(processId);
return process.ProcessName + ":" + processId;
}
catch (Exception)
{
return string.Empty;
}
} }
} }
} }
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Titanium.Web.Proxy\Titanium.Web.Proxy.csproj" />
</ItemGroup>
</Project>
\ No newline at end of file
...@@ -72,9 +72,6 @@ ...@@ -72,9 +72,6 @@
<Prefer32Bit>true</Prefer32Bit> <Prefer32Bit>true</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="StreamExtended, Version=1.0.190.0, Culture=neutral, PublicKeyToken=bbfa0f1d54f50043, processorArchitecture=MSIL">
<HintPath>..\..\src\packages\StreamExtended.1.0.190\lib\net45\StreamExtended.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
...@@ -95,6 +92,7 @@ ...@@ -95,6 +92,7 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</ApplicationDefinition> </ApplicationDefinition>
<Compile Include="ObservableCollectionEx.cs" />
<Compile Include="Properties\Annotations.cs" /> <Compile Include="Properties\Annotations.cs" />
<Compile Include="SessionListItem.cs" /> <Compile Include="SessionListItem.cs" />
<Page Include="MainWindow.xaml"> <Page Include="MainWindow.xaml">
...@@ -128,7 +126,6 @@ ...@@ -128,7 +126,6 @@
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings"> <None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
......
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="StreamExtended" version="1.0.190" targetFramework="net45" />
</packages>
\ No newline at end of file
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio Version 16
VisualStudioVersion = 15.0.26906.1 VisualStudioVersion = 16.0.29102.190
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{B6DBABDC-C985-4872-9C38-B4E5079CBC4B}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{B6DBABDC-C985-4872-9C38-B4E5079CBC4B}"
EndProject EndProject
...@@ -23,7 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BC1E0789 ...@@ -23,7 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BC1E0789
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy", "Titanium.Web.Proxy\Titanium.Web.Proxy.csproj", "{91018B6D-A7A9-45BE-9CB3-79CBB8B169A6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy", "Titanium.Web.Proxy\Titanium.Web.Proxy.csproj", "{91018B6D-A7A9-45BE-9CB3-79CBB8B169A6}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Titanium.Web.Proxy.UnitTests", "..\tests\Titanium.Web.Proxy.UnitTests\Titanium.Web.Proxy.UnitTests.csproj", "{B517E3D0-D03B-436F-AB03-34BA0D5321AF}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy.UnitTests", "..\tests\Titanium.Web.Proxy.UnitTests\Titanium.Web.Proxy.UnitTests.csproj", "{B517E3D0-D03B-436F-AB03-34BA0D5321AF}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy.Examples.Basic", "..\examples\Titanium.Web.Proxy.Examples.Basic\Titanium.Web.Proxy.Examples.Basic.csproj", "{1FAC4205-4445-4F2B-BB8F-618E8A0C15FD}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy.Examples.Basic", "..\examples\Titanium.Web.Proxy.Examples.Basic\Titanium.Web.Proxy.Examples.Basic.csproj", "{1FAC4205-4445-4F2B-BB8F-618E8A0C15FD}"
EndProject EndProject
......
...@@ -19,16 +19,19 @@ ...@@ -19,16 +19,19 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MTA/@EntryIndexedValue">MTA</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MTA/@EntryIndexedValue">MTA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OID/@EntryIndexedValue">OID</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OID/@EntryIndexedValue">OID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OIDS/@EntryIndexedValue">OIDS</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OIDS/@EntryIndexedValue">OIDS</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpNaming/ApplyAutoDetectedRules/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PublicFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a4ab2e69_002D4d9c_002D4345_002Dbcd1_002D5541dacf5d38/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Method (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="METHOD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a4ab2e69_002D4d9c_002D4345_002Dbcd1_002D5541dacf5d38/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Method (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="METHOD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=dda2ffa1_002D435c_002D4111_002D88eb_002D1a7c93c382f0/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Property (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="PROPERTY" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=dda2ffa1_002D435c_002D4111_002D88eb_002D1a7c93c382f0/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Property (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="PROPERTY" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpRenamePlacementToArrangementMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
......
...@@ -29,7 +29,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -29,7 +29,7 @@ namespace Titanium.Web.Proxy.EventArguments
public X509Certificate RemoteCertificate { get; internal set; } public X509Certificate RemoteCertificate { get; internal set; }
/// <summary> /// <summary>
/// Acceptable issuers as listed by remoted server. /// Acceptable issuers as listed by remote server.
/// </summary> /// </summary>
public string[] AcceptableIssuers { get; internal set; } public string[] AcceptableIssuers { get; internal set; }
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended; using Titanium.Web.Proxy.Exceptions;
using StreamExtended.Network; using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
...@@ -60,7 +61,11 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -60,7 +61,11 @@ namespace Titanium.Web.Proxy.EventArguments
chunkHead = chunkHead.Substring(0, idx); chunkHead = chunkHead.Substring(0, idx);
} }
int chunkSize = int.Parse(chunkHead, NumberStyles.HexNumber); if (!int.TryParse(chunkHead, NumberStyles.HexNumber, null, out int chunkSize))
{
throw new ProxyHttpException($"Invalid chunk length: '{chunkHead}'", null, null);
}
bytesRemaining = chunkSize; bytesRemaining = chunkSize;
if (chunkSize == 0) if (chunkSize == 0)
......
...@@ -4,12 +4,12 @@ using System.IO; ...@@ -4,12 +4,12 @@ using System.IO;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.Compression; using Titanium.Web.Proxy.Compression;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http.Responses; using Titanium.Web.Proxy.Http.Responses;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
...@@ -28,6 +28,11 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -28,6 +28,11 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
private bool reRequest; private bool reRequest;
/// <summary>
/// Is this session a HTTP/2 promise?
/// </summary>
public bool IsPromise { get; internal set; }
/// <summary> /// <summary>
/// Constructor to initialize the proxy /// Constructor to initialize the proxy
/// </summary> /// </summary>
...@@ -88,6 +93,27 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -88,6 +93,27 @@ namespace Titanium.Web.Proxy.EventArguments
// If not already read (not cached yet) // If not already read (not cached yet)
if (!request.IsBodyRead) if (!request.IsBodyRead)
{
if (request.HttpVersion == HttpHeader.Version20)
{
// do not send to the remote endpoint
request.Http2IgnoreBodyFrames = true;
request.Http2BodyData = new MemoryStream();
var tcs = new TaskCompletionSource<bool>();
request.ReadHttp2BodyTaskCompletionSource = tcs;
// signal to HTTP/2 copy frame method to continue
request.ReadHttp2BeforeHandlerTaskCompletionSource.SetResult(true);
await tcs.Task;
// Now set the flag to true
// So that next time we can deliver body from cache
request.IsBodyRead = true;
}
else
{ {
var body = await readBodyAsync(true, cancellationToken); var body = await readBodyAsync(true, cancellationToken);
request.Body = body; request.Body = body;
...@@ -98,6 +124,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -98,6 +124,7 @@ namespace Titanium.Web.Proxy.EventArguments
OnDataSent(body, 0, body.Length); OnDataSent(body, 0, body.Length);
} }
} }
}
/// <summary> /// <summary>
/// reinit response object /// reinit response object
...@@ -117,7 +144,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -117,7 +144,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
catch (Exception ex) catch (Exception ex)
{ {
exceptionFunc(new Exception("Exception thrown in user event", ex)); ExceptionFunc(new Exception("Exception thrown in user event", ex));
} }
} }
...@@ -139,6 +166,27 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -139,6 +166,27 @@ namespace Titanium.Web.Proxy.EventArguments
// If not already read (not cached yet) // If not already read (not cached yet)
if (!response.IsBodyRead) if (!response.IsBodyRead)
{
if (response.HttpVersion == HttpHeader.Version20)
{
// do not send to the remote endpoint
response.Http2IgnoreBodyFrames = true;
response.Http2BodyData = new MemoryStream();
var tcs = new TaskCompletionSource<bool>();
response.ReadHttp2BodyTaskCompletionSource = tcs;
// signal to HTTP/2 copy frame method to continue
response.ReadHttp2BeforeHandlerTaskCompletionSource.SetResult(true);
await tcs.Task;
// Now set the flag to true
// So that next time we can deliver body from cache
response.IsBodyRead = true;
}
else
{ {
var body = await readBodyAsync(false, cancellationToken); var body = await readBodyAsync(false, cancellationToken);
response.Body = body; response.Body = body;
...@@ -149,12 +197,13 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -149,12 +197,13 @@ namespace Titanium.Web.Proxy.EventArguments
OnDataReceived(body, 0, body.Length); OnDataReceived(body, 0, body.Length);
} }
} }
}
private async Task<byte[]> readBodyAsync(bool isRequest, CancellationToken cancellationToken) private async Task<byte[]> readBodyAsync(bool isRequest, CancellationToken cancellationToken)
{ {
using (var bodyStream = new MemoryStream()) using (var bodyStream = new MemoryStream())
{ {
var writer = new HttpWriter(bodyStream, bufferPool, bufferSize); var writer = new HttpWriter(bodyStream, BufferPool, BufferSize);
if (isRequest) if (isRequest)
{ {
...@@ -186,7 +235,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -186,7 +235,7 @@ namespace Titanium.Web.Proxy.EventArguments
using (var bodyStream = new MemoryStream()) using (var bodyStream = new MemoryStream())
{ {
var writer = new HttpWriter(bodyStream, bufferPool, bufferSize); var writer = new HttpWriter(bodyStream, BufferPool, BufferSize);
await copyBodyAsync(isRequest, true, writer, TransformationMode.None, null, cancellationToken); await copyBodyAsync(isRequest, true, writer, TransformationMode.None, null, cancellationToken);
} }
} }
...@@ -207,7 +256,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -207,7 +256,7 @@ namespace Titanium.Web.Proxy.EventArguments
var reader = getStreamReader(true); var reader = getStreamReader(true);
string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType); string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType);
using (var copyStream = new CopyStream(reader, writer, bufferPool, bufferSize)) using (var copyStream = new CopyStream(reader, writer, BufferPool, BufferSize))
{ {
while (contentLength > copyStream.ReadBytes) while (contentLength > copyStream.ReadBytes)
{ {
...@@ -259,7 +308,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -259,7 +308,7 @@ namespace Titanium.Web.Proxy.EventArguments
string contentEncoding = useOriginalHeaderValues ? requestResponse.OriginalContentEncoding : requestResponse.ContentEncoding; string contentEncoding = useOriginalHeaderValues ? requestResponse.OriginalContentEncoding : requestResponse.ContentEncoding;
Stream s = limitedStream = new LimitedStream(stream, bufferPool, isChunked, contentLength); Stream s = limitedStream = new LimitedStream(stream, BufferPool, isChunked, contentLength);
if (transformation == TransformationMode.Uncompress && contentEncoding != null) if (transformation == TransformationMode.Uncompress && contentEncoding != null)
{ {
...@@ -268,7 +317,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -268,7 +317,7 @@ namespace Titanium.Web.Proxy.EventArguments
try try
{ {
using (var bufStream = new CustomBufferedStream(s, bufferPool, bufferSize, true)) using (var bufStream = new CustomBufferedStream(s, BufferPool, BufferSize, true))
{ {
await writer.CopyBodyAsync(bufStream, false, -1, onCopy, cancellationToken); await writer.CopyBodyAsync(bufStream, false, -1, onCopy, cancellationToken);
} }
...@@ -290,7 +339,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -290,7 +339,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
int bufferDataLength = 0; int bufferDataLength = 0;
var buffer = bufferPool.GetBuffer(bufferSize); var buffer = BufferPool.GetBuffer(BufferSize);
try try
{ {
int boundaryLength = boundary.Length + 4; int boundaryLength = boundary.Length + 4;
...@@ -340,7 +389,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -340,7 +389,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
finally finally
{ {
bufferPool.ReturnBuffer(buffer); BufferPool.ReturnBuffer(buffer);
} }
} }
......
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using StreamExtended;
using StreamExtended.Network;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network; using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
...@@ -24,14 +24,14 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -24,14 +24,14 @@ namespace Titanium.Web.Proxy.EventArguments
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 int BufferSize;
protected readonly IBufferPool bufferPool; protected readonly IBufferPool BufferPool;
protected readonly ExceptionHandler exceptionFunc; protected readonly ExceptionHandler ExceptionFunc;
/// <summary> /// <summary>
/// Relative milliseconds for various events. /// Relative milliseconds for various events.
/// </summary> /// </summary>
public Dictionary<string, DateTime> TimeLine { get; set; } = new Dictionary<string, DateTime>(); public Dictionary<string, DateTime> TimeLine { get; } = new Dictionary<string, DateTime>();
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class. /// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
...@@ -39,9 +39,9 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -39,9 +39,9 @@ namespace Titanium.Web.Proxy.EventArguments
private SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, private SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
CancellationTokenSource cancellationTokenSource) CancellationTokenSource cancellationTokenSource)
{ {
bufferSize = server.BufferSize; 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;
} }
...@@ -55,25 +55,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -55,25 +55,7 @@ namespace Titanium.Web.Proxy.EventArguments
HttpClient = new HttpWebClient(request); HttpClient = new HttpWebClient(request);
LocalEndPoint = endPoint; LocalEndPoint = endPoint;
HttpClient.ProcessId = new Lazy<int>(() => HttpClient.ProcessId = new Lazy<int>(() => ProxyClient.Connection.GetProcessId(endPoint));
{
if (RunTime.IsWindows)
{
var remoteEndPoint = ClientEndPoint;
// If client is localhost get the process id
if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
{
var ipVersion = endPoint.IpV6Enabled ? IpVersion.Ipv6 : IpVersion.Ipv4;
return TcpHelper.GetProcessIdByLocalPort(ipVersion, remoteEndPoint.Port);
}
// can't access process Id of remote request from remote machine
return -1;
}
throw new PlatformNotSupportedException();
});
} }
/// <summary> /// <summary>
...@@ -161,7 +143,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -161,7 +143,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
catch (Exception ex) catch (Exception ex)
{ {
exceptionFunc(new Exception("Exception thrown in user event", ex)); ExceptionFunc(new Exception("Exception thrown in user event", ex));
} }
} }
...@@ -173,7 +155,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -173,7 +155,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
catch (Exception ex) catch (Exception ex)
{ {
exceptionFunc(new Exception("Exception thrown in user event", ex)); ExceptionFunc(new Exception("Exception thrown in user event", ex));
} }
} }
......
...@@ -31,12 +31,12 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -31,12 +31,12 @@ namespace Titanium.Web.Proxy.EventArguments
public bool DenyConnect { get; set; } public bool DenyConnect { get; set; }
/// <summary> /// <summary>
/// Is this a connect request to secure HTTP server? Or is it to someother protocol. /// Is this a connect request to secure HTTP server? Or is it to some other protocol.
/// </summary> /// </summary>
public bool IsHttpsConnect public bool IsHttpsConnect
{ {
get => isHttpsConnect ?? get => isHttpsConnect ??
throw new Exception("The value of this property is known in the BeforeTunnectConnectResponse event"); throw new Exception("The value of this property is known in the BeforeTunnelConnectResponse event");
internal set => isHttpsConnect = value; internal set => isHttpsConnect = value;
} }
......
...@@ -20,7 +20,7 @@ namespace Titanium.Web.Proxy.Exceptions ...@@ -20,7 +20,7 @@ namespace Titanium.Web.Proxy.Exceptions
/// Initializes a new instance of the <see cref="ProxyException" /> class. /// Initializes a new instance of the <see cref="ProxyException" /> class.
/// - must be invoked by derived classes' constructors /// - must be invoked by derived classes' constructors
/// </summary> /// </summary>
/// <param name="message">Excception 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)
{ {
......
...@@ -5,7 +5,7 @@ using System.Security.Authentication; ...@@ -5,7 +5,7 @@ using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended; using Titanium.Web.Proxy.StreamExtended;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended; using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
...@@ -17,6 +17,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -17,6 +17,7 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="input"></param> /// <param name="input"></param>
/// <param name="output"></param> /// <param name="output"></param>
/// <param name="onCopy"></param> /// <param name="onCopy"></param>
/// <param name="bufferPool"></param>
/// <param name="bufferSize"></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, int bufferSize)
...@@ -30,6 +31,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -30,6 +31,7 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="input"></param> /// <param name="input"></param>
/// <param name="output"></param> /// <param name="output"></param>
/// <param name="onCopy"></param> /// <param name="onCopy"></param>
/// <param name="bufferPool"></param>
/// <param name="bufferSize"></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,
......
using System; using System;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
...@@ -120,9 +123,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -120,9 +123,9 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
/// <param name="clientStreamReader">The client stream reader.</param> /// <param name="clientStreamReader">The client stream reader.</param>
/// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns> /// <returns>1: when CONNECT, 0: when valid HTTP method, -1: otherwise</returns>
internal static Task<int> IsConnectMethod(ICustomStreamReader clientStreamReader) internal static Task<int> IsConnectMethod(ICustomStreamReader clientStreamReader, IBufferPool bufferPool, int bufferSize, CancellationToken cancellationToken = default)
{ {
return startsWith(clientStreamReader, "CONNECT"); return startsWith(clientStreamReader, bufferPool, bufferSize, "CONNECT", cancellationToken);
} }
/// <summary> /// <summary>
...@@ -130,9 +133,9 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -130,9 +133,9 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
/// <param name="clientStreamReader">The client stream reader.</param> /// <param name="clientStreamReader">The client stream reader.</param>
/// <returns>1: when PRI, 0: when valid HTTP method, -1: otherwise</returns> /// <returns>1: when PRI, 0: when valid HTTP method, -1: otherwise</returns>
internal static Task<int> IsPriMethod(ICustomStreamReader clientStreamReader) internal static Task<int> IsPriMethod(ICustomStreamReader clientStreamReader, IBufferPool bufferPool, int bufferSize, CancellationToken cancellationToken = default)
{ {
return startsWith(clientStreamReader, "PRI"); return startsWith(clientStreamReader, bufferPool, bufferSize, "PRI", cancellationToken);
} }
/// <summary> /// <summary>
...@@ -143,37 +146,47 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -143,37 +146,47 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns> /// <returns>
/// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise /// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise
/// </returns> /// </returns>
private static async Task<int> startsWith(ICustomStreamReader clientStreamReader, string expectedStart) private static async Task<int> startsWith(ICustomStreamReader clientStreamReader, IBufferPool bufferPool, int bufferSize, string expectedStart, CancellationToken cancellationToken = default)
{ {
bool isExpected = true; int iRet = -1;
int legthToCheck = 10; const int lengthToCheck = 10;
for (int i = 0; i < legthToCheck; i++) byte[] buffer = null;
try
{ {
int b = await clientStreamReader.PeekByteAsync(i); buffer = bufferPool.GetBuffer(Math.Max(bufferSize, lengthToCheck));
if (b == -1)
int peeked = await clientStreamReader.PeekBytesAsync(buffer, 0, 0, lengthToCheck, cancellationToken);
if (peeked > 0)
{ {
return -1; bool isExpected = true;
}
if (b == ' ' && i > 2) for (int i = 0; i < lengthToCheck; i++)
{ {
return isExpected ? 1 : 0; int b = buffer[i];
}
if (b == ' ' && i > 2)
return isExpected ? 1 : 0;
else
{
char ch = (char)b; char ch = (char)b;
if (!char.IsLetter(ch)) if (!char.IsLetter(ch))
{
return -1; return -1;
} else if (i >= expectedStart.Length || ch != expectedStart[i])
if (i >= expectedStart.Length || ch != expectedStart[i])
{
isExpected = false; isExpected = false;
} }
} }
// only letters // only letters
return isExpected ? 1 : 0; iRet = isExpected ? 1 : 0;
}
}
finally
{
bufferPool.ReturnBuffer(buffer);
buffer = null;
}
return iRet;
} }
} }
} }
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
...@@ -23,7 +23,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -23,7 +23,7 @@ namespace Titanium.Web.Proxy.Helpers
internal async Task WriteRequestAsync(Request request, bool flush = true, internal async Task WriteRequestAsync(Request request, bool flush = true,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
await WriteLineAsync(Request.CreateRequestLine(request.Method, request.OriginalUrl, request.HttpVersion), await WriteLineAsync(Request.CreateRequestLine(request.Method, request.RequestUriString, request.HttpVersion),
cancellationToken); cancellationToken);
await WriteAsync(request, flush, cancellationToken); await WriteAsync(request, flush, cancellationToken);
} }
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
......
...@@ -4,10 +4,10 @@ using System.IO; ...@@ -4,10 +4,10 @@ using System.IO;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended;
using StreamExtended.Network;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
...@@ -18,18 +18,13 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -18,18 +18,13 @@ namespace Titanium.Web.Proxy.Helpers
private static readonly byte[] newLine = ProxyConstants.NewLineBytes; private static readonly byte[] newLine = ProxyConstants.NewLineBytes;
private static readonly Encoder encoder = Encoding.ASCII.GetEncoder(); private static readonly Encoding encoder = Encoding.ASCII;
private readonly char[] charBuffer;
internal HttpWriter(Stream stream, IBufferPool bufferPool, int bufferSize) internal HttpWriter(Stream stream, IBufferPool bufferPool, int bufferSize)
{ {
BufferSize = bufferSize; BufferSize = bufferSize;
this.stream = stream; this.stream = stream;
this.bufferPool = bufferPool; this.bufferPool = bufferPool;
// ASCII encoder max byte count is char count + 1
charBuffer = new char[BufferSize - 1];
} }
internal int BufferSize { get; } internal int BufferSize { get; }
...@@ -55,12 +50,10 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -55,12 +50,10 @@ namespace Titanium.Web.Proxy.Helpers
int charCount = value.Length; int charCount = value.Length;
if (charCount < BufferSize - newLineChars) if (charCount < BufferSize - newLineChars)
{ {
value.CopyTo(0, charBuffer, 0, charCount);
var buffer = bufferPool.GetBuffer(BufferSize); var buffer = bufferPool.GetBuffer(BufferSize);
try try
{ {
int idx = encoder.GetBytes(charBuffer, 0, charCount, buffer, 0, true); int idx = encoder.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);
...@@ -76,11 +69,8 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -76,11 +69,8 @@ namespace Titanium.Web.Proxy.Helpers
} }
else else
{ {
var charBuffer = new char[charCount];
value.CopyTo(0, charBuffer, 0, charCount);
var buffer = new byte[charCount + newLineChars + 1]; var buffer = new byte[charCount + newLineChars + 1];
int idx = encoder.GetBytes(charBuffer, 0, charCount, buffer, 0, true); int idx = encoder.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);
......
namespace Titanium.Web.Proxy.Helpers
{
internal class Ref<T>
{
internal Ref()
{
}
internal Ref(T value)
{
Value = value;
}
internal T Value { get; set; }
public override string ToString()
{
var value = Value;
return value == null ? string.Empty : value.ToString();
}
public static implicit operator T(Ref<T> r)
{
return r.Value;
}
public static implicit operator Ref<T>(T value)
{
return new Ref<T>(value);
}
}
}
...@@ -70,7 +70,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -70,7 +70,7 @@ namespace Titanium.Web.Proxy.Helpers
internal static bool IsRunningAsUwp() internal static bool IsRunningAsUwp()
{ {
if (IsWindows7OrLower) if (isWindows7OrLower)
{ {
return false; return false;
} }
...@@ -87,7 +87,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -87,7 +87,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
} }
private static bool IsWindows7OrLower private static bool isWindows7OrLower
{ {
get get
{ {
......
...@@ -80,7 +80,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -80,7 +80,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="protocolType"></param> /// <param name="protocolType"></param>
internal void SetProxy(string hostname, int port, ProxyProtocolType protocolType) internal void SetProxy(string hostname, int port, ProxyProtocolType protocolType)
{ {
using (var reg = OpenInternetSettingsKey()) using (var reg = openInternetSettingsKey())
{ {
if (reg == null) if (reg == null)
{ {
...@@ -127,7 +127,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -127,7 +127,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
internal void RemoveProxy(ProxyProtocolType protocolType, bool saveOriginalConfig = true) internal void RemoveProxy(ProxyProtocolType protocolType, bool saveOriginalConfig = true)
{ {
using (var reg = OpenInternetSettingsKey()) using (var reg = openInternetSettingsKey())
{ {
if (reg == null) if (reg == null)
{ {
...@@ -168,7 +168,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -168,7 +168,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
internal void DisableAllProxy() internal void DisableAllProxy()
{ {
using (var reg = OpenInternetSettingsKey()) using (var reg = openInternetSettingsKey())
{ {
if (reg == null) if (reg == null)
{ {
...@@ -186,7 +186,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -186,7 +186,7 @@ namespace Titanium.Web.Proxy.Helpers
internal void SetAutoProxyUrl(string url) internal void SetAutoProxyUrl(string url)
{ {
using (var reg = OpenInternetSettingsKey()) using (var reg = openInternetSettingsKey())
{ {
if (reg == null) if (reg == null)
{ {
...@@ -201,7 +201,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -201,7 +201,7 @@ namespace Titanium.Web.Proxy.Helpers
internal void SetProxyOverride(string proxyOverride) internal void SetProxyOverride(string proxyOverride)
{ {
using (var reg = OpenInternetSettingsKey()) using (var reg = openInternetSettingsKey())
{ {
if (reg == null) if (reg == null)
{ {
...@@ -286,7 +286,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -286,7 +286,7 @@ namespace Titanium.Web.Proxy.Helpers
internal ProxyInfo GetProxyInfoFromRegistry() internal ProxyInfo GetProxyInfoFromRegistry()
{ {
using (var reg = OpenInternetSettingsKey()) using (var reg = openInternetSettingsKey())
{ {
if (reg == null) if (reg == null)
{ {
...@@ -347,7 +347,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -347,7 +347,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary> /// <summary>
/// Opens the registry key with the internet settings /// Opens the registry key with the internet settings
/// </summary> /// </summary>
private static RegistryKey OpenInternetSettingsKey() private static RegistryKey openInternetSettingsKey()
{ {
return Registry.CurrentUser.OpenSubKey(regKeyInternetSettings, true); return Registry.CurrentUser.OpenSubKey(regKeyInternetSettings, true);
} }
......
using System; using System;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
...@@ -96,11 +96,12 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -96,11 +96,12 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary> /// <summary>
/// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers
/// as prefix /// as prefix
/// Usefull for websocket requests /// Useful for websocket requests
/// Task-based Asynchronous Pattern /// Task-based Asynchronous Pattern
/// </summary> /// </summary>
/// <param name="clientStream"></param> /// <param name="clientStream"></param>
/// <param name="serverStream"></param> /// <param name="serverStream"></param>
/// <param name="bufferPool"></param>
/// <param name="bufferSize"></param> /// <param name="bufferSize"></param>
/// <param name="onDataSend"></param> /// <param name="onDataSend"></param>
/// <param name="onDataReceive"></param> /// <param name="onDataReceive"></param>
...@@ -128,10 +129,11 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -128,10 +129,11 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary> /// <summary>
/// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers /// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers
/// as prefix /// as prefix
/// Usefull for websocket requests /// Useful for websocket requests
/// </summary> /// </summary>
/// <param name="clientStream"></param> /// <param name="clientStream"></param>
/// <param name="serverStream"></param> /// <param name="serverStream"></param>
/// <param name="bufferPool"></param>
/// <param name="bufferSize"></param> /// <param name="bufferSize"></param>
/// <param name="onDataSend"></param> /// <param name="onDataSend"></param>
/// <param name="onDataReceive"></param> /// <param name="onDataReceive"></param>
......
using StreamExtended; using Titanium.Web.Proxy.StreamExtended;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
{ {
...@@ -12,6 +12,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -12,6 +12,8 @@ namespace Titanium.Web.Proxy.Http
Method = "CONNECT"; Method = "CONNECT";
} }
public TunnelType TunnelType { get; internal set; }
public ClientHelloInfo ClientHelloInfo { get; set; } public ClientHelloInfo ClientHelloInfo { get; set; }
} }
} }
using System; using System;
using System.Net; using System.Net;
using StreamExtended; using Titanium.Web.Proxy.StreamExtended;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
{ {
...@@ -12,11 +12,11 @@ namespace Titanium.Web.Proxy.Http ...@@ -12,11 +12,11 @@ namespace Titanium.Web.Proxy.Http
public ServerHelloInfo ServerHelloInfo { get; set; } public ServerHelloInfo ServerHelloInfo { get; set; }
/// <summary> /// <summary>
/// Creates a successfull CONNECT response /// Creates a successful CONNECT response
/// </summary> /// </summary>
/// <param name="httpVersion"></param> /// <param name="httpVersion"></param>
/// <returns></returns> /// <returns></returns>
internal static ConnectResponse CreateSuccessfullConnectResponse(Version httpVersion) internal static ConnectResponse CreateSuccessfulConnectResponse(Version httpVersion)
{ {
var response = new ConnectResponse var response = new ConnectResponse
{ {
......
...@@ -67,7 +67,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -67,7 +67,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// Returns all headers with given name if exists /// Returns all headers with given name if exists
/// Returns null if does'nt exist /// Returns null if doesn't exist
/// </summary> /// </summary>
/// <param name="name"></param> /// <param name="name"></param>
/// <returns></returns> /// <returns></returns>
......
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
{ {
......
...@@ -97,10 +97,19 @@ namespace Titanium.Web.Proxy.Http ...@@ -97,10 +97,19 @@ namespace Titanium.Web.Proxy.Http
var writer = Connection.StreamWriter; var writer = Connection.StreamWriter;
string url;
if (useUpstreamProxy || isTransparent)
{
url = Request.RequestUriString;
}
else
{
var uri = Request.RequestUri;
url = uri.IsWellFormedOriginalString() ? uri.PathAndQuery : uri.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
}
// prepare the request & headers // prepare the request & headers
await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method, await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method, url, Request.HttpVersion), cancellationToken);
useUpstreamProxy || isTransparent ? Request.OriginalUrl : Request.RequestUri.PathAndQuery,
Request.HttpVersion), cancellationToken);
var headerBuilder = new StringBuilder(); var headerBuilder = new StringBuilder();
......
...@@ -6,28 +6,28 @@ ...@@ -6,28 +6,28 @@
public static class KnownHeaders public static class KnownHeaders
{ {
// Both // Both
public const string Connection = "connection"; public const string Connection = "Connection";
public const string ConnectionClose = "close"; public const string ConnectionClose = "close";
public const string ConnectionKeepAlive = "keep-alive"; public const string ConnectionKeepAlive = "keep-alive";
public const string ContentLength = "content-length"; public const string ContentLength = "Content-Length";
public const string ContentType = "content-type"; public const string ContentType = "Content-Type";
public const string ContentTypeCharset = "charset"; public const string ContentTypeCharset = "charset";
public const string ContentTypeBoundary = "boundary"; public const string ContentTypeBoundary = "boundary";
public const string Upgrade = "upgrade"; public const string Upgrade = "Upgrade";
public const string UpgradeWebsocket = "websocket"; public const string UpgradeWebsocket = "websocket";
// Request headers // Request headers
public const string AcceptEncoding = "accept-encoding"; public const string AcceptEncoding = "Accept-Encoding";
public const string Authorization = "Authorization"; public const string Authorization = "Authorization";
public const string Expect = "expect"; public const string Expect = "Expect";
public const string Expect100Continue = "100-continue"; public const string Expect100Continue = "100-continue";
public const string Host = "host"; public const string Host = "Host";
public const string ProxyAuthorization = "Proxy-Authorization"; public const string ProxyAuthorization = "Proxy-Authorization";
public const string ProxyAuthorizationBasic = "basic"; public const string ProxyAuthorizationBasic = "basic";
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
public const string ProxyConnectionClose = "close"; public const string ProxyConnectionClose = "close";
// Response headers // Response headers
public const string ContentEncoding = "content-encoding"; public const string ContentEncoding = "Content-Encoding";
public const string ContentEncodingDeflate = "deflate"; public const string ContentEncodingDeflate = "deflate";
public const string ContentEncodingGzip = "gzip"; public const string ContentEncodingGzip = "gzip";
public const string ContentEncodingBrotli = "br"; public const string ContentEncodingBrotli = "br";
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
public const string ProxyAuthenticate = "Proxy-Authenticate"; public const string ProxyAuthenticate = "Proxy-Authenticate";
public const string TransferEncoding = "transfer-encoding"; public const string TransferEncoding = "Transfer-Encoding";
public const string TransferEncodingChunked = "chunked"; public const string TransferEncodingChunked = "chunked";
} }
} }
...@@ -14,6 +14,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -14,6 +14,8 @@ 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>
...@@ -32,7 +34,20 @@ namespace Titanium.Web.Proxy.Http ...@@ -32,7 +34,20 @@ namespace Titanium.Web.Proxy.Http
/// <summary> /// <summary>
/// The original request Url. /// The original request Url.
/// </summary> /// </summary>
public string OriginalUrl { get; set; } public string OriginalUrl
{
get => originalUrl;
internal set
{
originalUrl = value;
RequestUriString = value;
}
}
/// <summary>
/// The request uri as it is in the HTTP header
/// </summary>
public string RequestUriString { get; set; }
/// <summary> /// <summary>
/// Has request body? /// Has request body?
...@@ -140,7 +155,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -140,7 +155,7 @@ namespace Titanium.Web.Proxy.Http
get get
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.Append($"{CreateRequestLine(Method, OriginalUrl, HttpVersion)}{ProxyConstants.NewLine}"); sb.Append($"{CreateRequestLine(Method, RequestUriString, HttpVersion)}{ProxyConstants.NewLine}");
foreach (var header in Headers) foreach (var header in Headers)
{ {
sb.Append($"{header.ToString()}{ProxyConstants.NewLine}"); sb.Append($"{header.ToString()}{ProxyConstants.NewLine}");
......
...@@ -3,6 +3,7 @@ using System.ComponentModel; ...@@ -3,6 +3,7 @@ using System.ComponentModel;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Compression; using Titanium.Web.Proxy.Compression;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
...@@ -49,6 +50,21 @@ namespace Titanium.Web.Proxy.Http ...@@ -49,6 +50,21 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
internal string OriginalContentEncoding { get; set; } internal string OriginalContentEncoding { get; set; }
internal TaskCompletionSource<bool> ReadHttp2BeforeHandlerTaskCompletionSource;
internal TaskCompletionSource<bool> ReadHttp2BodyTaskCompletionSource;
internal MemoryStream Http2BodyData;
internal bool Http2IgnoreBodyFrames;
internal Task Http2BeforeHandlerTask;
/// <summary>
/// Priority used only in HTTP/2
/// </summary>
internal long? Priority;
/// <summary> /// <summary>
/// Keeps the body data after the session is finished. /// Keeps the body data after the session is finished.
/// </summary> /// </summary>
...@@ -189,11 +205,13 @@ namespace Titanium.Web.Proxy.Http ...@@ -189,11 +205,13 @@ namespace Titanium.Web.Proxy.Http
public bool IsBodyRead { get; internal set; } public bool IsBodyRead { get; internal set; }
/// <summary> /// <summary>
/// Is the request/response no more modifyable by user (user callbacks complete?) /// Is the request/response no more modifiable by user (user callbacks complete?)
/// Also if user set this as a custom response then this should be true. /// Also if user set this as a custom response then this should be true.
/// </summary> /// </summary>
internal bool Locked { get; set; } internal bool Locked { get; set; }
internal bool BodyAvailable => BodyInternal != null;
internal abstract void EnsureBodyAvailable(bool throwWhenNotReadYet = true); internal abstract void EnsureBodyAvailable(bool throwWhenNotReadYet = true);
/// <summary> /// <summary>
......
namespace Titanium.Web.Proxy.Http
{
public enum TunnelType
{
Unknown,
Https,
Websocket,
Http2,
}
}
...@@ -61,7 +61,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -61,7 +61,9 @@ 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>
public void EncodeHeader(BinaryWriter output, string name, string value, bool sensitive = false) /// <param name="indexType">Index type.</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)
{ {
// 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)
...@@ -116,10 +118,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -116,10 +118,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack
} }
else else
{ {
int nameIndex = getNameIndex(name); int nameIndex = useStaticName ? getNameIndex(name) : -1;
ensureCapacity(headerSize); ensureCapacity(headerSize);
var indexType = HpackUtil.IndexType.Incremental;
encodeLiteral(output, name, value, indexType, nameIndex); encodeLiteral(output, name, value, indexType, nameIndex);
add(name, value); add(name, value);
} }
...@@ -309,7 +310,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -309,7 +310,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 && Equals(name, e.Name) && Equals(value, e.Value)) if (e.Hash == h && name.Equals(e.Name, StringComparison.OrdinalIgnoreCase) && Equals(value, e.Value))
{ {
return e; return e;
} }
...@@ -336,7 +337,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -336,7 +337,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
int index = -1; int index = -1;
for (var e = headerFields[i]; e != null; e = e.Next) for (var e = headerFields[i]; e != null; e = e.Next)
{ {
if (e.Hash == h && HpackUtil.Equals(name, e.Name)) if (e.Hash == h && name.Equals(e.Name, StringComparison.OrdinalIgnoreCase))
{ {
index = e.Index; index = e.Index;
break; break;
...@@ -513,7 +514,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -513,7 +514,7 @@ 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) public HeaderEntry(int hash, string name, string value, int index, HeaderEntry next) : base(name, value, true)
{ {
Index = index; Index = index;
Hash = hash; Hash = hash;
......
...@@ -59,102 +59,102 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -59,102 +59,102 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/* 14 */ /* 14 */
new HttpHeader(":status", "500"), new HttpHeader(":status", "500"),
/* 15 */ /* 15 */
new HttpHeader("accept-charset", string.Empty), new HttpHeader("Accept-Charset", string.Empty),
/* 16 */ /* 16 */
new HttpHeader("accept-encoding", "gzip, deflate"), new HttpHeader("Accept-Encoding", "gzip, deflate"),
/* 17 */ /* 17 */
new HttpHeader("accept-language", string.Empty), new HttpHeader("Accept-Language", string.Empty),
/* 18 */ /* 18 */
new HttpHeader("accept-ranges", string.Empty), new HttpHeader("Accept-Ranges", string.Empty),
/* 19 */ /* 19 */
new HttpHeader("accept", string.Empty), new HttpHeader("Accept", string.Empty),
/* 20 */ /* 20 */
new HttpHeader("access-control-allow-origin", string.Empty), new HttpHeader("Access-Control-Allow-Origin", string.Empty),
/* 21 */ /* 21 */
new HttpHeader("age", string.Empty), new HttpHeader("Age", string.Empty),
/* 22 */ /* 22 */
new HttpHeader("allow", string.Empty), new HttpHeader("Allow", string.Empty),
/* 23 */ /* 23 */
new HttpHeader("authorization", string.Empty), new HttpHeader("Authorization", string.Empty),
/* 24 */ /* 24 */
new HttpHeader("cache-control", string.Empty), new HttpHeader("Cache-Control", string.Empty),
/* 25 */ /* 25 */
new HttpHeader("content-disposition", string.Empty), new HttpHeader("Content-Disposition", string.Empty),
/* 26 */ /* 26 */
new HttpHeader("content-encoding", string.Empty), new HttpHeader("Content-Encoding", string.Empty),
/* 27 */ /* 27 */
new HttpHeader("content-language", string.Empty), new HttpHeader("Content-Language", string.Empty),
/* 28 */ /* 28 */
new HttpHeader("content-length", string.Empty), new HttpHeader("Content-Length", string.Empty),
/* 29 */ /* 29 */
new HttpHeader("content-location", string.Empty), new HttpHeader("Content-Location", string.Empty),
/* 30 */ /* 30 */
new HttpHeader("content-range", string.Empty), new HttpHeader("Content-Range", string.Empty),
/* 31 */ /* 31 */
new HttpHeader("content-type", string.Empty), new HttpHeader("Content-Type", string.Empty),
/* 32 */ /* 32 */
new HttpHeader("cookie", string.Empty), new HttpHeader("Cookie", string.Empty),
/* 33 */ /* 33 */
new HttpHeader("date", string.Empty), new HttpHeader("Date", string.Empty),
/* 34 */ /* 34 */
new HttpHeader("etag", string.Empty), new HttpHeader("ETag", string.Empty),
/* 35 */ /* 35 */
new HttpHeader("expect", string.Empty), new HttpHeader("Expect", string.Empty),
/* 36 */ /* 36 */
new HttpHeader("expires", string.Empty), new HttpHeader("Expires", string.Empty),
/* 37 */ /* 37 */
new HttpHeader("from", string.Empty), new HttpHeader("From", string.Empty),
/* 38 */ /* 38 */
new HttpHeader("host", string.Empty), new HttpHeader("Host", string.Empty),
/* 39 */ /* 39 */
new HttpHeader("if-match", string.Empty), new HttpHeader("If-Match", string.Empty),
/* 40 */ /* 40 */
new HttpHeader("if-modified-since", string.Empty), new HttpHeader("If-Modified-Since", string.Empty),
/* 41 */ /* 41 */
new HttpHeader("if-none-match", string.Empty), new HttpHeader("If-None-Match", string.Empty),
/* 42 */ /* 42 */
new HttpHeader("if-range", string.Empty), new HttpHeader("If-Range", string.Empty),
/* 43 */ /* 43 */
new HttpHeader("if-unmodified-since", string.Empty), new HttpHeader("If-Unmodified-Since", string.Empty),
/* 44 */ /* 44 */
new HttpHeader("last-modified", string.Empty), new HttpHeader("Last-Modified", string.Empty),
/* 45 */ /* 45 */
new HttpHeader("link", string.Empty), new HttpHeader("Link", string.Empty),
/* 46 */ /* 46 */
new HttpHeader("location", string.Empty), new HttpHeader("Location", string.Empty),
/* 47 */ /* 47 */
new HttpHeader("max-forwards", string.Empty), new HttpHeader("Max-Forwards", string.Empty),
/* 48 */ /* 48 */
new HttpHeader("proxy-authenticate", string.Empty), new HttpHeader("Proxy-Authenticate", string.Empty),
/* 49 */ /* 49 */
new HttpHeader("proxy-authorization", string.Empty), new HttpHeader("Proxy-Authorization", string.Empty),
/* 50 */ /* 50 */
new HttpHeader("range", string.Empty), new HttpHeader("Range", string.Empty),
/* 51 */ /* 51 */
new HttpHeader("referer", string.Empty), new HttpHeader("Referer", string.Empty),
/* 52 */ /* 52 */
new HttpHeader("refresh", string.Empty), new HttpHeader("Refresh", string.Empty),
/* 53 */ /* 53 */
new HttpHeader("retry-after", string.Empty), new HttpHeader("Retry-After", string.Empty),
/* 54 */ /* 54 */
new HttpHeader("server", string.Empty), new HttpHeader("Server", string.Empty),
/* 55 */ /* 55 */
new HttpHeader("set-cookie", string.Empty), new HttpHeader("Set-Cookie", string.Empty),
/* 56 */ /* 56 */
new HttpHeader("strict-transport-security", string.Empty), new HttpHeader("Strict-Transport-Security", string.Empty),
/* 57 */ /* 57 */
new HttpHeader("transfer-encoding", string.Empty), new HttpHeader("Transfer-Encoding", string.Empty),
/* 58 */ /* 58 */
new HttpHeader("user-agent", string.Empty), new HttpHeader("User-Agent", string.Empty),
/* 59 */ /* 59 */
new HttpHeader("vary", string.Empty), new HttpHeader("Vary", string.Empty),
/* 60 */ /* 60 */
new HttpHeader("via", string.Empty), new HttpHeader("Via", string.Empty),
/* 61 */ /* 61 */
new HttpHeader("www-authenticate", string.Empty) new HttpHeader("WWW-Authenticate", string.Empty)
}; };
private static readonly Dictionary<string, int> staticIndexByName = CreateMap(); private static readonly Dictionary<string, int> staticIndexByName = createMap();
/// <summary> /// <summary>
/// The number of header fields in the static table. /// The number of header fields in the static table.
...@@ -180,12 +180,12 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -180,12 +180,12 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <param name="name">Name.</param> /// <param name="name">Name.</param>
public static int GetIndex(string name) public static int GetIndex(string name)
{ {
if (!staticIndexByName.ContainsKey(name)) if (!staticIndexByName.TryGetValue(name, out int index))
{ {
return -1; return -1;
} }
return staticIndexByName[name]; return index;
} }
/// <summary> /// <summary>
...@@ -207,7 +207,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -207,7 +207,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
while (index <= Length) while (index <= Length)
{ {
var entry = Get(index); var entry = Get(index);
if (!HpackUtil.Equals(name, entry.Name)) if (!name.Equals(entry.Name, StringComparison.OrdinalIgnoreCase))
{ {
break; break;
} }
...@@ -227,7 +227,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -227,7 +227,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// create a map of header name to index value to allow quick lookup /// create a map of header name to index value to allow quick lookup
/// </summary> /// </summary>
/// <returns>The map.</returns> /// <returns>The map.</returns>
private static Dictionary<string, int> CreateMap() private static Dictionary<string, int> createMap()
{ {
int length = staticTable.Count; int length = staticTable.Count;
var ret = new Dictionary<string, int>(length); var ret = new Dictionary<string, int>(length);
...@@ -237,7 +237,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -237,7 +237,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
for (int index = length; index > 0; index--) for (int index = length; index > 0; index--)
{ {
var entry = Get(index); var entry = Get(index);
string name = entry.Name; string name = entry.Name.ToLower();
ret[name] = index; ret[name] = index;
} }
......
using System;
namespace Titanium.Web.Proxy.Http2
{
[Flags]
internal enum Http2FrameFlag : byte
{
Ack = 0x01,
EndStream = 0x01,
EndHeaders = 0x04,
Padded = 0x08,
Priority = 0x20,
}
}
\ No newline at end of file
namespace Titanium.Web.Proxy.Http2
{
internal class Http2FrameHeader
{
public int Length;
public Http2FrameType Type;
public Http2FrameFlag Flags;
public int StreamId;
public byte[] Buffer;
public byte[] CopyToBuffer()
{
int length = Length;
var buf = /*new byte[9];*/Buffer;
buf[0] = (byte)((length >> 16) & 0xff);
buf[1] = (byte)((length >> 8) & 0xff);
buf[2] = (byte)(length & 0xff);
buf[3] = (byte)Type;
buf[4] = (byte)Flags;
int streamId = StreamId;
//buf[5] = (byte)((streamId >> 24) & 0xff);
//buf[6] = (byte)((streamId >> 16) & 0xff);
//buf[7] = (byte)((streamId >> 8) & 0xff);
//buf[8] = (byte)(streamId & 0xff);
return buf;
}
}
}
namespace Titanium.Web.Proxy.Http2
{
internal enum Http2FrameType : byte
{
Data = 0x00,
Headers = 0x01,
Priority = 0x02,
RstStream = 0x03,
Settings = 0x04,
PushPromise = 0x05,
Ping = 0x06,
GoAway = 0x07,
WindowUpdate = 0x08,
Continuation = 0x09,
}
}
\ No newline at end of file
This diff is collapsed.
...@@ -31,7 +31,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -31,7 +31,7 @@ namespace Titanium.Web.Proxy.Models
/// Intercept tunnel connect request. /// Intercept tunnel connect request.
/// Valid only for explicit endpoints. /// Valid only for explicit endpoints.
/// 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
/// should'nt 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;
...@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.Models
} }
} }
internal async Task InvokeBeforeTunnectConnectResponse(ProxyServer proxyServer, internal async Task InvokeBeforeTunnelConnectResponse(ProxyServer proxyServer,
TunnelConnectSessionEventArgs connectArgs, ExceptionHandler exceptionFunc, bool isClientHello = false) TunnelConnectSessionEventArgs connectArgs, ExceptionHandler exceptionFunc, bool isClientHello = false)
{ {
if (BeforeTunnelConnectResponse != null) if (BeforeTunnelConnectResponse != null)
......
...@@ -70,7 +70,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -70,7 +70,7 @@ namespace Titanium.Web.Proxy.Models
public int Port { get; set; } public int Port { get; set; }
/// <summary> /// <summary>
/// Get cache key for Tcp connection cahe. /// Get cache key for Tcp connection cache.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
internal string GetCacheKey() internal string GetCacheKey()
......
...@@ -35,17 +35,24 @@ namespace Titanium.Web.Proxy.Models ...@@ -35,17 +35,24 @@ namespace Titanium.Web.Proxy.Models
{ {
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
{ {
throw new Exception("Name cannot be null"); throw new Exception("Name cannot be null or empty");
} }
Name = name.Trim(); Name = name.Trim();
Value = value.Trim(); Value = value.Trim();
} }
protected HttpHeader(string name, string value, bool headerEntry)
{
// special header entry created in inherited class with empty name
Name = name.Trim();
Value = value.Trim();
}
/// <summary> /// <summary>
/// Header Name. /// Header Name.
/// </summary> /// </summary>
public string Name { get; set; } public string Name { get; }
/// <summary> /// <summary>
/// Header Value. /// Header Value.
......
...@@ -143,8 +143,16 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -143,8 +143,16 @@ namespace Titanium.Web.Proxy.Network.Certificate
#if NET45 #if NET45
// Set private key onto certificate instance // Set private key onto certificate instance
var x509Certificate = new X509Certificate2(certificate.GetEncoded()); X509Certificate2 x509Certificate;
if (RunTime.IsRunningOnMono)
{
x509Certificate = withPrivateKey(certificate, rsaparams);
}
else
{
x509Certificate = new X509Certificate2(certificate.GetEncoded());
x509Certificate.PrivateKey = DotNetUtilities.ToRSA(rsaparams); x509Certificate.PrivateKey = DotNetUtilities.ToRSA(rsaparams);
}
#else #else
var x509Certificate = withPrivateKey(certificate, rsaparams); var x509Certificate = withPrivateKey(certificate, rsaparams);
#endif #endif
......
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
...@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary> /// <summary>
/// A list of pending certificate creation tasks. /// A list of pending certificate creation tasks.
/// Usefull to prevent multiple threads working on same certificate generation /// Useful to prevent multiple threads working on same certificate generation
/// when burst certificate generation requests happen for same certificate. /// when burst certificate generation requests happen for same certificate.
/// </summary> /// </summary>
private readonly ConcurrentDictionary<string, Task<X509Certificate2>> pendingCertificateCreationTasks private readonly ConcurrentDictionary<string, Task<X509Certificate2>> pendingCertificateCreationTasks
...@@ -149,7 +149,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -149,7 +149,7 @@ namespace Titanium.Web.Proxy.Network
set set
{ {
// For Mono (or Non-Windows) only Bouncy Castle is supported // For Mono (or Non-Windows) only Bouncy Castle is supported
if (!RunTime.IsWindows || RunTime.IsRunningOnMono) if (!RunTime.IsWindows)
{ {
value = CertificateEngine.BouncyCastle; value = CertificateEngine.BouncyCastle;
} }
...@@ -662,7 +662,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -662,7 +662,7 @@ namespace Titanium.Web.Proxy.Network
/// <returns>True if success.</returns> /// <returns>True if success.</returns>
public bool TrustRootCertificateAsAdmin(bool machineTrusted = false) public bool TrustRootCertificateAsAdmin(bool machineTrusted = false)
{ {
if (!RunTime.IsWindows || RunTime.IsRunningOnMono) if (!RunTime.IsWindows)
{ {
return false; return false;
} }
...@@ -805,7 +805,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -805,7 +805,7 @@ namespace Titanium.Web.Proxy.Network
/// <returns>Should also remove from machine store?</returns> /// <returns>Should also remove from machine store?</returns>
public bool RemoveTrustedRootCertificateAsAdmin(bool machineTrusted = false) public bool RemoveTrustedRootCertificateAsAdmin(bool machineTrusted = false)
{ {
if (!RunTime.IsWindows || RunTime.IsRunningOnMono) if (!RunTime.IsWindows)
{ {
return false; return false;
} }
......
#if DEBUG 
using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
#if DEBUG
using System; using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using StreamExtended;
using StreamExtended.Network;
namespace Titanium.Web.Proxy.Network namespace Titanium.Web.Proxy.Network
{ {
......
...@@ -59,6 +59,12 @@ namespace Titanium.Web.Proxy.Network ...@@ -59,6 +59,12 @@ namespace Titanium.Web.Proxy.Network
private X509Certificate2 loadCertificate(string path, string password, X509KeyStorageFlags storageFlags) private X509Certificate2 loadCertificate(string path, string password, X509KeyStorageFlags storageFlags)
{ {
byte[] exported; byte[] exported;
if (!File.Exists(path))
{
return null;
}
try try
{ {
exported = File.ReadAllBytes(path); exported = File.ReadAllBytes(path);
......
using StreamExtended.Network; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Network namespace Titanium.Web.Proxy.Network
{ {
......
...@@ -7,6 +7,8 @@ using System.Net.Security; ...@@ -7,6 +7,8 @@ using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Network.Tcp namespace Titanium.Web.Proxy.Network.Tcp
{ {
...@@ -34,11 +36,42 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -34,11 +36,42 @@ namespace Titanium.Web.Proxy.Network.Tcp
private readonly TcpClient tcpClient; private readonly TcpClient tcpClient;
private int? processId;
public Stream GetStream() public Stream GetStream()
{ {
return tcpClient.GetStream(); return tcpClient.GetStream();
} }
public int GetProcessId(ProxyEndPoint endPoint)
{
if (processId.HasValue)
{
return processId.Value;
}
if (RunTime.IsWindows)
{
var remoteEndPoint = (IPEndPoint)RemoteEndPoint;
// If client is localhost get the process id
if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
{
var ipVersion = endPoint.IpV6Enabled ? IpVersion.Ipv6 : IpVersion.Ipv4;
processId = TcpHelper.GetProcessIdByLocalPort(ipVersion, remoteEndPoint.Port);
}
else
{
// can't access process Id of remote request from remote machine
processId = -1;
}
return processId.Value;
}
throw new PlatformNotSupportedException();
}
/// <summary> /// <summary>
/// Dispose. /// Dispose.
/// </summary> /// </summary>
......
...@@ -8,12 +8,12 @@ using System.Net.Sockets; ...@@ -8,12 +8,12 @@ using System.Net.Sockets;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Network.Tcp namespace Titanium.Web.Proxy.Network.Tcp
{ {
...@@ -38,11 +38,11 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -38,11 +38,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
internal TcpConnectionFactory(ProxyServer server) internal TcpConnectionFactory(ProxyServer server)
{ {
this.server = server; this.Server = server;
Task.Run(async () => await clearOutdatedConnections()); Task.Run(async () => await clearOutdatedConnections());
} }
internal ProxyServer server { get; set; } internal ProxyServer Server { get; }
internal string GetConnectionCacheKey(string remoteHostName, int remotePort, internal string GetConnectionCacheKey(string remoteHostName, int remotePort,
bool isHttps, List<SslApplicationProtocol> applicationProtocols, bool isHttps, List<SslApplicationProtocol> applicationProtocols,
...@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
{ {
//http version is ignored since its an application level decision b/w HTTP 1.0/1.1 //http version is ignored since its an application level decision b/w HTTP 1.0/1.1
//also when doing connect request MS Edge browser sends http 1.0 but uses 1.1 after server sends 1.1 its response. //also when doing connect request MS Edge browser sends http 1.0 but uses 1.1 after server sends 1.1 its response.
//That can create cache miss for same server connection unneccessarily expecially when prefetcing with Connect. //That can create cache miss for same server connection unnecessarily especially when prefetching with Connect.
//http version 2 is separated using applicationProtocols below. //http version 2 is separated using applicationProtocols below.
var cacheKeyBuilder = new StringBuilder($"{remoteHostName}-{remotePort}-" + var cacheKeyBuilder = new StringBuilder($"{remoteHostName}-{remotePort}-" +
//when creating Tcp client isConnect won't matter //when creating Tcp client isConnect won't matter
...@@ -232,7 +232,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -232,7 +232,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
//deny connection to proxy end points to avoid infinite connection loop. //deny connection to proxy end points to avoid infinite connection loop.
if (server.ProxyEndPoints.Any(x => x.Port == remotePort) if (Server.ProxyEndPoints.Any(x => x.Port == remotePort)
&& NetworkHelper.IsLocalIpAddress(remoteHostName)) && NetworkHelper.IsLocalIpAddress(remoteHostName))
{ {
throw new Exception($"A client is making HTTP request to one of the listening ports of this proxy {remoteHostName}:{remotePort}"); throw new Exception($"A client is making HTTP request to one of the listening ports of this proxy {remoteHostName}:{remotePort}");
...@@ -240,7 +240,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -240,7 +240,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
if (externalProxy != null) if (externalProxy != null)
{ {
if (server.ProxyEndPoints.Any(x => x.Port == externalProxy.Port) if (Server.ProxyEndPoints.Any(x => x.Port == externalProxy.Port)
&& NetworkHelper.IsLocalIpAddress(externalProxy.HostName)) && NetworkHelper.IsLocalIpAddress(externalProxy.HostName))
{ {
throw new Exception($"A client is making HTTP request via external proxy to one of the listening ports of this proxy {remoteHostName}:{remotePort}"); throw new Exception($"A client is making HTTP request via external proxy to one of the listening ports of this proxy {remoteHostName}:{remotePort}");
...@@ -274,13 +274,11 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -274,13 +274,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
NoDelay = proxyServer.NoDelay, NoDelay = proxyServer.NoDelay,
ReceiveTimeout = proxyServer.ConnectionTimeOutSeconds * 1000, ReceiveTimeout = proxyServer.ConnectionTimeOutSeconds * 1000,
SendTimeout = proxyServer.ConnectionTimeOutSeconds * 1000, SendTimeout = proxyServer.ConnectionTimeOutSeconds * 1000,
SendBufferSize = proxyServer.BufferSize,
ReceiveBufferSize = proxyServer.BufferSize,
LingerState = new LingerOption(true, proxyServer.TcpTimeWaitSeconds) LingerState = new LingerOption(true, proxyServer.TcpTimeWaitSeconds)
}; };
//linux has a bug with socket reuse in .net core. //linux has a bug with socket reuse in .net core.
if (proxyServer.ReuseSocket && (RunTime.IsWindows || RunTime.IsRunningOnMono)) if (proxyServer.ReuseSocket && RunTime.IsWindows)
{ {
tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
} }
...@@ -418,7 +416,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -418,7 +416,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
return; return;
} }
if (close || connection.IsWinAuthenticated || !server.EnableConnectionPool) if (close || connection.IsWinAuthenticated || !Server.EnableConnectionPool || connection.IsClosed)
{ {
disposalBag.Add(connection); disposalBag.Add(connection);
return; return;
...@@ -434,7 +432,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -434,7 +432,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
{ {
if (cache.TryGetValue(connection.CacheKey, out var existingConnections)) if (cache.TryGetValue(connection.CacheKey, out var existingConnections))
{ {
while (existingConnections.Count >= server.MaxCachedConnections) while (existingConnections.Count >= Server.MaxCachedConnections)
{ {
if (existingConnections.TryDequeue(out var staleConnection)) if (existingConnections.TryDequeue(out var staleConnection))
{ {
...@@ -491,19 +489,20 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -491,19 +489,20 @@ namespace Titanium.Web.Proxy.Network.Tcp
{ {
if (queue.TryDequeue(out var connection)) if (queue.TryDequeue(out var connection))
{ {
var cutOff = DateTime.Now.AddSeconds(-1 * server.ConnectionTimeOutSeconds); var cutOff = DateTime.Now.AddSeconds(-1 * Server.ConnectionTimeOutSeconds);
if (!server.EnableConnectionPool if (!Server.EnableConnectionPool
|| connection.LastAccess < cutOff) || connection.LastAccess < cutOff)
{ {
disposalBag.Add(connection); disposalBag.Add(connection);
continue;
} }
else
{
queue.Enqueue(connection); queue.Enqueue(connection);
break; break;
} }
} }
} }
}
try try
{ {
...@@ -531,7 +530,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -531,7 +530,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
} }
catch (Exception e) catch (Exception e)
{ {
server.ExceptionFunc(new Exception("An error occurred when disposing server connections.", e)); Server.ExceptionFunc(new Exception("An error occurred when disposing server connections.", e));
} }
finally finally
{ {
......
...@@ -5,10 +5,10 @@ using System.Net.Security; ...@@ -5,10 +5,10 @@ using System.Net.Security;
#endif #endif
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Network.Tcp namespace Titanium.Web.Proxy.Network.Tcp
{ {
...@@ -27,6 +27,8 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -27,6 +27,8 @@ namespace Titanium.Web.Proxy.Network.Tcp
private ProxyServer proxyServer { get; } private ProxyServer proxyServer { get; }
internal bool IsClosed => Stream.IsClosed;
internal ExternalProxy UpStreamProxy { get; set; } internal ExternalProxy UpStreamProxy { get; set; }
internal string HostName { get; set; } internal string HostName { get; set; }
......
// //
// Mono.Security.BitConverterLE.cs // Mono.Security.BitConverterLE.cs
// Like System.BitConverter but always little endian // Like System.BitConverter but always little endian
// //
......
...@@ -11,7 +11,7 @@ using System.Runtime.InteropServices; ...@@ -11,7 +11,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Titanium.Web.Proxy")] [assembly: AssemblyProduct("Titanium.Web.Proxy")]
[assembly: AssemblyCopyright("Copyright Titanium 2015-2017")] [assembly: AssemblyCopyright("Copyright Titanium 2015-2019")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: InternalsVisibleTo("Titanium.Web.Proxy.UnitTests, PublicKey=" + [assembly: InternalsVisibleTo("Titanium.Web.Proxy.UnitTests, PublicKey=" +
......
...@@ -7,8 +7,6 @@ using System.Security.Authentication; ...@@ -7,8 +7,6 @@ using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended;
using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
...@@ -16,6 +14,8 @@ using Titanium.Web.Proxy.Helpers.WinHttp; ...@@ -16,6 +14,8 @@ using Titanium.Web.Proxy.Helpers.WinHttp;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network; using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
...@@ -57,6 +57,7 @@ namespace Titanium.Web.Proxy ...@@ -57,6 +57,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
private WinHttpWebProxyFinder systemProxyResolver; private WinHttpWebProxyFinder systemProxyResolver;
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>
/// Initializes a new instance of ProxyServer class with provided parameters. /// Initializes a new instance of ProxyServer class with provided parameters.
...@@ -102,7 +103,7 @@ namespace Titanium.Web.Proxy ...@@ -102,7 +103,7 @@ namespace Titanium.Web.Proxy
ProxyEndPoints = new List<ProxyEndPoint>(); ProxyEndPoints = new List<ProxyEndPoint>();
tcpConnectionFactory = new TcpConnectionFactory(this); tcpConnectionFactory = new TcpConnectionFactory(this);
if (!RunTime.IsRunningOnMono && RunTime.IsWindows && !RunTime.IsUwpOnWindows) if (RunTime.IsWindows && !RunTime.IsUwpOnWindows)
{ {
systemProxySettingsManager = new SystemProxyManager(); systemProxySettingsManager = new SystemProxyManager();
} }
...@@ -145,7 +146,15 @@ namespace Titanium.Web.Proxy ...@@ -145,7 +146,15 @@ namespace Titanium.Web.Proxy
public bool EnableWinAuth { get; set; } public bool EnableWinAuth { get; set; }
/// <summary> /// <summary>
/// Should we check for certificare revocation during SSL authentication to servers /// Enable disable HTTP/2 support.
/// Warning: HTTP/2 support is very limited
/// - only enabled when both client and server supports it (no protocol changing in proxy)
/// - cannot modify the request/response (e.g header modifications in BeforeRequest/Response events are ignored)
/// </summary>
public bool EnableHttp2 { get; set; } = false;
/// <summary>
/// Should we check for certificate revocation during SSL authentication to servers
/// Note: If enabled can reduce performance. Defaults to false. /// Note: If enabled can reduce performance. Defaults to false.
/// </summary> /// </summary>
public X509RevocationMode CheckCertificateRevocation { get; set; } public X509RevocationMode CheckCertificateRevocation { get; set; }
...@@ -168,7 +177,7 @@ namespace Titanium.Web.Proxy ...@@ -168,7 +177,7 @@ namespace Titanium.Web.Proxy
/// When enabled, as soon as we receive a client connection we concurrently initiate /// When enabled, as soon as we receive a client connection we concurrently initiate
/// corresponding server connection process using CONNECT hostname or SNI hostname on a separate task so that after parsing client request /// corresponding server connection process using CONNECT hostname or SNI hostname on a separate task so that after parsing client request
/// we will have the server connection immediately ready or in the process of getting ready. /// we will have the server connection immediately ready or in the process of getting ready.
/// If a server connection is available in cache then this prefetch task will immediatly return with the available connection from cache. /// If a server connection is available in cache then this prefetch task will immediately return with the available connection from cache.
/// Defaults to true. /// Defaults to true.
/// </summary> /// </summary>
public bool EnableTcpServerConnectionPrefetch { get; set; } = true; public bool EnableTcpServerConnectionPrefetch { get; set; } = true;
...@@ -352,6 +361,11 @@ namespace Titanium.Web.Proxy ...@@ -352,6 +361,11 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public event AsyncEventHandler<TcpClient> OnServerConnectionCreate; public event AsyncEventHandler<TcpClient> OnServerConnectionCreate;
/// <summary>
/// Customize the minimum ThreadPool size (increase it on a server)
/// </summary>
public int ThreadPoolWorkerThread { get; set; } = Environment.ProcessorCount;
/// <summary> /// <summary>
/// Add a proxy end point. /// Add a proxy end point.
/// </summary> /// </summary>
...@@ -374,7 +388,7 @@ namespace Titanium.Web.Proxy ...@@ -374,7 +388,7 @@ namespace Titanium.Web.Proxy
/// <summary> /// <summary>
/// Remove a proxy end point. /// Remove a proxy end point.
/// Will throw error if the end point does'nt exist. /// Will throw error if the end point doesn't exist.
/// </summary> /// </summary>
/// <param name="endPoint">The existing endpoint to remove.</param> /// <param name="endPoint">The existing endpoint to remove.</param>
public void RemoveEndPoint(ProxyEndPoint endPoint) public void RemoveEndPoint(ProxyEndPoint endPoint)
...@@ -417,9 +431,10 @@ namespace Titanium.Web.Proxy ...@@ -417,9 +431,10 @@ namespace Titanium.Web.Proxy
/// <param name="protocolType">The proxy protocol type.</param> /// <param name="protocolType">The proxy protocol type.</param>
public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType) public void SetAsSystemProxy(ExplicitProxyEndPoint endPoint, ProxyProtocolType protocolType)
{ {
if (RunTime.IsRunningOnMono) if (!RunTime.IsWindows)
{ {
throw new Exception("Mono Runtime do not support system proxy settings."); throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows.
Please manually confugure you operating system to use this proxy's port and address.");
} }
validateEndPointAsSystemProxy(endPoint); validateEndPointAsSystemProxy(endPoint);
...@@ -510,9 +525,10 @@ namespace Titanium.Web.Proxy ...@@ -510,9 +525,10 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public void DisableSystemProxy(ProxyProtocolType protocolType) public void DisableSystemProxy(ProxyProtocolType protocolType)
{ {
if (RunTime.IsRunningOnMono) if (!RunTime.IsWindows)
{ {
throw new Exception("Mono Runtime do not support system proxy settings."); throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows.
Please manually confugure you operating system to use this proxy's port and address.");
} }
systemProxySettingsManager.RemoveProxy(protocolType); systemProxySettingsManager.RemoveProxy(protocolType);
...@@ -523,9 +539,10 @@ namespace Titanium.Web.Proxy ...@@ -523,9 +539,10 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public void DisableAllSystemProxies() public void DisableAllSystemProxies()
{ {
if (RunTime.IsRunningOnMono) if (!RunTime.IsWindows)
{ {
throw new Exception("Mono Runtime do not support system proxy settings."); throw new NotSupportedException(@"Setting system proxy settings are only supported in Windows.
Please manually confugure you operating system to use this proxy's port and address.");
} }
systemProxySettingsManager.DisableAllProxy(); systemProxySettingsManager.DisableAllProxy();
...@@ -541,6 +558,8 @@ namespace Titanium.Web.Proxy ...@@ -541,6 +558,8 @@ namespace Titanium.Web.Proxy
throw new Exception("Proxy is already running."); throw new Exception("Proxy is already running.");
} }
setThreadPoolMinThread(ThreadPoolWorkerThread);
if (ProxyEndPoints.OfType<ExplicitProxyEndPoint>().Any(x => x.GenericCertificate == null)) if (ProxyEndPoints.OfType<ExplicitProxyEndPoint>().Any(x => x.GenericCertificate == null))
{ {
CertificateManager.EnsureRootCertificate(); CertificateManager.EnsureRootCertificate();
...@@ -599,7 +618,7 @@ namespace Titanium.Web.Proxy ...@@ -599,7 +618,7 @@ namespace Titanium.Web.Proxy
throw new Exception("Proxy is not running."); throw new Exception("Proxy is not running.");
} }
if (!RunTime.IsRunningOnMono && RunTime.IsWindows && !RunTime.IsUwpOnWindows) if (RunTime.IsWindows && !RunTime.IsUwpOnWindows)
{ {
bool setAsSystemProxy = ProxyEndPoints.OfType<ExplicitProxyEndPoint>() bool setAsSystemProxy = ProxyEndPoints.OfType<ExplicitProxyEndPoint>()
.Any(x => x.IsSystemHttpProxy || x.IsSystemHttpsProxy); .Any(x => x.IsSystemHttpProxy || x.IsSystemHttpsProxy);
...@@ -632,7 +651,7 @@ namespace Titanium.Web.Proxy ...@@ -632,7 +651,7 @@ namespace Titanium.Web.Proxy
endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port); endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port);
//linux/macOS has a bug with socket reuse in .net core. //linux/macOS has a bug with socket reuse in .net core.
if (ReuseSocket && (RunTime.IsWindows || RunTime.IsRunningOnMono)) if (ReuseSocket && RunTime.IsWindows)
{ {
endPoint.Listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); endPoint.Listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
} }
...@@ -718,13 +737,32 @@ namespace Titanium.Web.Proxy ...@@ -718,13 +737,32 @@ namespace Titanium.Web.Proxy
if (tcpClient != null) if (tcpClient != null)
{ {
Task.Run(async () => { await handleClient(tcpClient, endPoint); }); Task.Run(async () =>
{
await handleClient(tcpClient, endPoint);
});
} }
// Get the listener that handles the client request. // Get the listener that handles the client request.
endPoint.Listener.BeginAcceptTcpClient(onAcceptConnection, endPoint); endPoint.Listener.BeginAcceptTcpClient(onAcceptConnection, endPoint);
} }
/// <summary>
/// Change the ThreadPool.WorkerThread minThread
/// </summary>
/// <param name="workerThreads">minimum Threads allocated in the ThreadPool</param>
private void setThreadPoolMinThread(int workerThreads)
{
ThreadPool.GetMinThreads(out int minWorkerThreads, out int minCompletionPortThreads);
ThreadPool.GetMaxThreads(out int maxWorkerThreads, out _);
minWorkerThreads = Math.Min(maxWorkerThreads, Math.Max(workerThreads, Environment.ProcessorCount));
ThreadPool.SetMinThreads(minWorkerThreads, minCompletionPortThreads);
}
/// <summary> /// <summary>
/// Handle the client. /// Handle the client.
/// </summary> /// </summary>
...@@ -735,8 +773,7 @@ namespace Titanium.Web.Proxy ...@@ -735,8 +773,7 @@ namespace Titanium.Web.Proxy
{ {
tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000; tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000;
tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000; tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000;
tcpClient.SendBufferSize = BufferSize;
tcpClient.ReceiveBufferSize = BufferSize;
tcpClient.LingerState = new LingerOption(true, TcpTimeWaitSeconds); tcpClient.LingerState = new LingerOption(true, TcpTimeWaitSeconds);
await InvokeConnectionCreateEvent(tcpClient, true); await InvokeConnectionCreateEvent(tcpClient, true);
......
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets;
#if NETCOREAPP2_1 #if NETCOREAPP2_1
using System.Net.Security; using System.Net.Security;
#endif #endif
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions; using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
...@@ -18,6 +18,7 @@ using Titanium.Web.Proxy.Models; ...@@ -18,6 +18,7 @@ using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network; using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
...@@ -27,7 +28,7 @@ namespace Titanium.Web.Proxy ...@@ -27,7 +28,7 @@ namespace Titanium.Web.Proxy
public partial class ProxyServer public partial class ProxyServer
{ {
private bool isWindowsAuthenticationEnabledAndSupported => private bool isWindowsAuthenticationEnabledAndSupported =>
EnableWinAuth && RunTime.IsWindows && !RunTime.IsRunningOnMono; EnableWinAuth && RunTime.IsWindows;
/// <summary> /// <summary>
/// This is the core request handler method for a particular connection from client. /// This is the core request handler method for a particular connection from client.
...@@ -43,7 +44,7 @@ namespace Titanium.Web.Proxy ...@@ -43,7 +44,7 @@ namespace Titanium.Web.Proxy
/// The https hostname as appeared in CONNECT request if this is a HTTPS request from /// The https hostname as appeared in CONNECT request if this is a HTTPS request from
/// explicit endpoint. /// explicit endpoint.
/// </param> /// </param>
/// <param name="connectRequest">The Connect request if this is a HTTPS request from explicit endpoint.</param> /// <param name="connectArgs">The Connect request if this is a HTTPS request from explicit endpoint.</param>
/// <param name="prefetchConnectionTask">Prefetched server connection for current client using Connect/SNI headers.</param> /// <param name="prefetchConnectionTask">Prefetched server connection for current client using Connect/SNI headers.</param>
private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientConnection clientConnection, private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientConnection clientConnection,
CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter, CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter,
...@@ -60,7 +61,7 @@ namespace Titanium.Web.Proxy ...@@ -60,7 +61,7 @@ namespace Titanium.Web.Proxy
{ {
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
// Loop through each subsequest request on this particular client connection // Loop through each subsequent request on this particular client connection
// (assuming HTTP connection is kept alive by client) // (assuming HTTP connection is kept alive by client)
while (true) while (true)
{ {
...@@ -187,9 +188,21 @@ namespace Titanium.Web.Proxy ...@@ -187,9 +188,21 @@ namespace Titanium.Web.Proxy
//If prefetch task is available. //If prefetch task is available.
if (connection == null && prefetchTask != null) if (connection == null && prefetchTask != null)
{
try
{ {
connection = await prefetchTask; connection = await prefetchTask;
}
catch (SocketException e)
{
if(e.SocketErrorCode != SocketError.HostNotFound)
{
throw;
}
}
prefetchTask = null; prefetchTask = null;
} }
// create a new connection if cache key changes. // create a new connection if cache key changes.
...@@ -299,6 +312,8 @@ namespace Titanium.Web.Proxy ...@@ -299,6 +312,8 @@ namespace Titanium.Web.Proxy
if (args.HttpClient.Request.UpgradeToWebSocket) if (args.HttpClient.Request.UpgradeToWebSocket)
{ {
args.HttpClient.ConnectRequest.TunnelType = TunnelType.Websocket;
// if upgrading to websocket then relay the request without reading the contents // if upgrading to websocket then relay the request without reading the contents
await handleWebSocketUpgrade(httpCmd, args, args.HttpClient.Request, await handleWebSocketUpgrade(httpCmd, args, args.HttpClient.Request,
args.HttpClient.Response, args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamWriter, args.HttpClient.Response, args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamWriter,
...@@ -360,7 +375,7 @@ namespace Titanium.Web.Proxy ...@@ -360,7 +375,7 @@ namespace Titanium.Web.Proxy
} }
/// <summary> /// <summary>
/// Prepare the request headers so that we can avoid encodings not parsable by this proxy /// Prepare the request headers so that we can avoid encodings not parseable by this proxy
/// </summary> /// </summary>
private void prepareRequestHeaders(HeaderCollection requestHeaders) private void prepareRequestHeaders(HeaderCollection requestHeaders)
{ {
......
...@@ -14,7 +14,7 @@ namespace Titanium.Web.Proxy ...@@ -14,7 +14,7 @@ namespace Titanium.Web.Proxy
public partial class ProxyServer public partial class ProxyServer
{ {
/// <summary> /// <summary>
/// Called asynchronously when a request was successfull and we received the response. /// Called asynchronously when a request was successful and we received the response.
/// </summary> /// </summary>
/// <param name="args">The session event arguments.</param> /// <param name="args">The session event arguments.</param>
/// <returns> The task.</returns> /// <returns> The task.</returns>
...@@ -92,7 +92,7 @@ namespace Titanium.Web.Proxy ...@@ -92,7 +92,7 @@ namespace Titanium.Web.Proxy
// clear current response // clear current response
await args.ClearResponse(cancellationToken); await args.ClearResponse(cancellationToken);
var httpCmd = Request.CreateRequestLine(args.HttpClient.Request.Method, var httpCmd = Request.CreateRequestLine(args.HttpClient.Request.Method,
args.HttpClient.Request.OriginalUrl, args.HttpClient.Request.HttpVersion); args.HttpClient.Request.RequestUriString, args.HttpClient.Request.HttpVersion);
await handleHttpSessionRequest(httpCmd, args, null, args.ClientConnection.NegotiatedApplicationProtocol, await handleHttpSessionRequest(httpCmd, args, null, args.ClientConnection.NegotiatedApplicationProtocol,
cancellationToken, args.CancellationTokenSource); cancellationToken, args.CancellationTokenSource);
return; return;
...@@ -125,7 +125,6 @@ namespace Titanium.Web.Proxy ...@@ -125,7 +125,6 @@ namespace Titanium.Web.Proxy
} }
args.TimeLine["Response Sent"] = DateTime.Now; args.TimeLine["Response Sent"] = DateTime.Now;
} }
/// <summary> /// <summary>
......
using System.Collections.Concurrent;
namespace Titanium.Web.Proxy.StreamExtended.BufferPool
{
/// <summary>
/// A concrete IBufferPool implementation using a thread-safe stack.
/// Works well when all consumers ask for buffers with the same size.
/// If your application would use variable size buffers consider implementing IBufferPool using System.Buffers library from Microsoft.
/// </summary>
public class DefaultBufferPool : IBufferPool
{
private readonly ConcurrentStack<byte[]> buffers = new ConcurrentStack<byte[]>();
/// <summary>
/// Gets a buffer.
/// </summary>
/// <param name="bufferSize">Size of the buffer.</param>
/// <returns></returns>
public byte[] GetBuffer(int bufferSize)
{
if (!buffers.TryPop(out var buffer) || buffer.Length != bufferSize)
{
buffer = new byte[bufferSize];
}
return buffer;
}
/// <summary>
/// Returns the buffer.
/// </summary>
/// <param name="buffer">The buffer.</param>
public void ReturnBuffer(byte[] buffer)
{
if (buffer != null)
{
buffers.Push(buffer);
}
}
public void Dispose()
{
buffers.Clear();
}
}
}
using System;
namespace Titanium.Web.Proxy.StreamExtended.BufferPool
{
/// <summary>
/// Use this interface to implement custom buffer pool.
/// To use the default buffer pool implementation use DefaultBufferPool class.
/// </summary>
public interface IBufferPool : IDisposable
{
byte[] GetBuffer(int bufferSize);
void ReturnBuffer(byte[] buffer);
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
using System.Threading;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
/// <summary>
/// A concrete implementation of this interface is required when calling CopyStream.
/// </summary>
public interface ICustomStreamWriter
{
void Write(byte[] buffer, int i, int bufferLength);
Task WriteAsync(byte[] buffer, int i, int bufferLength, CancellationToken cancellationToken);
}
}
\ No newline at end of file
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