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:
- [ ] 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.
- [ ] 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
### Note: This Project is no longer maintained. Any pull requests for fixes are welcome.
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)
......@@ -36,7 +38,7 @@ Supports
#### Windows
* 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
* Visual Studio Code as IDE for .NET core
......
......@@ -136,7 +136,7 @@
</span>
<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>
<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 class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
......
......@@ -103,13 +103,13 @@ or when server terminates connection from proxy.</p>
<div class="inheritedMembers">
<h5>Inherited Members</h5>
<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>
<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>
<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>
<a class="xref" href="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TimeLine">SessionEventArgsBase.TimeLine</a>
......@@ -188,7 +188,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs__ctor_Titanium_Web_Proxy_ProxyServer_Titanium_Web_Proxy_Models_ProxyEndPoint_Titanium_Web_Proxy_Http_Request_System_Threading_CancellationTokenSource_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.%23ctor(Titanium.Web.Proxy.ProxyServer%2CTitanium.Web.Proxy.Models.ProxyEndPoint%2CTitanium.Web.Proxy.Http.Request%2CSystem.Threading.CancellationTokenSource)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L40">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L45">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs__ctor_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.#ctor*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs__ctor_Titanium_Web_Proxy_ProxyServer_Titanium_Web_Proxy_Models_ProxyEndPoint_Titanium_Web_Proxy_Http_Request_System_Threading_CancellationTokenSource_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.#ctor(Titanium.Web.Proxy.ProxyServer,Titanium.Web.Proxy.Models.ProxyEndPoint,Titanium.Web.Proxy.Http.Request,System.Threading.CancellationTokenSource)">SessionEventArgs(ProxyServer, ProxyEndPoint, Request, CancellationTokenSource)</h4>
......@@ -232,12 +232,43 @@ or when server terminates connection from proxy.</p>
</table>
<h3 id="properties">Properties
</h3>
<span class="small pull-right mobile-hide">
<span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_IsPromise.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.IsPromise%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L34">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_IsPromise_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.IsPromise*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_IsPromise" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.IsPromise">IsPromise</h4>
<div class="markdown level1 summary"><p>Is this session a HTTP/2 promise?</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public bool IsPromise { get; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.boolean">Boolean</a></td>
<td></td>
</tr>
</tbody>
</table>
<span class="small pull-right mobile-hide">
<span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_ReRequest.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.ReRequest%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L51">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L56">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_ReRequest_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.ReRequest*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_ReRequest" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.ReRequest">ReRequest</h4>
......@@ -270,7 +301,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Dispose.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Dispose%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L616">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L665">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Dispose_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Dispose*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Dispose" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Dispose">Dispose()</h4>
......@@ -288,7 +319,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_Byte___System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.Byte%5B%5D%2CSystem.Net.HttpStatusCode%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L536">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L585">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_Byte___System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.Byte[],System.Net.HttpStatusCode,System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">GenericResponse(Byte[], HttpStatusCode, Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4>
......@@ -341,7 +372,7 @@ the specified status to client. And then ignore the request.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_String_System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.String%2CSystem.Net.HttpStatusCode%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L517">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L566">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GenericResponse_System_String_System_Net_HttpStatusCode_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GenericResponse(System.String,System.Net.HttpStatusCode,System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">GenericResponse(String, HttpStatusCode, Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4>
......@@ -395,7 +426,7 @@ And then ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBody_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBody(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L352">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L401">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBody*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBody_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBody(System.Threading.CancellationToken)">GetRequestBody(CancellationToken)</h4>
......@@ -445,7 +476,7 @@ And then ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBodyAsString_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBodyAsString(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L367">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L416">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBodyAsString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBodyAsString*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetRequestBodyAsString_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetRequestBodyAsString(System.Threading.CancellationToken)">GetRequestBodyAsString(CancellationToken)</h4>
......@@ -495,7 +526,7 @@ And then ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBody_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBody(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L412">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L461">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBody*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBody_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBody(System.Threading.CancellationToken)">GetResponseBody(CancellationToken)</h4>
......@@ -545,7 +576,7 @@ And then ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBodyAsString_System_Threading_CancellationToken_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBodyAsString(System.Threading.CancellationToken)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L427">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L476">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBodyAsString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBodyAsString*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_GetResponseBodyAsString_System_Threading_CancellationToken_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBodyAsString(System.Threading.CancellationToken)">GetResponseBodyAsString(CancellationToken)</h4>
......@@ -595,7 +626,7 @@ And then ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_Byte___System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.Byte%5B%5D%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L497">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L546">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_Byte___System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.Byte[],System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">Ok(Byte[], Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4>
......@@ -642,7 +673,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_String_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.String%2CSystem.Collections.Generic.Dictionary%7BSystem.String%2CTitanium.Web.Proxy.Models.HttpHeader%7D%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L475">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L524">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Ok_System_String_System_Collections_Generic_Dictionary_System_String_Titanium_Web_Proxy_Models_HttpHeader__System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Ok(System.String,System.Collections.Generic.Dictionary{System.String,Titanium.Web.Proxy.Models.HttpHeader},System.Boolean)">Ok(String, Dictionary&lt;String, HttpHeader&gt;, Boolean)</h4>
......@@ -689,7 +720,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Redirect_System_String_System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Redirect(System.String%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L552">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L601">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Redirect_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Redirect*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Redirect_System_String_System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Redirect(System.String,System.Boolean)">Redirect(String, Boolean)</h4>
......@@ -729,7 +760,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_Respond_Titanium_Web_Proxy_Http_Response_System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.Respond(Titanium.Web.Proxy.Http.Response%2CSystem.Boolean)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L567">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L616">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Respond_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Respond*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_Respond_Titanium_Web_Proxy_Http_Response_System_Boolean_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.Respond(Titanium.Web.Proxy.Http.Response,System.Boolean)">Respond(Response, Boolean)</h4>
......@@ -769,7 +800,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBody_System_Byte___.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBody(System.Byte%5B%5D)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L381">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L430">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBody*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBody_System_Byte___" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBody(System.Byte[])">SetRequestBody(Byte[])</h4>
......@@ -803,7 +834,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBodyString_System_String_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBodyString(System.String)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L396">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L445">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBodyString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBodyString*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetRequestBodyString_System_String_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetRequestBodyString(System.String)">SetRequestBodyString(String)</h4>
......@@ -837,7 +868,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBody_System_Byte___.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBody(System.Byte%5B%5D)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L441">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L490">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBody_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBody*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBody_System_Byte___" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBody(System.Byte[])">SetResponseBody(Byte[])</h4>
......@@ -871,7 +902,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBodyString_System_String_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBodyString(System.String)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L456">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L505">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBodyString_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBodyString*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_SetResponseBodyString_System_String_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.SetResponseBodyString(System.String)">SetResponseBodyString(String)</h4>
......@@ -905,7 +936,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_TerminateServerConnection.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.TerminateServerConnection%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L608">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L657">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_TerminateServerConnection_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.TerminateServerConnection*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_TerminateServerConnection" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.TerminateServerConnection">TerminateServerConnection()</h4>
......@@ -923,7 +954,7 @@ and ignore the request. </p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgs_MultipartRequestPartSent.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgs.MultipartRequestPartSent%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L68">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs/#L73">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgs_MultipartRequestPartSent" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgs.MultipartRequestPartSent">MultipartRequestPartSent</h4>
<div class="markdown level1 summary"><p>Occurs when multipart request part sent.</p>
......
......@@ -187,17 +187,17 @@ or when server terminates connection from proxy.</p>
</h3>
<span class="small pull-right mobile-hide">
<span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferPool.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferPool%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferPool.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L28">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferPool" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferPool">bufferPool</h4>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferPool" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool">BufferPool</h4>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected readonly IBufferPool bufferPool</code></pre>
<pre><code class="lang-csharp hljs">protected readonly IBufferPool BufferPool</code></pre>
</div>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -209,24 +209,24 @@ or when server terminates connection from proxy.</p>
</thead>
<tbody>
<tr>
<td><span class="xref">StreamExtended.IBufferPool</span></td>
<td><span class="xref">IBufferPool</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_EventArguments_SessionEventArgsBase_bufferSize.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferSize%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferSize%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L27">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferSize" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferSize">bufferSize</h4>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferSize">BufferSize</h4>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected readonly int bufferSize</code></pre>
<pre><code class="lang-csharp hljs">protected readonly int BufferSize</code></pre>
</div>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -245,17 +245,17 @@ or when server terminates connection from proxy.</p>
</table>
<span class="small pull-right mobile-hide">
<span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_exceptionFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.exceptionFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ExceptionFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L29">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_exceptionFunc" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.exceptionFunc">exceptionFunc</h4>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ExceptionFunc" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc">ExceptionFunc</h4>
<div class="markdown level1 summary"></div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">protected readonly ExceptionHandler exceptionFunc</code></pre>
<pre><code class="lang-csharp hljs">protected readonly ExceptionHandler ExceptionFunc</code></pre>
</div>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -279,7 +279,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L102">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L84">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint">ClientEndPoint</h4>
......@@ -310,7 +310,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_CustomUpStreamProxyUsed.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.CustomUpStreamProxyUsed%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L115">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L97">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_CustomUpStreamProxyUsed_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.CustomUpStreamProxyUsed*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_CustomUpStreamProxyUsed" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.CustomUpStreamProxyUsed">CustomUpStreamProxyUsed</h4>
......@@ -341,7 +341,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Exception.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Exception%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L130">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L112">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Exception_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Exception*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Exception" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Exception">Exception</h4>
......@@ -372,7 +372,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_HttpClient.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.HttpClient%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L107">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L89">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_HttpClient_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.HttpClient*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_HttpClient" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.HttpClient">HttpClient</h4>
......@@ -403,7 +403,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsHttps.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsHttps%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L97">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L79">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsHttps_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsHttps*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsHttps" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsHttps">IsHttps</h4>
......@@ -434,7 +434,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsTransparent.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsTransparent%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L125">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L107">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsTransparent_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsTransparent*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_IsTransparent" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.IsTransparent">IsTransparent</h4>
......@@ -465,7 +465,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_LocalEndPoint.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.LocalEndPoint%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L120">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L102">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_LocalEndPoint_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.LocalEndPoint*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_LocalEndPoint" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.LocalEndPoint">LocalEndPoint</h4>
......@@ -505,7 +505,7 @@ or when server terminates connection from proxy.</p>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public Dictionary&lt;string, DateTime&gt; TimeLine { get; set; }</code></pre>
<pre><code class="lang-csharp hljs">public Dictionary&lt;string, DateTime&gt; TimeLine { get; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -527,7 +527,7 @@ or when server terminates connection from proxy.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L88">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L70">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_UserData" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.UserData">UserData</h4>
......@@ -559,7 +559,7 @@ same as the user data of HttpClient.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_WebSession.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.WebSession%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L109">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L91">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_WebSession_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.WebSession*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_WebSession" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.WebSession">WebSession</h4>
......@@ -592,7 +592,7 @@ public HttpWebClient WebSession { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Dispose.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Dispose%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L135">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L117">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Dispose_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Dispose*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_Dispose" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Dispose">Dispose()</h4>
......@@ -608,7 +608,7 @@ public HttpWebClient WebSession { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TerminateSession.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TerminateSession%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L183">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L165">View Source</a>
</span>
<a id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TerminateSession_" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TerminateSession*"></a>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_TerminateSession" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.TerminateSession">TerminateSession()</h4>
......@@ -626,7 +626,7 @@ public HttpWebClient WebSession { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataReceived.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataReceived%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L154">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L136">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataReceived" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataReceived">DataReceived</h4>
<div class="markdown level1 summary"><p>Fired when data is received within this session from client/server.</p>
......@@ -646,7 +646,7 @@ public HttpWebClient WebSession { get; }</code></pre>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.eventhandler-1">EventHandler</a>&lt;<span class="xref">StreamExtended.Network.DataEventArgs</span>&gt;</td>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.eventhandler-1">EventHandler</a>&lt;<span class="xref">DataEventArgs</span>&gt;</td>
<td></td>
</tr>
</tbody>
......@@ -656,7 +656,7 @@ public HttpWebClient WebSession { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataSent.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataSent%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L149">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/EventArguments/SessionEventArgsBase.cs/#L131">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_DataSent" data-uid="Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.DataSent">DataSent</h4>
<div class="markdown level1 summary"><p>Fired when data is sent within this session to server/client.</p>
......@@ -676,7 +676,7 @@ public HttpWebClient WebSession { get; }</code></pre>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.eventhandler-1">EventHandler</a>&lt;<span class="xref">StreamExtended.Network.DataEventArgs</span>&gt;</td>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.eventhandler-1">EventHandler</a>&lt;<span class="xref">DataEventArgs</span>&gt;</td>
<td></td>
</tr>
</tbody>
......
......@@ -100,13 +100,13 @@
<div class="inheritedMembers">
<h5>Inherited Members</h5>
<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>
<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>
<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>
<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>
</span>
<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>
<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 class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
......
......@@ -236,7 +236,7 @@
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.string">String</a></td>
<td><span class="parametername">message</span></td>
<td><p>Excception message</p>
<td><p>Exception message</p>
</td>
</tr>
<tr>
......
......@@ -107,6 +107,9 @@
<div>
<a class="xref" href="Titanium.Web.Proxy.Http.Request.html#Titanium_Web_Proxy_Http_Request_OriginalUrl">Request.OriginalUrl</a>
</div>
<div>
<a class="xref" href="Titanium.Web.Proxy.Http.Request.html#Titanium_Web_Proxy_Http_Request_RequestUriString">Request.RequestUriString</a>
</div>
<div>
<a class="xref" href="Titanium.Web.Proxy.Http.Request.html#Titanium_Web_Proxy_Http_Request_HasBody">Request.HasBody</a>
</div>
......@@ -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>
</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>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/ConnectRequest.cs/#L17">View Source</a>
</span>
<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>
......@@ -242,7 +245,37 @@
</thead>
<tbody>
<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>
</tr>
</tbody>
......
......@@ -201,7 +201,7 @@
</thead>
<tbody>
<tr>
<td><span class="xref">StreamExtended.ServerHelloInfo</span></td>
<td><span class="xref">ServerHelloInfo</span></td>
<td></td>
</tr>
</tbody>
......
......@@ -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>
<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
Returns null if does&apos;nt exist</p>
Returns null if doesn&apos;t exist</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
......
......@@ -135,7 +135,7 @@
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -193,7 +193,7 @@
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -280,7 +280,7 @@
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -396,7 +396,7 @@
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -425,7 +425,7 @@
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -512,7 +512,7 @@
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -570,7 +570,7 @@
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -773,7 +773,7 @@
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -831,7 +831,7 @@
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="fieldValue">Field Value</h5>
<table class="table table-bordered table-striped table-condensed">
......
......@@ -167,7 +167,7 @@ public class Request : RequestResponseBase</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_ExpectationFailed.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.ExpectationFailed%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/Request.cs/#L133">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L148">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_ExpectationFailed_" data-uid="Titanium.Web.Proxy.Http.Request.ExpectationFailed*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_ExpectationFailed" data-uid="Titanium.Web.Proxy.Http.Request.ExpectationFailed">ExpectationFailed</h4>
......@@ -198,7 +198,7 @@ public class Request : RequestResponseBase</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_ExpectationSucceeded.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.ExpectationSucceeded%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/Request.cs/#L128">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L143">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_ExpectationSucceeded_" data-uid="Titanium.Web.Proxy.Http.Request.ExpectationSucceeded*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_ExpectationSucceeded" data-uid="Titanium.Web.Proxy.Http.Request.ExpectationSucceeded">ExpectationSucceeded</h4>
......@@ -229,7 +229,7 @@ public class Request : RequestResponseBase</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_ExpectContinue.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.ExpectContinue%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/Request.cs/#L82">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L97">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_ExpectContinue_" data-uid="Titanium.Web.Proxy.Http.Request.ExpectContinue*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_ExpectContinue" data-uid="Titanium.Web.Proxy.Http.Request.ExpectContinue">ExpectContinue</h4>
......@@ -260,7 +260,7 @@ public class Request : RequestResponseBase</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_HasBody.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.HasBody%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/Request.cs/#L40">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L55">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_HasBody_" data-uid="Titanium.Web.Proxy.Http.Request.HasBody*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_HasBody" data-uid="Titanium.Web.Proxy.Http.Request.HasBody">HasBody</h4>
......@@ -293,7 +293,7 @@ public class Request : RequestResponseBase</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_HeaderText.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.HeaderText%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/Request.cs/#L138">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L153">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_HeaderText_" data-uid="Titanium.Web.Proxy.Http.Request.HeaderText*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_HeaderText" data-uid="Titanium.Web.Proxy.Http.Request.HeaderText">HeaderText</h4>
......@@ -326,7 +326,7 @@ public class Request : RequestResponseBase</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_Host.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.Host%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/Request.cs/#L73">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L88">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_Host_" data-uid="Titanium.Web.Proxy.Http.Request.Host*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_Host" data-uid="Titanium.Web.Proxy.Http.Request.Host">Host</h4>
......@@ -359,7 +359,7 @@ Users can set new RequestUri separately.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_IsHttps.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.IsHttps%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L30">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L32">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_IsHttps_" data-uid="Titanium.Web.Proxy.Http.Request.IsHttps*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_IsHttps" data-uid="Titanium.Web.Proxy.Http.Request.IsHttps">IsHttps</h4>
......@@ -390,7 +390,7 @@ Users can set new RequestUri separately.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_IsMultipartFormData.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.IsMultipartFormData%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/Request.cs/#L94">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L109">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_IsMultipartFormData_" data-uid="Titanium.Web.Proxy.Http.Request.IsMultipartFormData*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_IsMultipartFormData" data-uid="Titanium.Web.Proxy.Http.Request.IsMultipartFormData">IsMultipartFormData</h4>
......@@ -421,7 +421,7 @@ Users can set new RequestUri separately.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_Method.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.Method%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/Request.cs/#L20">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L22">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_Method_" data-uid="Titanium.Web.Proxy.Http.Request.Method*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_Method" data-uid="Titanium.Web.Proxy.Http.Request.Method">Method</h4>
......@@ -452,7 +452,7 @@ Users can set new RequestUri separately.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_OriginalUrl.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.OriginalUrl%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/Request.cs/#L35">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L37">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_OriginalUrl_" data-uid="Titanium.Web.Proxy.Http.Request.OriginalUrl*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_OriginalUrl" data-uid="Titanium.Web.Proxy.Http.Request.OriginalUrl">OriginalUrl</h4>
......@@ -461,7 +461,7 @@ Users can set new RequestUri separately.</p>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string OriginalUrl { get; set; }</code></pre>
<pre><code class="lang-csharp hljs">public string OriginalUrl { get; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -483,7 +483,7 @@ Users can set new RequestUri separately.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_RequestUri.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.RequestUri%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/Request.cs/#L25">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L27">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_RequestUri_" data-uid="Titanium.Web.Proxy.Http.Request.RequestUri*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_RequestUri" data-uid="Titanium.Web.Proxy.Http.Request.RequestUri">RequestUri</h4>
......@@ -509,12 +509,43 @@ Users can set new RequestUri separately.</p>
</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_Request_RequestUriString.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.RequestUriString%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/Request.cs/#L50">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_RequestUriString_" data-uid="Titanium.Web.Proxy.Http.Request.RequestUriString*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_RequestUriString" data-uid="Titanium.Web.Proxy.Http.Request.RequestUriString">RequestUriString</h4>
<div class="markdown level1 summary"><p>The request uri as it is in the HTTP header</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public string RequestUriString { get; set; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.string">String</a></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_Request_UpgradeToWebSocket.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.UpgradeToWebSocket%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/Request.cs/#L110">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L125">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_UpgradeToWebSocket_" data-uid="Titanium.Web.Proxy.Http.Request.UpgradeToWebSocket*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_UpgradeToWebSocket" data-uid="Titanium.Web.Proxy.Http.Request.UpgradeToWebSocket">UpgradeToWebSocket</h4>
......@@ -545,7 +576,7 @@ Users can set new RequestUri separately.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_Request_Url.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.Request.Url%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/Request.cs/#L99">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/Request.cs/#L114">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_Request_Url_" data-uid="Titanium.Web.Proxy.Http.Request.Url*"></a>
<h4 id="Titanium_Web_Proxy_Http_Request_Url" data-uid="Titanium.Web.Proxy.Http.Request.Url">Url</h4>
......
......@@ -127,7 +127,7 @@
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_Body.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.Body%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/RequestResponseBase.cs/#L155">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L171">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_Body_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.Body*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_Body" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.Body">Body</h4>
......@@ -159,7 +159,7 @@ public byte[] Body { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_BodyInternal.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.BodyInternal%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/RequestResponseBase.cs/#L21">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L22">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_BodyInternal_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.BodyInternal*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_BodyInternal" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.BodyInternal">BodyInternal</h4>
......@@ -190,7 +190,7 @@ public byte[] Body { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_BodyString.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.BodyString%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/RequestResponseBase.cs/#L183">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L199">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_BodyString_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.BodyString*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_BodyString" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.BodyString">BodyString</h4>
......@@ -223,7 +223,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_ContentEncoding.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.ContentEncoding%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/RequestResponseBase.cs/#L106">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L122">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_ContentEncoding_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.ContentEncoding*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_ContentEncoding" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.ContentEncoding">ContentEncoding</h4>
......@@ -254,7 +254,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_ContentLength.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.ContentLength%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/RequestResponseBase.cs/#L70">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L86">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_ContentLength_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.ContentLength*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_ContentLength" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.ContentLength">ContentLength</h4>
......@@ -285,7 +285,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_ContentType.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.ContentType%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/RequestResponseBase.cs/#L116">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L132">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_ContentType_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.ContentType*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_ContentType" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.ContentType">ContentType</h4>
......@@ -316,7 +316,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_Encoding.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.Encoding%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/RequestResponseBase.cs/#L111">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L127">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_Encoding_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.Encoding*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_Encoding" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.Encoding">Encoding</h4>
......@@ -347,7 +347,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_HasBody.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.HasBody%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/RequestResponseBase.cs/#L177">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L193">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_HasBody_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.HasBody*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_HasBody" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.HasBody">HasBody</h4>
......@@ -378,7 +378,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_Headers.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.Headers%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/RequestResponseBase.cs/#L65">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L81">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_Headers_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.Headers*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_Headers" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.Headers">Headers</h4>
......@@ -409,7 +409,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_HeaderText.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.HeaderText%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/RequestResponseBase.cs/#L150">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L166">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_HeaderText_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.HeaderText*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_HeaderText" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.HeaderText">HeaderText</h4>
......@@ -440,7 +440,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_HttpVersion.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.HttpVersion%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/RequestResponseBase.cs/#L60">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L76">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_HttpVersion_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.HttpVersion*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_HttpVersion" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.HttpVersion">HttpVersion</h4>
......@@ -471,7 +471,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_IsBodyRead.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.IsBodyRead%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/RequestResponseBase.cs/#L189">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L205">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_IsBodyRead_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.IsBodyRead*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_IsBodyRead" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.IsBodyRead">IsBodyRead</h4>
......@@ -502,7 +502,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_IsChunked.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.IsChunked%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/RequestResponseBase.cs/#L125">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L141">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_IsChunked_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.IsChunked*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_IsChunked" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.IsChunked">IsChunked</h4>
......@@ -533,7 +533,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_KeepBody.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.KeepBody%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/RequestResponseBase.cs/#L55">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L71">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_KeepBody_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.KeepBody*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_KeepBody" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.KeepBody">KeepBody</h4>
......@@ -566,7 +566,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase_ToString.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase.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 class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L292">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L310">View Source</a>
</span>
<a id="Titanium_Web_Proxy_Http_RequestResponseBase_ToString_" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.ToString*"></a>
<h4 id="Titanium_Web_Proxy_Http_RequestResponseBase_ToString" data-uid="Titanium.Web.Proxy.Http.RequestResponseBase.ToString">ToString()</h4>
......@@ -604,7 +604,7 @@ public string BodyString { get; }</code></pre>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_Http_RequestResponseBase.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.Http.RequestResponseBase%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A" class="contribution-link">Improve this Doc</a>
</li>
<li>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L16" class="contribution-link">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/Http/RequestResponseBase.cs/#L17" class="contribution-link">View Source</a>
</li>
</ul>
</div>
......
......@@ -194,19 +194,19 @@
</h3>
<span class="small pull-right mobile-hide">
<span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_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 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>
<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>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="parameters">Parameters</h5>
<table class="table table-bordered table-striped table-condensed">
......@@ -240,6 +240,18 @@
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.boolean">Boolean</a></td>
<td><span class="parametername">sensitive</span></td>
<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>
</tr>
</tbody>
......@@ -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>
</span>
<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>
<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>
......
......@@ -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.
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
should&apos;nt be decrypted and instead be relayed.</p>
shouldn&apos;t be decrypted and instead be relayed.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
......
......@@ -160,6 +160,48 @@
</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_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>
<span class="small pull-right mobile-hide">
......@@ -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>
</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/#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>
<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>
......@@ -210,7 +252,7 @@ The additional 32 octets account for an estimated overhead associated with an en
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<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>
<h5 class="propertyValue">Property Value</h5>
<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
<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 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>
<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>
......@@ -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>
</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/#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>
<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>
......@@ -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>
</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/#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>
<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>
......@@ -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>
</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/#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>
<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>
......
......@@ -133,7 +133,7 @@ However care should be taken to avoid using the same listening ports across mult
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer__ctor_System_Boolean_System_Boolean_System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.%23ctor(System.Boolean%2CSystem.Boolean%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/ProxyServer.cs/#L73">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L74">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer__ctor_" data-uid="Titanium.Web.Proxy.ProxyServer.#ctor*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer__ctor_System_Boolean_System_Boolean_System_Boolean_" data-uid="Titanium.Web.Proxy.ProxyServer.#ctor(System.Boolean,System.Boolean,System.Boolean)">ProxyServer(Boolean, Boolean, Boolean)</h4>
......@@ -181,7 +181,7 @@ prompting for UAC if required?</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer__ctor_System_String_System_String_System_Boolean_System_Boolean_System_Boolean_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.%23ctor(System.String%2CSystem.String%2CSystem.Boolean%2CSystem.Boolean%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/ProxyServer.cs/#L93">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L94">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer__ctor_" data-uid="Titanium.Web.Proxy.ProxyServer.#ctor*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer__ctor_System_String_System_String_System_Boolean_System_Boolean_System_Boolean_" data-uid="Titanium.Web.Proxy.ProxyServer.#ctor(System.String,System.String,System.Boolean,System.Boolean,System.Boolean)">ProxyServer(String, String, Boolean, Boolean, Boolean)</h4>
......@@ -243,7 +243,7 @@ prompting for UAC if required?</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_BufferPool.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.BufferPool%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L243">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L252">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_BufferPool_" data-uid="Titanium.Web.Proxy.ProxyServer.BufferPool*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_BufferPool" data-uid="Titanium.Web.Proxy.ProxyServer.BufferPool">BufferPool</h4>
......@@ -266,7 +266,7 @@ By default this uses DefaultBufferPool implementation available in StreamExtende
</thead>
<tbody>
<tr>
<td><span class="xref">StreamExtended.IBufferPool</span></td>
<td><span class="xref">IBufferPool</span></td>
<td></td>
</tr>
</tbody>
......@@ -276,7 +276,7 @@ By default this uses DefaultBufferPool implementation available in StreamExtende
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_BufferSize.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.BufferSize%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L186">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L195">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_BufferSize_" data-uid="Titanium.Web.Proxy.ProxyServer.BufferSize*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_BufferSize" data-uid="Titanium.Web.Proxy.ProxyServer.BufferSize">BufferSize</h4>
......@@ -308,7 +308,7 @@ Default value is 8192 bytes.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_CertificateManager.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.CertificateManager%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L248">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L257">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_CertificateManager_" data-uid="Titanium.Web.Proxy.ProxyServer.CertificateManager*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_CertificateManager" data-uid="Titanium.Web.Proxy.ProxyServer.CertificateManager">CertificateManager</h4>
......@@ -339,11 +339,11 @@ Default value is 8192 bytes.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_CheckCertificateRevocation.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.CheckCertificateRevocation%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L151">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L160">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_CheckCertificateRevocation_" data-uid="Titanium.Web.Proxy.ProxyServer.CheckCertificateRevocation*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_CheckCertificateRevocation" data-uid="Titanium.Web.Proxy.ProxyServer.CheckCertificateRevocation">CheckCertificateRevocation</h4>
<div class="markdown level1 summary"><p>Should we check for certificare revocation during SSL authentication to servers
<div class="markdown level1 summary"><p>Should we check for certificate revocation during SSL authentication to servers
Note: If enabled can reduce performance. Defaults to false.</p>
</div>
<div class="markdown level1 conceptual"></div>
......@@ -371,7 +371,7 @@ Note: If enabled can reduce performance. Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ClientConnectionCount.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ClientConnectionCount%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L217">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L226">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ClientConnectionCount_" data-uid="Titanium.Web.Proxy.ProxyServer.ClientConnectionCount*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ClientConnectionCount" data-uid="Titanium.Web.Proxy.ProxyServer.ClientConnectionCount">ClientConnectionCount</h4>
......@@ -402,7 +402,7 @@ Note: If enabled can reduce performance. Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ConnectionTimeOutSeconds.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ConnectionTimeOutSeconds%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L193">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L202">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ConnectionTimeOutSeconds_" data-uid="Titanium.Web.Proxy.ProxyServer.ConnectionTimeOutSeconds*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ConnectionTimeOutSeconds" data-uid="Titanium.Web.Proxy.ProxyServer.ConnectionTimeOutSeconds">ConnectionTimeOutSeconds</h4>
......@@ -435,7 +435,7 @@ Default value is 60 seconds.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Enable100ContinueBehaviour.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Enable100ContinueBehaviour%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L158">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L167">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_Enable100ContinueBehaviour_" data-uid="Titanium.Web.Proxy.ProxyServer.Enable100ContinueBehaviour*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_Enable100ContinueBehaviour" data-uid="Titanium.Web.Proxy.ProxyServer.Enable100ContinueBehaviour">Enable100ContinueBehaviour</h4>
......@@ -468,7 +468,7 @@ Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_EnableConnectionPool.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableConnectionPool%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L164">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L173">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_EnableConnectionPool_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableConnectionPool*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_EnableConnectionPool" data-uid="Titanium.Web.Proxy.ProxyServer.EnableConnectionPool">EnableConnectionPool</h4>
......@@ -495,12 +495,48 @@ Defaults to true.</p>
</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_ProxyServer_EnableHttp2.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableHttp2%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L154">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_EnableHttp2_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableHttp2*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_EnableHttp2" data-uid="Titanium.Web.Proxy.ProxyServer.EnableHttp2">EnableHttp2</h4>
<div class="markdown level1 summary"><p>Enable disable HTTP/2 support.
Warning: HTTP/2 support is very limited</p>
<ul>
<li>only enabled when both client and server supports it (no protocol changing in proxy)</li>
<li>cannot modify the request/response (e.g header modifications in BeforeRequest/Response events are ignored)</li>
</ul>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public bool EnableHttp2 { get; set; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.boolean">Boolean</a></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_ProxyServer_EnableTcpServerConnectionPrefetch.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableTcpServerConnectionPrefetch%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L174">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L183">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_EnableTcpServerConnectionPrefetch_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableTcpServerConnectionPrefetch*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_EnableTcpServerConnectionPrefetch" data-uid="Titanium.Web.Proxy.ProxyServer.EnableTcpServerConnectionPrefetch">EnableTcpServerConnectionPrefetch</h4>
......@@ -508,7 +544,7 @@ Defaults to true.</p>
When enabled, as soon as we receive a client connection we concurrently initiate
corresponding server connection process using CONNECT hostname or SNI hostname on a separate task so that after parsing client request
we will have the server connection immediately ready or in the process of getting ready.
If a server connection is available in cache then this prefetch task will 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.</p>
</div>
<div class="markdown level1 conceptual"></div>
......@@ -536,7 +572,7 @@ Defaults to true.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_EnableWinAuth.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.EnableWinAuth%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L145">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L146">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_EnableWinAuth_" data-uid="Titanium.Web.Proxy.ProxyServer.EnableWinAuth*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_EnableWinAuth" data-uid="Titanium.Web.Proxy.ProxyServer.EnableWinAuth">EnableWinAuth</h4>
......@@ -571,7 +607,7 @@ Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ExceptionFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ExceptionFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L280">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L289">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ExceptionFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.ExceptionFunc*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ExceptionFunc" data-uid="Titanium.Web.Proxy.ProxyServer.ExceptionFunc">ExceptionFunc</h4>
......@@ -602,7 +638,7 @@ Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ForwardToUpstreamGateway.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ForwardToUpstreamGateway%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L136">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L137">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ForwardToUpstreamGateway_" data-uid="Titanium.Web.Proxy.ProxyServer.ForwardToUpstreamGateway*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ForwardToUpstreamGateway" data-uid="Titanium.Web.Proxy.ProxyServer.ForwardToUpstreamGateway">ForwardToUpstreamGateway</h4>
......@@ -634,7 +670,7 @@ Defaults to false.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_GetCustomUpStreamProxyFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.GetCustomUpStreamProxyFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L275">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L284">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_GetCustomUpStreamProxyFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.GetCustomUpStreamProxyFunc*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_GetCustomUpStreamProxyFunc" data-uid="Titanium.Web.Proxy.ProxyServer.GetCustomUpStreamProxyFunc">GetCustomUpStreamProxyFunc</h4>
......@@ -666,7 +702,7 @@ User should return the ExternalProxy object with valid credentials.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_MaxCachedConnections.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.MaxCachedConnections%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L200">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L209">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_MaxCachedConnections_" data-uid="Titanium.Web.Proxy.ProxyServer.MaxCachedConnections*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_MaxCachedConnections" data-uid="Titanium.Web.Proxy.ProxyServer.MaxCachedConnections">MaxCachedConnections</h4>
......@@ -699,7 +735,7 @@ Default value is 2.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_NoDelay.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.NoDelay%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L180">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L189">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_NoDelay_" data-uid="Titanium.Web.Proxy.ProxyServer.NoDelay*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_NoDelay" data-uid="Titanium.Web.Proxy.ProxyServer.NoDelay">NoDelay</h4>
......@@ -731,7 +767,7 @@ Defaults to true, no nagle algorithm is used.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationRealm.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationRealm%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L227">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L236">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationRealm_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationRealm*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationRealm" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationRealm">ProxyAuthenticationRealm</h4>
......@@ -762,7 +798,7 @@ Defaults to true, no nagle algorithm is used.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationSchemes.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationSchemes%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L308">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L317">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationSchemes_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationSchemes*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxyAuthenticationSchemes" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyAuthenticationSchemes">ProxyAuthenticationSchemes</h4>
......@@ -794,7 +830,7 @@ Works in relation with ProxySchemeAuthenticateFunc.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyBasicAuthenticateFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyBasicAuthenticateFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L295">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L304">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxyBasicAuthenticateFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyBasicAuthenticateFunc*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxyBasicAuthenticateFunc" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyBasicAuthenticateFunc">ProxyBasicAuthenticateFunc</h4>
......@@ -827,7 +863,7 @@ Should return true for successful authentication.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyEndPoints.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyEndPoints%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L269">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L278">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxyEndPoints_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyEndPoints*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxyEndPoints" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyEndPoints">ProxyEndPoints</h4>
......@@ -858,7 +894,7 @@ Should return true for successful authentication.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxyRunning.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxyRunning%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L130">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L131">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxyRunning_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyRunning*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxyRunning" data-uid="Titanium.Web.Proxy.ProxyServer.ProxyRunning">ProxyRunning</h4>
......@@ -889,7 +925,7 @@ Should return true for successful authentication.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ProxySchemeAuthenticateFunc.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ProxySchemeAuthenticateFunc%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L302">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L311">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ProxySchemeAuthenticateFunc_" data-uid="Titanium.Web.Proxy.ProxyServer.ProxySchemeAuthenticateFunc*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ProxySchemeAuthenticateFunc" data-uid="Titanium.Web.Proxy.ProxyServer.ProxySchemeAuthenticateFunc">ProxySchemeAuthenticateFunc</h4>
......@@ -922,7 +958,7 @@ Should return success for successful authentication, continuation if the package
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ReuseSocket.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ReuseSocket%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L212">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L221">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ReuseSocket_" data-uid="Titanium.Web.Proxy.ProxyServer.ReuseSocket*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ReuseSocket" data-uid="Titanium.Web.Proxy.ProxyServer.ReuseSocket">ReuseSocket</h4>
......@@ -954,7 +990,7 @@ Default is true (disabled for linux/macOS due to bug in .Net core).</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ServerConnectionCount.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ServerConnectionCount%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L222">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L231">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ServerConnectionCount_" data-uid="Titanium.Web.Proxy.ProxyServer.ServerConnectionCount*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ServerConnectionCount" data-uid="Titanium.Web.Proxy.ProxyServer.ServerConnectionCount">ServerConnectionCount</h4>
......@@ -985,7 +1021,7 @@ Default is true (disabled for linux/macOS due to bug in .Net core).</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SupportedSslProtocols.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SupportedSslProtocols%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L232">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L241">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_SupportedSslProtocols_" data-uid="Titanium.Web.Proxy.ProxyServer.SupportedSslProtocols*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_SupportedSslProtocols" data-uid="Titanium.Web.Proxy.ProxyServer.SupportedSslProtocols">SupportedSslProtocols</h4>
......@@ -1016,7 +1052,7 @@ Default is true (disabled for linux/macOS due to bug in .Net core).</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_TcpTimeWaitSeconds.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.TcpTimeWaitSeconds%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L206">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L215">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_TcpTimeWaitSeconds_" data-uid="Titanium.Web.Proxy.ProxyServer.TcpTimeWaitSeconds*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_TcpTimeWaitSeconds" data-uid="Titanium.Web.Proxy.ProxyServer.TcpTimeWaitSeconds">TcpTimeWaitSeconds</h4>
......@@ -1043,12 +1079,43 @@ Default value is 30.</p>
</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_ProxyServer_ThreadPoolWorkerThread.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L367">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_ThreadPoolWorkerThread_" data-uid="Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_ThreadPoolWorkerThread" data-uid="Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread">ThreadPoolWorkerThread</h4>
<div class="markdown level1 summary"><p>Customize the minimum ThreadPool size (increase it on a server)</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
<div class="codewrapper">
<pre><code class="lang-csharp hljs">public int ThreadPoolWorkerThread { get; set; }</code></pre>
</div>
<h5 class="propertyValue">Property Value</h5>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a class="xref" href="https://docs.microsoft.com/dotnet/api/system.int32">Int32</a></td>
<td></td>
</tr>
</tbody>
</table>
<span class="small pull-right mobile-hide">
<span class="divider">|</span>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_UpStreamEndPoint.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.UpStreamEndPoint%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L264">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L273">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_UpStreamEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamEndPoint*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_UpStreamEndPoint" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamEndPoint">UpStreamEndPoint</h4>
......@@ -1080,7 +1147,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_UpStreamHttpProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.UpStreamHttpProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L253">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L262">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpProxy" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpProxy">UpStreamHttpProxy</h4>
......@@ -1111,7 +1178,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_UpStreamHttpsProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.UpStreamHttpsProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L258">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L267">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpsProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpsProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_UpStreamHttpsProxy" data-uid="Titanium.Web.Proxy.ProxyServer.UpStreamHttpsProxy">UpStreamHttpsProxy</h4>
......@@ -1144,7 +1211,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_AddEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.AddEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L359">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L373">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_AddEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.AddEndPoint*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_AddEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.AddEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)">AddEndPoint(ProxyEndPoint)</h4>
......@@ -1178,7 +1245,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableAllSystemProxies.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableAllSystemProxies%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L524">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L540">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_DisableAllSystemProxies_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableAllSystemProxies*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_DisableAllSystemProxies" data-uid="Titanium.Web.Proxy.ProxyServer.DisableAllSystemProxies">DisableAllSystemProxies()</h4>
......@@ -1194,7 +1261,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableSystemHttpProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableSystemHttpProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L495">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L510">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpProxy" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpProxy">DisableSystemHttpProxy()</h4>
......@@ -1210,7 +1277,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableSystemHttpsProxy.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableSystemHttpsProxy%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L503">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L518">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpsProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpsProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_DisableSystemHttpsProxy" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemHttpsProxy">DisableSystemHttpsProxy()</h4>
......@@ -1226,7 +1293,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_DisableSystemProxy_Titanium_Web_Proxy_Models_ProxyProtocolType_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.DisableSystemProxy(Titanium.Web.Proxy.Models.ProxyProtocolType)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L511">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L526">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_DisableSystemProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_DisableSystemProxy_Titanium_Web_Proxy_Models_ProxyProtocolType_" data-uid="Titanium.Web.Proxy.ProxyServer.DisableSystemProxy(Titanium.Web.Proxy.Models.ProxyProtocolType)">DisableSystemProxy(ProxyProtocolType)</h4>
......@@ -1259,7 +1326,7 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Dispose.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Dispose%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L851">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L888">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_Dispose_" data-uid="Titanium.Web.Proxy.ProxyServer.Dispose*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_Dispose" data-uid="Titanium.Web.Proxy.ProxyServer.Dispose">Dispose()</h4>
......@@ -1275,12 +1342,12 @@ Defaults via any IP addresses of this machine.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_RemoveEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.RemoveEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L380">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L394">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_RemoveEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.RemoveEndPoint*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_RemoveEndPoint_Titanium_Web_Proxy_Models_ProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.RemoveEndPoint(Titanium.Web.Proxy.Models.ProxyEndPoint)">RemoveEndPoint(ProxyEndPoint)</h4>
<div class="markdown level1 summary"><p>Remove a proxy end point.
Will throw error if the end point does&apos;nt exist.</p>
Will throw error if the end point doesn&apos;t exist.</p>
</div>
<div class="markdown level1 conceptual"></div>
<h5 class="decalaration">Declaration</h5>
......@@ -1310,7 +1377,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L399">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L413">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)">SetAsSystemHttpProxy(ExplicitProxyEndPoint)</h4>
......@@ -1344,7 +1411,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpsProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpsProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L408">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L422">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpsProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpsProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_SetAsSystemHttpsProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemHttpsProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint)">SetAsSystemHttpsProxy(ExplicitProxyEndPoint)</h4>
......@@ -1378,7 +1445,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_SetAsSystemProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_Titanium_Web_Proxy_Models_ProxyProtocolType_.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.SetAsSystemProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint%2CTitanium.Web.Proxy.Models.ProxyProtocolType)%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L418">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L432">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_SetAsSystemProxy_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemProxy*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_SetAsSystemProxy_Titanium_Web_Proxy_Models_ExplicitProxyEndPoint_Titanium_Web_Proxy_Models_ProxyProtocolType_" data-uid="Titanium.Web.Proxy.ProxyServer.SetAsSystemProxy(Titanium.Web.Proxy.Models.ExplicitProxyEndPoint,Titanium.Web.Proxy.Models.ProxyProtocolType)">SetAsSystemProxy(ExplicitProxyEndPoint, ProxyProtocolType)</h4>
......@@ -1418,7 +1485,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Start.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Start%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L537">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L554">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_Start_" data-uid="Titanium.Web.Proxy.ProxyServer.Start*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_Start" data-uid="Titanium.Web.Proxy.ProxyServer.Start">Start()</h4>
......@@ -1434,7 +1501,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_Stop.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.Stop%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L595">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L614">View Source</a>
</span>
<a id="Titanium_Web_Proxy_ProxyServer_Stop_" data-uid="Titanium.Web.Proxy.ProxyServer.Stop*"></a>
<h4 id="Titanium_Web_Proxy_ProxyServer_Stop" data-uid="Titanium.Web.Proxy.ProxyServer.Stop">Stop()</h4>
......@@ -1452,7 +1519,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_AfterResponse.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.AfterResponse%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L343">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L352">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_ProxyServer_AfterResponse" data-uid="Titanium.Web.Proxy.ProxyServer.AfterResponse">AfterResponse</h4>
<div class="markdown level1 summary"><p>Intercept after response event from server.</p>
......@@ -1482,7 +1549,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_BeforeRequest.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.BeforeRequest%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L333">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L342">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_ProxyServer_BeforeRequest" data-uid="Titanium.Web.Proxy.ProxyServer.BeforeRequest">BeforeRequest</h4>
<div class="markdown level1 summary"><p>Intercept request event to server.</p>
......@@ -1512,7 +1579,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_BeforeResponse.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.BeforeResponse%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L338">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L347">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_ProxyServer_BeforeResponse" data-uid="Titanium.Web.Proxy.ProxyServer.BeforeResponse">BeforeResponse</h4>
<div class="markdown level1 summary"><p>Intercept response event from server.</p>
......@@ -1542,7 +1609,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ClientCertificateSelectionCallback.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ClientCertificateSelectionCallback%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L328">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L337">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_ProxyServer_ClientCertificateSelectionCallback" data-uid="Titanium.Web.Proxy.ProxyServer.ClientCertificateSelectionCallback">ClientCertificateSelectionCallback</h4>
<div class="markdown level1 summary"><p>Event to override client certificate selection during mutual SSL authentication.</p>
......@@ -1572,7 +1639,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ClientConnectionCountChanged.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ClientConnectionCountChanged%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L313">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L322">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_ProxyServer_ClientConnectionCountChanged" data-uid="Titanium.Web.Proxy.ProxyServer.ClientConnectionCountChanged">ClientConnectionCountChanged</h4>
<div class="markdown level1 summary"><p>Event occurs when client connection count changed.</p>
......@@ -1602,7 +1669,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_OnClientConnectionCreate.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.OnClientConnectionCreate%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L348">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L357">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_ProxyServer_OnClientConnectionCreate" data-uid="Titanium.Web.Proxy.ProxyServer.OnClientConnectionCreate">OnClientConnectionCreate</h4>
<div class="markdown level1 summary"><p>Customize TcpClient used for client connection upon create.</p>
......@@ -1632,7 +1699,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_OnServerConnectionCreate.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.OnServerConnectionCreate%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L353">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L362">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_ProxyServer_OnServerConnectionCreate" data-uid="Titanium.Web.Proxy.ProxyServer.OnServerConnectionCreate">OnServerConnectionCreate</h4>
<div class="markdown level1 summary"><p>Customize TcpClient used for server connection upon create.</p>
......@@ -1662,7 +1729,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ServerCertificateValidationCallback.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ServerCertificateValidationCallback%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L323">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L332">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_ProxyServer_ServerCertificateValidationCallback" data-uid="Titanium.Web.Proxy.ProxyServer.ServerCertificateValidationCallback">ServerCertificateValidationCallback</h4>
<div class="markdown level1 summary"><p>Event to override the default verification logic of remote SSL certificate received during authentication.</p>
......@@ -1692,7 +1759,7 @@ Will throw error if the end point does&apos;nt exist.</p>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/new/master/apiSpec/new?filename=Titanium_Web_Proxy_ProxyServer_ServerConnectionCountChanged.md&amp;value=---%0Auid%3A%20Titanium.Web.Proxy.ProxyServer.ServerConnectionCountChanged%0Asummary%3A%20'*You%20can%20override%20summary%20for%20the%20API%20here%20using%20*MARKDOWN*%20syntax'%0A---%0A%0A*Please%20type%20below%20more%20information%20about%20this%20API%3A*%0A%0A">Improve this Doc</a>
</span>
<span class="small pull-right mobile-hide">
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L318">View Source</a>
<a href="https://github.com/justcoding121/Titanium-Web-Proxy/blob/master/src/Titanium.Web.Proxy/ProxyServer.cs/#L327">View Source</a>
</span>
<h4 id="Titanium_Web_Proxy_ProxyServer_ServerConnectionCountChanged" data-uid="Titanium.Web.Proxy.ProxyServer.ServerConnectionCountChanged">ServerConnectionCountChanged</h4>
<div class="markdown level1 summary"><p>Event occurs when server connection count changed.</p>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -350,6 +350,19 @@ references:
isSpec: "True"
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgs.GetResponseBodyAsString
nameWithType: SessionEventArgs.GetResponseBodyAsString
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgs.IsPromise
name: IsPromise
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html#Titanium_Web_Proxy_EventArguments_SessionEventArgs_IsPromise
commentId: P:Titanium.Web.Proxy.EventArguments.SessionEventArgs.IsPromise
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgs.IsPromise
nameWithType: SessionEventArgs.IsPromise
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgs.IsPromise*
name: IsPromise
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html#Titanium_Web_Proxy_EventArguments_SessionEventArgs_IsPromise_
commentId: Overload:Titanium.Web.Proxy.EventArguments.SessionEventArgs.IsPromise
isSpec: "True"
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgs.IsPromise
nameWithType: SessionEventArgs.IsPromise
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgs.MultipartRequestPartSent
name: MultipartRequestPartSent
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgs.html#Titanium_Web_Proxy_EventArguments_SessionEventArgs_MultipartRequestPartSent
......@@ -510,18 +523,18 @@ references:
isSpec: "True"
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.SessionEventArgsBase
nameWithType: SessionEventArgsBase.SessionEventArgsBase
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferPool
name: bufferPool
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferPool
commentId: F:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferPool
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferPool
nameWithType: SessionEventArgsBase.bufferPool
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferSize
name: bufferSize
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_bufferSize
commentId: F:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferSize
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.bufferSize
nameWithType: SessionEventArgsBase.bufferSize
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool
name: BufferPool
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferPool
commentId: F:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferPool
nameWithType: SessionEventArgsBase.BufferPool
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferSize
name: BufferSize
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_BufferSize
commentId: F:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferSize
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.BufferSize
nameWithType: SessionEventArgsBase.BufferSize
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ClientEndPoint
name: ClientEndPoint
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ClientEndPoint
......@@ -586,12 +599,12 @@ references:
isSpec: "True"
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.Exception
nameWithType: SessionEventArgsBase.Exception
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.exceptionFunc
name: exceptionFunc
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_exceptionFunc
commentId: F:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.exceptionFunc
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.exceptionFunc
nameWithType: SessionEventArgsBase.exceptionFunc
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc
name: ExceptionFunc
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_ExceptionFunc
commentId: F:Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc
fullName: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.ExceptionFunc
nameWithType: SessionEventArgsBase.ExceptionFunc
- uid: Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.HttpClient
name: HttpClient
href: api/Titanium.Web.Proxy.EventArguments.SessionEventArgsBase.html#Titanium_Web_Proxy_EventArguments_SessionEventArgsBase_HttpClient
......@@ -962,6 +975,19 @@ references:
isSpec: "True"
fullName: Titanium.Web.Proxy.Http.ConnectRequest.ClientHelloInfo
nameWithType: ConnectRequest.ClientHelloInfo
- uid: Titanium.Web.Proxy.Http.ConnectRequest.TunnelType
name: TunnelType
href: api/Titanium.Web.Proxy.Http.ConnectRequest.html#Titanium_Web_Proxy_Http_ConnectRequest_TunnelType
commentId: P:Titanium.Web.Proxy.Http.ConnectRequest.TunnelType
fullName: Titanium.Web.Proxy.Http.ConnectRequest.TunnelType
nameWithType: ConnectRequest.TunnelType
- uid: Titanium.Web.Proxy.Http.ConnectRequest.TunnelType*
name: TunnelType
href: api/Titanium.Web.Proxy.Http.ConnectRequest.html#Titanium_Web_Proxy_Http_ConnectRequest_TunnelType_
commentId: Overload:Titanium.Web.Proxy.Http.ConnectRequest.TunnelType
isSpec: "True"
fullName: Titanium.Web.Proxy.Http.ConnectRequest.TunnelType
nameWithType: ConnectRequest.TunnelType
- uid: Titanium.Web.Proxy.Http.ConnectResponse
name: ConnectResponse
href: api/Titanium.Web.Proxy.Http.ConnectResponse.html
......@@ -1601,6 +1627,19 @@ references:
isSpec: "True"
fullName: Titanium.Web.Proxy.Http.Request.RequestUri
nameWithType: Request.RequestUri
- uid: Titanium.Web.Proxy.Http.Request.RequestUriString
name: RequestUriString
href: api/Titanium.Web.Proxy.Http.Request.html#Titanium_Web_Proxy_Http_Request_RequestUriString
commentId: P:Titanium.Web.Proxy.Http.Request.RequestUriString
fullName: Titanium.Web.Proxy.Http.Request.RequestUriString
nameWithType: Request.RequestUriString
- uid: Titanium.Web.Proxy.Http.Request.RequestUriString*
name: RequestUriString
href: api/Titanium.Web.Proxy.Http.Request.html#Titanium_Web_Proxy_Http_Request_RequestUriString_
commentId: Overload:Titanium.Web.Proxy.Http.Request.RequestUriString
isSpec: "True"
fullName: Titanium.Web.Proxy.Http.Request.RequestUriString
nameWithType: Request.RequestUriString
- uid: Titanium.Web.Proxy.Http.Request.UpgradeToWebSocket
name: UpgradeToWebSocket
href: api/Titanium.Web.Proxy.Http.Request.html#Titanium_Web_Proxy_Http_Request_UpgradeToWebSocket
......@@ -2218,12 +2257,12 @@ references:
isSpec: "True"
fullName: Titanium.Web.Proxy.Http2.Hpack.Encoder.Encoder
nameWithType: Encoder.Encoder
- uid: Titanium.Web.Proxy.Http2.Hpack.Encoder.EncodeHeader(System.IO.BinaryWriter,System.String,System.String,System.Boolean)
name: EncodeHeader(BinaryWriter, String, String, Boolean)
href: api/Titanium.Web.Proxy.Http2.Hpack.Encoder.html#Titanium_Web_Proxy_Http2_Hpack_Encoder_EncodeHeader_System_IO_BinaryWriter_System_String_System_String_System_Boolean_
commentId: M:Titanium.Web.Proxy.Http2.Hpack.Encoder.EncodeHeader(System.IO.BinaryWriter,System.String,System.String,System.Boolean)
fullName: Titanium.Web.Proxy.Http2.Hpack.Encoder.EncodeHeader(System.IO.BinaryWriter, System.String, System.String, System.Boolean)
nameWithType: Encoder.EncodeHeader(BinaryWriter, String, String, Boolean)
- 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)
name: EncodeHeader(BinaryWriter, String, String, Boolean, HpackUtil.IndexType, Boolean)
href: api/Titanium.Web.Proxy.Http2.Hpack.Encoder.html#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_
commentId: M: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)
fullName: 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)
nameWithType: Encoder.EncodeHeader(BinaryWriter, String, String, Boolean, HpackUtil.IndexType, Boolean)
- uid: Titanium.Web.Proxy.Http2.Hpack.Encoder.EncodeHeader*
name: EncodeHeader
href: api/Titanium.Web.Proxy.Http2.Hpack.Encoder.html#Titanium_Web_Proxy_Http2_Hpack_Encoder_EncodeHeader_
......@@ -2602,6 +2641,12 @@ references:
commentId: M:Titanium.Web.Proxy.Models.HttpHeader.#ctor(System.String,System.String)
fullName: Titanium.Web.Proxy.Models.HttpHeader.HttpHeader(System.String, System.String)
nameWithType: HttpHeader.HttpHeader(String, String)
- uid: Titanium.Web.Proxy.Models.HttpHeader.#ctor(System.String,System.String,System.Boolean)
name: HttpHeader(String, String, Boolean)
href: api/Titanium.Web.Proxy.Models.HttpHeader.html#Titanium_Web_Proxy_Models_HttpHeader__ctor_System_String_System_String_System_Boolean_
commentId: M:Titanium.Web.Proxy.Models.HttpHeader.#ctor(System.String,System.String,System.Boolean)
fullName: Titanium.Web.Proxy.Models.HttpHeader.HttpHeader(System.String, System.String, System.Boolean)
nameWithType: HttpHeader.HttpHeader(String, String, Boolean)
- uid: Titanium.Web.Proxy.Models.HttpHeader.#ctor*
name: HttpHeader
href: api/Titanium.Web.Proxy.Models.HttpHeader.html#Titanium_Web_Proxy_Models_HttpHeader__ctor_
......@@ -3492,6 +3537,19 @@ references:
isSpec: "True"
fullName: Titanium.Web.Proxy.ProxyServer.EnableConnectionPool
nameWithType: ProxyServer.EnableConnectionPool
- uid: Titanium.Web.Proxy.ProxyServer.EnableHttp2
name: EnableHttp2
href: api/Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_EnableHttp2
commentId: P:Titanium.Web.Proxy.ProxyServer.EnableHttp2
fullName: Titanium.Web.Proxy.ProxyServer.EnableHttp2
nameWithType: ProxyServer.EnableHttp2
- uid: Titanium.Web.Proxy.ProxyServer.EnableHttp2*
name: EnableHttp2
href: api/Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_EnableHttp2_
commentId: Overload:Titanium.Web.Proxy.ProxyServer.EnableHttp2
isSpec: "True"
fullName: Titanium.Web.Proxy.ProxyServer.EnableHttp2
nameWithType: ProxyServer.EnableHttp2
- uid: Titanium.Web.Proxy.ProxyServer.EnableTcpServerConnectionPrefetch
name: EnableTcpServerConnectionPrefetch
href: api/Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_EnableTcpServerConnectionPrefetch
......@@ -3815,6 +3873,19 @@ references:
isSpec: "True"
fullName: Titanium.Web.Proxy.ProxyServer.TcpTimeWaitSeconds
nameWithType: ProxyServer.TcpTimeWaitSeconds
- uid: Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread
name: ThreadPoolWorkerThread
href: api/Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_ThreadPoolWorkerThread
commentId: P:Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread
fullName: Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread
nameWithType: ProxyServer.ThreadPoolWorkerThread
- uid: Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread*
name: ThreadPoolWorkerThread
href: api/Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_ThreadPoolWorkerThread_
commentId: Overload:Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread
isSpec: "True"
fullName: Titanium.Web.Proxy.ProxyServer.ThreadPoolWorkerThread
nameWithType: ProxyServer.ThreadPoolWorkerThread
- uid: Titanium.Web.Proxy.ProxyServer.UpStreamEndPoint
name: UpStreamEndPoint
href: api/Titanium.Web.Proxy.ProxyServer.html#Titanium_Web_Proxy_ProxyServer_UpStreamEndPoint
......
......@@ -4,7 +4,7 @@ using System.Runtime.InteropServices;
namespace Titanium.Web.Proxy.Examples.Basic.Helpers
{
/// <summary>
/// Adapated from
/// Adapted from
/// http://stackoverflow.com/questions/13656846/how-to-programmatic-disable-c-sharp-console-applications-quick-edit-mode
/// </summary>
internal static class ConsoleHelper
......
......@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Demo")]
[assembly: AssemblyCopyright("Copyright © Titanium 2015-2017")]
[assembly: AssemblyCopyright("Copyright © Titanium 2015-2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
......
......@@ -32,11 +32,11 @@ namespace Titanium.Web.Proxy.Examples.Basic
{
if (exception is ProxyHttpException phex)
{
await WriteToConsole(exception.Message + ": " + phex.InnerException?.Message, true);
await writeToConsole(exception.Message + ": " + phex.InnerException?.Message, true);
}
else
{
await WriteToConsole(exception.Message, true);
await writeToConsole(exception.Message, true);
}
};
proxyServer.ForwardToUpstreamGateway = true;
......@@ -52,8 +52,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
public void StartProxy()
{
proxyServer.BeforeRequest += OnRequest;
proxyServer.BeforeResponse += OnResponse;
proxyServer.BeforeRequest += onRequest;
proxyServer.BeforeResponse += onResponse;
proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
......@@ -63,8 +63,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000);
// Fired when a CONNECT request is received
explicitEndPoint.BeforeTunnelConnectRequest += OnBeforeTunnelConnectRequest;
explicitEndPoint.BeforeTunnelConnectResponse += OnBeforeTunnelConnectResponse;
explicitEndPoint.BeforeTunnelConnectRequest += onBeforeTunnelConnectRequest;
explicitEndPoint.BeforeTunnelConnectResponse += onBeforeTunnelConnectResponse;
// An explicit endpoint is where the client knows about the existence of a proxy
// So client sends request in a proxy friendly manner
......@@ -102,11 +102,11 @@ namespace Titanium.Web.Proxy.Examples.Basic
public void Stop()
{
explicitEndPoint.BeforeTunnelConnectRequest -= OnBeforeTunnelConnectRequest;
explicitEndPoint.BeforeTunnelConnectResponse -= OnBeforeTunnelConnectResponse;
explicitEndPoint.BeforeTunnelConnectRequest -= onBeforeTunnelConnectRequest;
explicitEndPoint.BeforeTunnelConnectResponse -= onBeforeTunnelConnectResponse;
proxyServer.BeforeRequest -= OnRequest;
proxyServer.BeforeResponse -= OnResponse;
proxyServer.BeforeRequest -= onRequest;
proxyServer.BeforeResponse -= onResponse;
proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;
......@@ -116,10 +116,10 @@ namespace Titanium.Web.Proxy.Examples.Basic
//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;
await WriteToConsole("Tunnel to: " + hostname);
await writeToConsole("Tunnel to: " + hostname);
if (hostname.Contains("dropbox.com"))
{
......@@ -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);
}
// 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(e.HttpClient.Request.Url);
await writeToConsole("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
await writeToConsole(e.HttpClient.Request.Url);
// store it in the UserData property
// It can be a simple integer, Guid, or any type
......@@ -177,19 +177,19 @@ namespace Titanium.Web.Proxy.Examples.Basic
}
// Modify response
private async Task MultipartRequestPartSent(object sender, MultipartRequestPartSentEventArgs e)
private async Task multipartRequestPartSent(object sender, MultipartRequestPartSentEventArgs e)
{
var session = (SessionEventArgs)sender;
await WriteToConsole("Multipart form data headers:");
await writeToConsole("Multipart form data 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);
......@@ -261,7 +261,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
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();
......
......@@ -36,13 +36,20 @@
</ListView>
<TabControl Grid.Column="2" Grid.Row="0">
<TabItem Header="Session">
<Grid Background="Red" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<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>
</TabItem>
</TabControl>
......
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
......@@ -8,6 +9,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
......@@ -36,6 +38,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf
public MainWindow()
{
proxyServer = new ProxyServer();
proxyServer.EnableHttp2 = true;
//proxyServer.CertificateManager.CertificateEngine = CertificateEngine.DefaultWindows;
////Set a password for the .pfx file
......@@ -53,6 +58,9 @@ namespace Titanium.Web.Proxy.Examples.Wpf
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
//proxyServer.CertificateManager.EnsureRootCertificate(true);
......@@ -93,7 +101,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
InitializeComponent();
}
public ObservableCollection<SessionListItem> Sessions { get; } = new ObservableCollection<SessionListItem>();
public ObservableCollectionEx<SessionListItem> Sessions { get; } = new ObservableCollectionEx<SessionListItem>();
public SessionListItem SelectedSession
{
......@@ -103,7 +111,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
if (value != selectedSession)
{
selectedSession = value;
SelectedSessionChanged();
selectedSessionChanged();
}
}
}
......@@ -128,7 +136,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
e.DecryptSsl = false;
}
await Dispatcher.InvokeAsync(() => { AddSession(e); });
await Dispatcher.InvokeAsync(() => { addSession(e); });
}
private async Task ProxyServer_BeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e)
......@@ -144,8 +152,20 @@ namespace Titanium.Web.Proxy.Examples.Wpf
private async Task ProxyServer_BeforeRequest(object sender, SessionEventArgs e)
{
if (e.HttpClient.ConnectRequest?.TunnelType != TunnelType.Http2)
{
return;
}
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)
{
......@@ -156,6 +176,11 @@ namespace Titanium.Web.Proxy.Examples.Wpf
private async Task ProxyServer_BeforeResponse(object sender, SessionEventArgs e)
{
if (e.HttpClient.ConnectRequest?.TunnelType != TunnelType.Http2)
{
return;
}
SessionListItem item = null;
await Dispatcher.InvokeAsync(() =>
{
......@@ -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 (e.HttpClient.Response.HasBody)
......@@ -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);
sessionDictionary.Add(e.HttpClient, item);
return item;
}
private SessionListItem CreateSessionListItem(SessionEventArgsBase e)
private SessionListItem createSessionListItem(SessionEventArgsBase e)
{
lastSessionNumber++;
bool isTunnelConnect = e is TunnelConnectSessionEventArgs;
......@@ -211,18 +240,30 @@ namespace Titanium.Web.Proxy.Examples.Wpf
{
e.DataReceived += (sender, args) =>
{
var session = (SessionEventArgs)sender;
var session = (SessionEventArgsBase)sender;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
if (tunnelType != TunnelType.Unknown)
{
li.Protocol = TunnelTypeToString(tunnelType);
}
li.ReceivedDataCount += args.Count;
}
};
e.DataSent += (sender, args) =>
{
var session = (SessionEventArgs)sender;
var session = (SessionEventArgsBase)sender;
if (sessionDictionary.TryGetValue(session.HttpClient, out var li))
{
var tunnelType = session.HttpClient.ConnectRequest?.TunnelType ?? TunnelType.Unknown;
if (tunnelType != TunnelType.Unknown)
{
li.Protocol = TunnelTypeToString(tunnelType);
}
li.SentDataCount += args.Count;
}
};
......@@ -232,20 +273,38 @@ namespace Titanium.Web.Proxy.Examples.Wpf
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)
{
if (e.Key == Key.Delete)
{
var selectedItems = ((ListView)sender).SelectedItems;
Sessions.SuppressNotification = true;
foreach (var item in selectedItems.Cast<SessionListItem>().ToArray())
{
Sessions.Remove(item);
sessionDictionary.Remove(item.HttpClient);
}
Sessions.SuppressNotification = false;
}
}
private void SelectedSessionChanged()
private void selectedSessionChanged()
{
if (SelectedSession == null)
{
......@@ -256,7 +315,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf
var session = SelectedSession.HttpClient;
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;
if (truncated)
{
......@@ -272,7 +332,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf
TextBoxRequest.Text = sb.ToString();
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;
if (truncated)
{
......@@ -292,6 +353,19 @@ namespace Titanium.Web.Proxy.Examples.Wpf
}
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
}
/// <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
/// or of the Lazy.Value property can never be null.
/// </summary>
......@@ -85,7 +85,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf.Annotations
}
/// <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
/// or of the Lazy.Value property can be null.
/// </summary>
......@@ -251,7 +251,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf.Annotations
/// </list>
/// 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
/// 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 />
/// 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
......
......@@ -10,7 +10,7 @@ using System.Windows;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Demo WPF")]
[assembly: AssemblyCopyright("Copyright ©2017 Titanium")]
[assembly: AssemblyCopyright("Copyright © Titanium 2015-2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
......
......@@ -11,7 +11,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
private long? bodySize;
private Exception exception;
private string host;
private string process;
private int processId;
private string protocol;
private long receivedDataCount;
private long sentDataCount;
......@@ -54,10 +54,32 @@ namespace Titanium.Web.Proxy.Examples.Wpf
set => SetField(ref bodySize, value);
}
public int ProcessId
{
get => processId;
set
{
if (SetField(ref processId, value))
{
OnPropertyChanged(nameof(Process));
}
}
}
public string Process
{
get => process;
set => SetField(ref process, value);
get
{
try
{
var process = System.Diagnostics.Process.GetProcessById(processId);
return process.ProcessName + ":" + processId;
}
catch (Exception)
{
return string.Empty;
}
}
}
public long ReceivedDataCount
......@@ -80,13 +102,16 @@ namespace Titanium.Web.Proxy.Examples.Wpf
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))
{
field = value;
OnPropertyChanged(propertyName);
return true;
}
return false;
}
[NotifyPropertyChangedInvocator]
......@@ -132,20 +157,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
BodySize = responseSize;
}
Process = GetProcessDescription(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;
}
ProcessId = HttpClient.ProcessId.Value;
}
}
}
<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 @@
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<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.Data" />
<Reference Include="System.Xml" />
......@@ -95,6 +92,7 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="ObservableCollectionEx.cs" />
<Compile Include="Properties\Annotations.cs" />
<Compile Include="SessionListItem.cs" />
<Page Include="MainWindow.xaml">
......@@ -128,7 +126,6 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<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
# Visual Studio 15
VisualStudioVersion = 15.0.26906.1
# Visual Studio Version 16
VisualStudioVersion = 16.0.29102.190
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{B6DBABDC-C985-4872-9C38-B4E5079CBC4B}"
EndProject
......@@ -23,7 +23,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{BC1E0789
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy", "Titanium.Web.Proxy\Titanium.Web.Proxy.csproj", "{91018B6D-A7A9-45BE-9CB3-79CBB8B169A6}"
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
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
......
......@@ -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/=OID/@EntryIndexedValue">OID</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/=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/=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/=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_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_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_002ECSharpPlaceAttributeOnSameLineMigration/@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
public X509Certificate RemoteCertificate { get; internal set; }
/// <summary>
/// Acceptable issuers as listed by remoted server.
/// Acceptable issuers as listed by remote server.
/// </summary>
public string[] AcceptableIssuers { get; internal set; }
......
......@@ -2,8 +2,9 @@
using System.Globalization;
using System.IO;
using System.Threading.Tasks;
using StreamExtended;
using StreamExtended.Network;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments
{
......@@ -60,7 +61,11 @@ namespace Titanium.Web.Proxy.EventArguments
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;
if (chunkSize == 0)
......
......@@ -4,12 +4,12 @@ using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.Compression;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http.Responses;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments
{
......@@ -28,6 +28,11 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
private bool reRequest;
/// <summary>
/// Is this session a HTTP/2 promise?
/// </summary>
public bool IsPromise { get; internal set; }
/// <summary>
/// Constructor to initialize the proxy
/// </summary>
......@@ -88,6 +93,27 @@ namespace Titanium.Web.Proxy.EventArguments
// If not already read (not cached yet)
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);
request.Body = body;
......@@ -98,6 +124,7 @@ namespace Titanium.Web.Proxy.EventArguments
OnDataSent(body, 0, body.Length);
}
}
}
/// <summary>
/// reinit response object
......@@ -117,7 +144,7 @@ namespace Titanium.Web.Proxy.EventArguments
}
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
// If not already read (not cached yet)
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);
response.Body = body;
......@@ -149,12 +197,13 @@ namespace Titanium.Web.Proxy.EventArguments
OnDataReceived(body, 0, body.Length);
}
}
}
private async Task<byte[]> readBodyAsync(bool isRequest, CancellationToken cancellationToken)
{
using (var bodyStream = new MemoryStream())
{
var writer = new HttpWriter(bodyStream, bufferPool, bufferSize);
var writer = new HttpWriter(bodyStream, BufferPool, BufferSize);
if (isRequest)
{
......@@ -186,7 +235,7 @@ namespace Titanium.Web.Proxy.EventArguments
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);
}
}
......@@ -207,7 +256,7 @@ namespace Titanium.Web.Proxy.EventArguments
var reader = getStreamReader(true);
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)
{
......@@ -259,7 +308,7 @@ namespace Titanium.Web.Proxy.EventArguments
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)
{
......@@ -268,7 +317,7 @@ namespace Titanium.Web.Proxy.EventArguments
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);
}
......@@ -290,7 +339,7 @@ namespace Titanium.Web.Proxy.EventArguments
{
int bufferDataLength = 0;
var buffer = bufferPool.GetBuffer(bufferSize);
var buffer = BufferPool.GetBuffer(BufferSize);
try
{
int boundaryLength = boundary.Length + 4;
......@@ -340,7 +389,7 @@ namespace Titanium.Web.Proxy.EventArguments
}
finally
{
bufferPool.ReturnBuffer(buffer);
BufferPool.ReturnBuffer(buffer);
}
}
......
......@@ -2,13 +2,13 @@
using System.Collections.Generic;
using System.Net;
using System.Threading;
using StreamExtended;
using StreamExtended.Network;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.EventArguments
{
......@@ -24,14 +24,14 @@ namespace Titanium.Web.Proxy.EventArguments
internal TcpServerConnection ServerConnection => HttpClient.Connection;
internal TcpClientConnection ClientConnection => ProxyClient.Connection;
protected readonly int bufferSize;
protected readonly IBufferPool bufferPool;
protected readonly ExceptionHandler exceptionFunc;
protected readonly int BufferSize;
protected readonly IBufferPool BufferPool;
protected readonly ExceptionHandler ExceptionFunc;
/// <summary>
/// Relative milliseconds for various events.
/// </summary>
public Dictionary<string, DateTime> TimeLine { get; set; } = new Dictionary<string, DateTime>();
public Dictionary<string, DateTime> TimeLine { get; } = new Dictionary<string, DateTime>();
/// <summary>
/// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
......@@ -39,9 +39,9 @@ namespace Titanium.Web.Proxy.EventArguments
private SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
CancellationTokenSource cancellationTokenSource)
{
bufferSize = server.BufferSize;
bufferPool = server.BufferPool;
exceptionFunc = server.ExceptionFunc;
BufferSize = server.BufferSize;
BufferPool = server.BufferPool;
ExceptionFunc = server.ExceptionFunc;
TimeLine["Session Created"] = DateTime.Now;
}
......@@ -55,25 +55,7 @@ namespace Titanium.Web.Proxy.EventArguments
HttpClient = new HttpWebClient(request);
LocalEndPoint = endPoint;
HttpClient.ProcessId = new Lazy<int>(() =>
{
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();
});
HttpClient.ProcessId = new Lazy<int>(() => ProxyClient.Connection.GetProcessId(endPoint));
}
/// <summary>
......@@ -161,7 +143,7 @@ namespace Titanium.Web.Proxy.EventArguments
}
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
}
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
public bool DenyConnect { get; set; }
/// <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>
public bool 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;
}
......
......@@ -20,7 +20,7 @@ namespace Titanium.Web.Proxy.Exceptions
/// Initializes a new instance of the <see cref="ProxyException" /> class.
/// - must be invoked by derived classes' constructors
/// </summary>
/// <param name="message">Excception message</param>
/// <param name="message">Exception message</param>
/// <param name="innerException">Inner exception associated</param>
protected ProxyException(string message, Exception innerException) : base(message, innerException)
{
......
......@@ -7,8 +7,6 @@ using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions;
......@@ -17,6 +15,9 @@ using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http2;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended;
using Titanium.Web.Proxy.StreamExtended.Network;
using SslExtensions = Titanium.Web.Proxy.Extensions.SslExtensions;
namespace Titanium.Web.Proxy
{
......@@ -48,9 +49,8 @@ namespace Titanium.Web.Proxy
string connectHostname = null;
TunnelConnectSessionEventArgs connectArgs = null;
// Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
if (await HttpHelper.IsConnectMethod(clientStream) == 1)
if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, BufferSize, cancellationToken) == 1)
{
// read the first line HTTP command
string httpCmd = await clientStream.ReadLineAsync(cancellationToken);
......@@ -103,7 +103,7 @@ namespace Titanium.Web.Proxy
if (await checkAuthorization(connectArgs) == false)
{
await endPoint.InvokeBeforeTunnectConnectResponse(this, connectArgs, ExceptionFunc);
await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc);
// send the response
await clientStreamWriter.WriteResponseAsync(connectArgs.HttpClient.Response,
......@@ -111,8 +111,8 @@ namespace Titanium.Web.Proxy
return;
}
// write back successfull CONNECT response
var response = ConnectResponse.CreateSuccessfullConnectResponse(version);
// write back successful CONNECT response
var response = ConnectResponse.CreateSuccessfulConnectResponse(version);
// Set ContentLength explicitly to properly handle HTTP 1.0
response.ContentLength = 0;
......@@ -126,10 +126,11 @@ namespace Titanium.Web.Proxy
bool isClientHello = clientHelloInfo != null;
if (isClientHello)
{
connectRequest.TunnelType = TunnelType.Https;
connectRequest.ClientHelloInfo = clientHelloInfo;
}
await endPoint.InvokeBeforeTunnectConnectResponse(this, connectArgs, ExceptionFunc, isClientHello);
await endPoint.InvokeBeforeTunnelConnectResponse(this, connectArgs, ExceptionFunc, isClientHello);
if (decryptSsl && isClientHello)
{
......@@ -141,18 +142,35 @@ namespace Titanium.Web.Proxy
if (alpn != null && alpn.Contains(SslApplicationProtocol.Http2))
{
// test server HTTP/2 support
try
{
// todo: this is a hack, because Titanium does not support HTTP protocol changing currently
var connection = await tcpConnectionFactory.GetServerConnection(this, connectArgs,
isConnect: true, applicationProtocols: SslExtensions.Http2ProtocolAsList,
noCache: true, cancellationToken: cancellationToken);
http2Supported = connection.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2;
//release connection back to pool intead of closing when connection pool is enabled.
http2Supported = connection.NegotiatedApplicationProtocol ==
SslApplicationProtocol.Http2;
//release connection back to pool instead of closing when connection pool is enabled.
await tcpConnectionFactory.Release(connection, true);
}
catch (Exception)
{
// ignore
}
}
if (EnableTcpServerConnectionPrefetch)
{
IPAddress[] ipAddresses = null;
try
{
//make sure the host can be resolved before creating the prefetch task
ipAddresses = await Dns.GetHostAddressesAsync(connectArgs.HttpClient.Request.RequestUri.Host);
}
catch (SocketException) { }
if (ipAddresses != null && ipAddresses.Length > 0)
{
//don't pass cancellation token here
//it could cause floating server connections when client exits
......@@ -160,11 +178,12 @@ namespace Titanium.Web.Proxy
isConnect: true, applicationProtocols: null, noCache: false,
cancellationToken: CancellationToken.None);
}
}
X509Certificate2 certificate = null;
try
{
sslStream = new SslStream(clientStream, true);
sslStream = new SslStream(clientStream, false);
string certName = HttpHelper.GetWildCardDomainName(connectHostname);
certificate = endPoint.GenericCertificate ??
......@@ -172,7 +191,7 @@ namespace Titanium.Web.Proxy
// Successfully managed to authenticate the client using the fake certificate
var options = new SslServerAuthenticationOptions();
if (http2Supported)
if (EnableHttp2 && http2Supported)
{
options.ApplicationProtocols = clientHelloInfo.GetAlpn();
if (options.ApplicationProtocols == null || options.ApplicationProtocols.Count == 0)
......@@ -197,12 +216,12 @@ namespace Titanium.Web.Proxy
}
catch (Exception e)
{
var certname = certificate?.GetNameInfo(X509NameType.SimpleName, false);
var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
throw new ProxyConnectException(
$"Couldn't authenticate host '{connectHostname}' with certificate '{certname}'.", e, connectArgs);
$"Couldn't authenticate host '{connectHostname}' with certificate '{certName}'.", e, connectArgs);
}
if (await HttpHelper.IsConnectMethod(clientStream) == -1)
if (await HttpHelper.IsConnectMethod(clientStream, BufferPool, BufferSize, cancellationToken) == -1)
{
decryptSsl = false;
}
......@@ -222,6 +241,11 @@ namespace Titanium.Web.Proxy
// Hostname is excluded or it is not an HTTPS connect
if (!decryptSsl || !isClientHello)
{
if (!isClientHello)
{
connectRequest.TunnelType = TunnelType.Websocket;
}
// create new connection to server.
// If we detected that client tunnel CONNECTs without SSL by checking for empty client hello then
// this connection should not be HTTPS.
......@@ -242,7 +266,7 @@ namespace Titanium.Web.Proxy
try
{
await clientStream.ReadAsync(data, 0, available, cancellationToken);
// clientStream.Available sbould be at most BufferSize because it is using the same buffer size
// clientStream.Available should be at most BufferSize because it is using the same buffer size
await connection.StreamWriter.WriteAsync(data, 0, available, true, cancellationToken);
}
finally
......@@ -269,12 +293,14 @@ namespace Titanium.Web.Proxy
}
}
if (connectArgs != null && await HttpHelper.IsPriMethod(clientStream) == 1)
if (connectArgs != null && await HttpHelper.IsPriMethod(clientStream, BufferPool, BufferSize, cancellationToken) == 1)
{
// todo
string httpCmd = await clientStream.ReadLineAsync(cancellationToken);
if (httpCmd == "PRI * HTTP/2.0")
{
connectArgs.HttpClient.ConnectRequest.TunnelType = TunnelType.Http2;
// HTTP/2 Connection Preface
string line = await clientStream.ReadLineAsync(cancellationToken);
if (line != string.Empty)
......@@ -307,9 +333,16 @@ namespace Titanium.Web.Proxy
await Http2Helper.SendHttp2(clientStream, connection.Stream, BufferSize,
(buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); },
(buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
() => new SessionEventArgs(this, endPoint, cancellationTokenSource)
{
ProxyClient = { Connection = clientConnection },
HttpClient = { ConnectRequest = connectArgs?.HttpClient.ConnectRequest },
UserData = connectArgs?.UserData
},
async args => { await invokeBeforeRequest(args); },
async args => { await invokeBeforeResponse(args); },
connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc);
#endif
}
finally
{
......
......@@ -5,7 +5,7 @@ using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.StreamExtended;
namespace Titanium.Web.Proxy.Extensions
{
......
......@@ -2,7 +2,7 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.Extensions
{
......@@ -17,6 +17,7 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="input"></param>
/// <param name="output"></param>
/// <param name="onCopy"></param>
/// <param name="bufferPool"></param>
/// <param name="bufferSize"></param>
internal static Task CopyToAsync(this Stream input, Stream output, Action<byte[], int, int> onCopy,
IBufferPool bufferPool, int bufferSize)
......@@ -30,6 +31,7 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="input"></param>
/// <param name="output"></param>
/// <param name="onCopy"></param>
/// <param name="bufferPool"></param>
/// <param name="bufferSize"></param>
/// <param name="cancellationToken"></param>
internal static async Task CopyToAsync(this Stream input, Stream output, Action<byte[], int, int> onCopy,
......
using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Helpers
{
......@@ -120,9 +123,9 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
/// <param name="clientStreamReader">The client stream reader.</param>
/// <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>
......@@ -130,9 +133,9 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
/// <param name="clientStreamReader">The client stream reader.</param>
/// <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>
......@@ -143,37 +146,47 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns>
/// 1: when starts with the given string, 0: when valid HTTP method, -1: otherwise
/// </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 legthToCheck = 10;
for (int i = 0; i < legthToCheck; i++)
int iRet = -1;
const int lengthToCheck = 10;
byte[] buffer = null;
try
{
int b = await clientStreamReader.PeekByteAsync(i);
if (b == -1)
buffer = bufferPool.GetBuffer(Math.Max(bufferSize, lengthToCheck));
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;
if (!char.IsLetter(ch))
{
return -1;
}
if (i >= expectedStart.Length || ch != expectedStart[i])
{
else if (i >= expectedStart.Length || ch != expectedStart[i])
isExpected = false;
}
}
// only letters
return isExpected ? 1 : 0;
iRet = isExpected ? 1 : 0;
}
}
finally
{
bufferPool.ReturnBuffer(buffer);
buffer = null;
}
return iRet;
}
}
}
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.Helpers
{
......@@ -23,7 +23,7 @@ namespace Titanium.Web.Proxy.Helpers
internal async Task WriteRequestAsync(Request request, bool flush = true,
CancellationToken cancellationToken = default)
{
await WriteLineAsync(Request.CreateRequestLine(request.Method, request.OriginalUrl, request.HttpVersion),
await WriteLineAsync(Request.CreateRequestLine(request.Method, request.RequestUriString, request.HttpVersion),
cancellationToken);
await WriteAsync(request, flush, cancellationToken);
}
......
......@@ -2,8 +2,8 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.Helpers
{
......
......@@ -4,10 +4,10 @@ using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using StreamExtended.Network;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Helpers
{
......@@ -18,18 +18,13 @@ namespace Titanium.Web.Proxy.Helpers
private static readonly byte[] newLine = ProxyConstants.NewLineBytes;
private static readonly Encoder encoder = Encoding.ASCII.GetEncoder();
private readonly char[] charBuffer;
private static readonly Encoding encoder = Encoding.ASCII;
internal HttpWriter(Stream stream, IBufferPool bufferPool, int bufferSize)
{
BufferSize = bufferSize;
this.stream = stream;
this.bufferPool = bufferPool;
// ASCII encoder max byte count is char count + 1
charBuffer = new char[BufferSize - 1];
}
internal int BufferSize { get; }
......@@ -55,12 +50,10 @@ namespace Titanium.Web.Proxy.Helpers
int charCount = value.Length;
if (charCount < BufferSize - newLineChars)
{
value.CopyTo(0, charBuffer, 0, charCount);
var buffer = bufferPool.GetBuffer(BufferSize);
try
{
int idx = encoder.GetBytes(charBuffer, 0, charCount, buffer, 0, true);
int idx = encoder.GetBytes(value, 0, charCount, buffer, 0);
if (newLineChars > 0)
{
Buffer.BlockCopy(newLine, 0, buffer, idx, newLineChars);
......@@ -76,11 +69,8 @@ namespace Titanium.Web.Proxy.Helpers
}
else
{
var charBuffer = new char[charCount];
value.CopyTo(0, charBuffer, 0, charCount);
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)
{
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
internal static bool IsRunningAsUwp()
{
if (IsWindows7OrLower)
if (isWindows7OrLower)
{
return false;
}
......@@ -87,7 +87,7 @@ namespace Titanium.Web.Proxy.Helpers
}
}
private static bool IsWindows7OrLower
private static bool isWindows7OrLower
{
get
{
......
......@@ -80,7 +80,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="protocolType"></param>
internal void SetProxy(string hostname, int port, ProxyProtocolType protocolType)
{
using (var reg = OpenInternetSettingsKey())
using (var reg = openInternetSettingsKey())
{
if (reg == null)
{
......@@ -127,7 +127,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
internal void RemoveProxy(ProxyProtocolType protocolType, bool saveOriginalConfig = true)
{
using (var reg = OpenInternetSettingsKey())
using (var reg = openInternetSettingsKey())
{
if (reg == null)
{
......@@ -168,7 +168,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
internal void DisableAllProxy()
{
using (var reg = OpenInternetSettingsKey())
using (var reg = openInternetSettingsKey())
{
if (reg == null)
{
......@@ -186,7 +186,7 @@ namespace Titanium.Web.Proxy.Helpers
internal void SetAutoProxyUrl(string url)
{
using (var reg = OpenInternetSettingsKey())
using (var reg = openInternetSettingsKey())
{
if (reg == null)
{
......@@ -201,7 +201,7 @@ namespace Titanium.Web.Proxy.Helpers
internal void SetProxyOverride(string proxyOverride)
{
using (var reg = OpenInternetSettingsKey())
using (var reg = openInternetSettingsKey())
{
if (reg == null)
{
......@@ -286,7 +286,7 @@ namespace Titanium.Web.Proxy.Helpers
internal ProxyInfo GetProxyInfoFromRegistry()
{
using (var reg = OpenInternetSettingsKey())
using (var reg = openInternetSettingsKey())
{
if (reg == null)
{
......@@ -347,7 +347,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary>
/// Opens the registry key with the internet settings
/// </summary>
private static RegistryKey OpenInternetSettingsKey()
private static RegistryKey openInternetSettingsKey()
{
return Registry.CurrentUser.OpenSubKey(regKeyInternetSettings, true);
}
......
using System;
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.Helpers
{
......@@ -96,11 +96,12 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary>
/// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers
/// as prefix
/// Usefull for websocket requests
/// Useful for websocket requests
/// Task-based Asynchronous Pattern
/// </summary>
/// <param name="clientStream"></param>
/// <param name="serverStream"></param>
/// <param name="bufferPool"></param>
/// <param name="bufferSize"></param>
/// <param name="onDataSend"></param>
/// <param name="onDataReceive"></param>
......@@ -128,10 +129,11 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary>
/// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers
/// as prefix
/// Usefull for websocket requests
/// Useful for websocket requests
/// </summary>
/// <param name="clientStream"></param>
/// <param name="serverStream"></param>
/// <param name="bufferPool"></param>
/// <param name="bufferSize"></param>
/// <param name="onDataSend"></param>
/// <param name="onDataReceive"></param>
......
using StreamExtended;
using Titanium.Web.Proxy.StreamExtended;
namespace Titanium.Web.Proxy.Http
{
......@@ -12,6 +12,8 @@ namespace Titanium.Web.Proxy.Http
Method = "CONNECT";
}
public TunnelType TunnelType { get; internal set; }
public ClientHelloInfo ClientHelloInfo { get; set; }
}
}
using System;
using System.Net;
using StreamExtended;
using Titanium.Web.Proxy.StreamExtended;
namespace Titanium.Web.Proxy.Http
{
......@@ -12,11 +12,11 @@ namespace Titanium.Web.Proxy.Http
public ServerHelloInfo ServerHelloInfo { get; set; }
/// <summary>
/// Creates a successfull CONNECT response
/// Creates a successful CONNECT response
/// </summary>
/// <param name="httpVersion"></param>
/// <returns></returns>
internal static ConnectResponse CreateSuccessfullConnectResponse(Version httpVersion)
internal static ConnectResponse CreateSuccessfulConnectResponse(Version httpVersion)
{
var response = new ConnectResponse
{
......
......@@ -67,7 +67,7 @@ namespace Titanium.Web.Proxy.Http
/// <summary>
/// Returns all headers with given name if exists
/// Returns null if does'nt exist
/// Returns null if doesn't exist
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
......
using System;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Http
{
......
......@@ -97,10 +97,19 @@ namespace Titanium.Web.Proxy.Http
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
await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method,
useUpstreamProxy || isTransparent ? Request.OriginalUrl : Request.RequestUri.PathAndQuery,
Request.HttpVersion), cancellationToken);
await writer.WriteLineAsync(Request.CreateRequestLine(Request.Method, url, Request.HttpVersion), cancellationToken);
var headerBuilder = new StringBuilder();
......
......@@ -6,28 +6,28 @@
public static class KnownHeaders
{
// Both
public const string Connection = "connection";
public const string Connection = "Connection";
public const string ConnectionClose = "close";
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 ContentTypeBoundary = "boundary";
public const string Upgrade = "upgrade";
public const string Upgrade = "Upgrade";
public const string UpgradeWebsocket = "websocket";
// Request headers
public const string AcceptEncoding = "accept-encoding";
public const string AcceptEncoding = "Accept-Encoding";
public const string Authorization = "Authorization";
public const string Expect = "expect";
public const string Expect = "Expect";
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 ProxyAuthorizationBasic = "basic";
......@@ -36,7 +36,7 @@
public const string ProxyConnectionClose = "close";
// Response headers
public const string ContentEncoding = "content-encoding";
public const string ContentEncoding = "Content-Encoding";
public const string ContentEncodingDeflate = "deflate";
public const string ContentEncodingGzip = "gzip";
public const string ContentEncodingBrotli = "br";
......@@ -45,7 +45,7 @@
public const string ProxyAuthenticate = "Proxy-Authenticate";
public const string TransferEncoding = "transfer-encoding";
public const string TransferEncoding = "Transfer-Encoding";
public const string TransferEncodingChunked = "chunked";
}
}
......@@ -14,6 +14,8 @@ namespace Titanium.Web.Proxy.Http
[TypeConverter(typeof(ExpandableObjectConverter))]
public class Request : RequestResponseBase
{
private string originalUrl;
/// <summary>
/// Request Method.
/// </summary>
......@@ -32,7 +34,20 @@ namespace Titanium.Web.Proxy.Http
/// <summary>
/// The original request Url.
/// </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>
/// Has request body?
......@@ -140,7 +155,7 @@ namespace Titanium.Web.Proxy.Http
get
{
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)
{
sb.Append($"{header.ToString()}{ProxyConstants.NewLine}");
......
......@@ -3,6 +3,7 @@ using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Compression;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
......@@ -49,6 +50,21 @@ namespace Titanium.Web.Proxy.Http
/// </summary>
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>
/// Keeps the body data after the session is finished.
/// </summary>
......@@ -189,11 +205,13 @@ namespace Titanium.Web.Proxy.Http
public bool IsBodyRead { get; internal set; }
/// <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.
/// </summary>
internal bool Locked { get; set; }
internal bool BodyAvailable => BodyInternal != null;
internal abstract void EnsureBodyAvailable(bool throwWhenNotReadYet = true);
/// <summary>
......
namespace Titanium.Web.Proxy.Http
{
public enum TunnelType
{
Unknown,
Https,
Websocket,
Http2,
}
}
......@@ -61,7 +61,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <param name="name">Name.</param>
/// <param name="value">Value.</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 (sensitive)
......@@ -116,10 +118,9 @@ namespace Titanium.Web.Proxy.Http2.Hpack
}
else
{
int nameIndex = getNameIndex(name);
int nameIndex = useStaticName ? getNameIndex(name) : -1;
ensureCapacity(headerSize);
var indexType = HpackUtil.IndexType.Incremental;
encodeLiteral(output, name, value, indexType, nameIndex);
add(name, value);
}
......@@ -309,7 +310,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
int i = index(h);
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;
}
......@@ -336,7 +337,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
int index = -1;
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;
break;
......@@ -513,7 +514,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <param name="value">Value.</param>
/// <param name="index">Index.</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;
Hash = hash;
......
......@@ -59,102 +59,102 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/* 14 */
new HttpHeader(":status", "500"),
/* 15 */
new HttpHeader("accept-charset", string.Empty),
new HttpHeader("Accept-Charset", string.Empty),
/* 16 */
new HttpHeader("accept-encoding", "gzip, deflate"),
new HttpHeader("Accept-Encoding", "gzip, deflate"),
/* 17 */
new HttpHeader("accept-language", string.Empty),
new HttpHeader("Accept-Language", string.Empty),
/* 18 */
new HttpHeader("accept-ranges", string.Empty),
new HttpHeader("Accept-Ranges", string.Empty),
/* 19 */
new HttpHeader("accept", string.Empty),
new HttpHeader("Accept", string.Empty),
/* 20 */
new HttpHeader("access-control-allow-origin", string.Empty),
new HttpHeader("Access-Control-Allow-Origin", string.Empty),
/* 21 */
new HttpHeader("age", string.Empty),
new HttpHeader("Age", string.Empty),
/* 22 */
new HttpHeader("allow", string.Empty),
new HttpHeader("Allow", string.Empty),
/* 23 */
new HttpHeader("authorization", string.Empty),
new HttpHeader("Authorization", string.Empty),
/* 24 */
new HttpHeader("cache-control", string.Empty),
new HttpHeader("Cache-Control", string.Empty),
/* 25 */
new HttpHeader("content-disposition", string.Empty),
new HttpHeader("Content-Disposition", string.Empty),
/* 26 */
new HttpHeader("content-encoding", string.Empty),
new HttpHeader("Content-Encoding", string.Empty),
/* 27 */
new HttpHeader("content-language", string.Empty),
new HttpHeader("Content-Language", string.Empty),
/* 28 */
new HttpHeader("content-length", string.Empty),
new HttpHeader("Content-Length", string.Empty),
/* 29 */
new HttpHeader("content-location", string.Empty),
new HttpHeader("Content-Location", string.Empty),
/* 30 */
new HttpHeader("content-range", string.Empty),
new HttpHeader("Content-Range", string.Empty),
/* 31 */
new HttpHeader("content-type", string.Empty),
new HttpHeader("Content-Type", string.Empty),
/* 32 */
new HttpHeader("cookie", string.Empty),
new HttpHeader("Cookie", string.Empty),
/* 33 */
new HttpHeader("date", string.Empty),
new HttpHeader("Date", string.Empty),
/* 34 */
new HttpHeader("etag", string.Empty),
new HttpHeader("ETag", string.Empty),
/* 35 */
new HttpHeader("expect", string.Empty),
new HttpHeader("Expect", string.Empty),
/* 36 */
new HttpHeader("expires", string.Empty),
new HttpHeader("Expires", string.Empty),
/* 37 */
new HttpHeader("from", string.Empty),
new HttpHeader("From", string.Empty),
/* 38 */
new HttpHeader("host", string.Empty),
new HttpHeader("Host", string.Empty),
/* 39 */
new HttpHeader("if-match", string.Empty),
new HttpHeader("If-Match", string.Empty),
/* 40 */
new HttpHeader("if-modified-since", string.Empty),
new HttpHeader("If-Modified-Since", string.Empty),
/* 41 */
new HttpHeader("if-none-match", string.Empty),
new HttpHeader("If-None-Match", string.Empty),
/* 42 */
new HttpHeader("if-range", string.Empty),
new HttpHeader("If-Range", string.Empty),
/* 43 */
new HttpHeader("if-unmodified-since", string.Empty),
new HttpHeader("If-Unmodified-Since", string.Empty),
/* 44 */
new HttpHeader("last-modified", string.Empty),
new HttpHeader("Last-Modified", string.Empty),
/* 45 */
new HttpHeader("link", string.Empty),
new HttpHeader("Link", string.Empty),
/* 46 */
new HttpHeader("location", string.Empty),
new HttpHeader("Location", string.Empty),
/* 47 */
new HttpHeader("max-forwards", string.Empty),
new HttpHeader("Max-Forwards", string.Empty),
/* 48 */
new HttpHeader("proxy-authenticate", string.Empty),
new HttpHeader("Proxy-Authenticate", string.Empty),
/* 49 */
new HttpHeader("proxy-authorization", string.Empty),
new HttpHeader("Proxy-Authorization", string.Empty),
/* 50 */
new HttpHeader("range", string.Empty),
new HttpHeader("Range", string.Empty),
/* 51 */
new HttpHeader("referer", string.Empty),
new HttpHeader("Referer", string.Empty),
/* 52 */
new HttpHeader("refresh", string.Empty),
new HttpHeader("Refresh", string.Empty),
/* 53 */
new HttpHeader("retry-after", string.Empty),
new HttpHeader("Retry-After", string.Empty),
/* 54 */
new HttpHeader("server", string.Empty),
new HttpHeader("Server", string.Empty),
/* 55 */
new HttpHeader("set-cookie", string.Empty),
new HttpHeader("Set-Cookie", string.Empty),
/* 56 */
new HttpHeader("strict-transport-security", string.Empty),
new HttpHeader("Strict-Transport-Security", string.Empty),
/* 57 */
new HttpHeader("transfer-encoding", string.Empty),
new HttpHeader("Transfer-Encoding", string.Empty),
/* 58 */
new HttpHeader("user-agent", string.Empty),
new HttpHeader("User-Agent", string.Empty),
/* 59 */
new HttpHeader("vary", string.Empty),
new HttpHeader("Vary", string.Empty),
/* 60 */
new HttpHeader("via", string.Empty),
new HttpHeader("Via", string.Empty),
/* 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>
/// The number of header fields in the static table.
......@@ -180,12 +180,12 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// <param name="name">Name.</param>
public static int GetIndex(string name)
{
if (!staticIndexByName.ContainsKey(name))
if (!staticIndexByName.TryGetValue(name, out int index))
{
return -1;
}
return staticIndexByName[name];
return index;
}
/// <summary>
......@@ -207,7 +207,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
while (index <= Length)
{
var entry = Get(index);
if (!HpackUtil.Equals(name, entry.Name))
if (!name.Equals(entry.Name, StringComparison.OrdinalIgnoreCase))
{
break;
}
......@@ -227,7 +227,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
/// create a map of header name to index value to allow quick lookup
/// </summary>
/// <returns>The map.</returns>
private static Dictionary<string, int> CreateMap()
private static Dictionary<string, int> createMap()
{
int length = staticTable.Count;
var ret = new Dictionary<string, int>(length);
......@@ -237,7 +237,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
for (int index = length; index > 0; index--)
{
var entry = Get(index);
string name = entry.Name;
string name = entry.Name.ToLower();
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
#if NETCOREAPP2_1
#if NETCOREAPP2_1
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Compression;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http2.Hpack;
namespace Titanium.Web.Proxy.Http2
{
[Flags]
internal enum Http2FrameFlag
{
Ack = 0x01,
EndStream = 0x01,
EndHeaders = 0x04,
Padded = 0x08,
Priority = 0x20,
}
internal class Http2Helper
{
/// <summary>
/// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers
/// as prefix
/// Usefull for websocket requests
/// Useful for websocket requests
/// Task-based Asynchronous Pattern
/// </summary>
/// <param name="clientStream"></param>
/// <param name="serverStream"></param>
/// <param name="bufferSize"></param>
/// <param name="onDataSend"></param>
/// <param name="onDataReceive"></param>
/// <param name="cancellationTokenSource"></param>
/// <param name="connectionId"></param>
/// <param name="exceptionFunc"></param>
/// <returns></returns>
internal static async Task SendHttp2(Stream clientStream, Stream serverStream, int bufferSize,
Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive,
Func<SessionEventArgs> sessionFactory,
Func<SessionEventArgs, Task> onBeforeRequest, Func<SessionEventArgs, Task> onBeforeResponse,
CancellationTokenSource cancellationTokenSource, Guid connectionId,
ExceptionHandler exceptionFunc)
{
var clientSettings = new Http2Settings();
var serverSettings = new Http2Settings();
var sessions = new ConcurrentDictionary<int, SessionEventArgs>();
// Now async relay all server=>client & client=>server data
var sendRelay =
CopyHttp2FrameAsync(clientStream, serverStream, onDataSend, bufferSize, connectionId,
true, cancellationTokenSource.Token);
copyHttp2FrameAsync(clientStream, serverStream, onDataSend, clientSettings, serverSettings,
sessionFactory, sessions, onBeforeRequest,
bufferSize, connectionId, true, cancellationTokenSource.Token, exceptionFunc);
var receiveRelay =
CopyHttp2FrameAsync(serverStream, clientStream, onDataReceive, bufferSize, connectionId,
false, cancellationTokenSource.Token);
copyHttp2FrameAsync(serverStream, clientStream, onDataReceive, serverSettings, clientSettings,
sessionFactory, sessions, onBeforeResponse,
bufferSize, connectionId, false, cancellationTokenSource.Token, exceptionFunc);
await Task.WhenAny(sendRelay, receiveRelay);
cancellationTokenSource.Cancel();
......@@ -53,77 +52,366 @@ namespace Titanium.Web.Proxy.Http2
await Task.WhenAll(sendRelay, receiveRelay);
}
private static async Task CopyHttp2FrameAsync(Stream input, Stream output, Action<byte[], int, int> onCopy,
int bufferSize, Guid connectionId, bool isClient, CancellationToken cancellationToken)
private static async Task copyHttp2FrameAsync(Stream input, Stream output, Action<byte[], int, int> onCopy,
Http2Settings localSettings, Http2Settings remoteSettings,
Func<SessionEventArgs> sessionFactory, ConcurrentDictionary<int, SessionEventArgs> sessions,
Func<SessionEventArgs, Task> onBeforeRequestResponse,
int bufferSize, Guid connectionId, bool isClient, CancellationToken cancellationToken,
ExceptionHandler exceptionFunc)
{
var decoder = new Decoder(8192, 4096);
int headerTableSize = 0;
Decoder decoder = null;
var headerBuffer = new byte[9];
var buffer = new byte[32768];
var frameHeader = new Http2FrameHeader();
frameHeader.Buffer = new byte[9];
byte[] buffer = null;
while (true)
{
int read = await ForceRead(input, headerBuffer, 0, 9, cancellationToken);
var frameHeaderBuffer = frameHeader.Buffer;
int read = await forceRead(input, frameHeaderBuffer, 0, 9, cancellationToken);
onCopy(frameHeaderBuffer, 0, read);
if (read != 9)
{
return;
}
int length = (headerBuffer[0] << 16) + (headerBuffer[1] << 8) + headerBuffer[2];
byte type = headerBuffer[3];
byte flags = headerBuffer[4];
int streamId = ((headerBuffer[5] & 0x7f) << 24) + (headerBuffer[6] << 16) + (headerBuffer[7] << 8) +
headerBuffer[8];
int length = (frameHeaderBuffer[0] << 16) + (frameHeaderBuffer[1] << 8) + frameHeaderBuffer[2];
var type = (Http2FrameType)frameHeaderBuffer[3];
var flags = (Http2FrameFlag)frameHeaderBuffer[4];
int streamId = ((frameHeaderBuffer[5] & 0x7f) << 24) + (frameHeaderBuffer[6] << 16) +
(frameHeaderBuffer[7] << 8) + frameHeaderBuffer[8];
frameHeader.Length = length;
frameHeader.Type = type;
frameHeader.Flags = flags;
frameHeader.StreamId = streamId;
read = await ForceRead(input, buffer, 0, length, cancellationToken);
if (buffer == null || buffer.Length < localSettings.MaxFrameSize)
{
buffer = new byte[localSettings.MaxFrameSize];
}
read = await forceRead(input, buffer, 0, length, cancellationToken);
onCopy(buffer, 0, read);
if (read != length)
{
return;
}
if (isClient)
bool sendPacket = true;
bool endStream = false;
SessionEventArgs args = null;
RequestResponseBase rr = null;
if (type == Http2FrameType.Data || type == Http2FrameType.Headers/* || type == Http2FrameType.PushPromise*/)
{
if (!sessions.TryGetValue(streamId, out args))
{
//if (type == Http2FrameType.Data)
//{
// throw new ProxyHttpException("HTTP Body data received before any header frame.", null, args);
//}
//if (type == Http2FrameType.Headers && !isClient)
//{
// throw new ProxyHttpException("HTTP Response received before any Request header frame.", null, args);
//}
if (type == Http2FrameType.PushPromise && isClient)
{
throw new ProxyHttpException("HTTP Push promise received from the client.", null, args);
}
}
}
//System.Diagnostics.Debug.WriteLine("CONN: " + connectionId + ", CLIENT: " + isClient + ", STREAM: " + streamId + ", TYPE: " + type);
if (type == Http2FrameType.Data && args != null)
{
rr = isClient ? (RequestResponseBase)args.HttpClient.Request : args.HttpClient.Response;
bool padded = (flags & Http2FrameFlag.Padded) != 0;
bool endStreamFlag = (flags & Http2FrameFlag.EndStream) != 0;
if (endStreamFlag)
{
endStream = true;
}
if (rr.Http2IgnoreBodyFrames)
{
if (type == 1 /*headers*/)
sendPacket = false;
}
if (rr.ReadHttp2BodyTaskCompletionSource != null)
{
bool endHeaders = (flags & (int)Http2FrameFlag.EndHeaders) != 0;
bool padded = (flags & (int)Http2FrameFlag.Padded) != 0;
bool priority = (flags & (int)Http2FrameFlag.Priority) != 0;
// Get body method was called in the "before" event handler
System.Diagnostics.Debug.WriteLine("HEADER: " + streamId + " end: " + endHeaders);
var data = rr.Http2BodyData;
int offset = 0;
if (padded)
{
offset++;
length--;
length -= buffer[0];
}
data.Write(buffer, offset, length);
}
}
else if (type == Http2FrameType.Headers/* || type == Http2FrameType.PushPromise*/)
{
bool endHeaders = (flags & Http2FrameFlag.EndHeaders) != 0;
bool padded = (flags & Http2FrameFlag.Padded) != 0;
bool priority = (flags & Http2FrameFlag.Priority) != 0;
bool endStreamFlag = (flags & Http2FrameFlag.EndStream) != 0;
if (endStreamFlag)
{
endStream = true;
}
int offset = 0;
if (padded)
{
offset = 1;
breakpoint();
}
if (type == Http2FrameType.PushPromise)
{
int promisedStreamId = (buffer[offset++] << 24) + (buffer[offset++] << 16) + (buffer[offset++] << 8) + buffer[offset++];
if (!sessions.TryGetValue(streamId, out args))
{
args = sessionFactory();
args.IsPromise = true;
sessions.TryAdd(streamId, args);
sessions.TryAdd(promisedStreamId, args);
}
System.Diagnostics.Debug.WriteLine("PROMISE STREAM: " + streamId + ", " + promisedStreamId +
", CONN: " + connectionId);
rr = args.HttpClient.Request;
if (isClient)
{
// push_promise from client???
breakpoint();
}
}
else
{
if (!sessions.TryGetValue(streamId, out args))
{
args = sessionFactory();
sessions.TryAdd(streamId, args);
}
rr = isClient ? (RequestResponseBase)args.HttpClient.Request : args.HttpClient.Response;
if (priority)
{
offset += 5;
var priorityData = ((long)buffer[offset++] << 32) + ((long)buffer[offset++] << 24) +
(buffer[offset++] << 16) + (buffer[offset++] << 8) + buffer[offset++];
rr.Priority = priorityData;
}
}
int dataLength = length - offset;
if (padded)
{
dataLength -= buffer[0];
}
var headerListener = new MyHeaderListener();
var headerListener = new MyHeaderListener(
(name, value) =>
{
var headers = isClient ? args.HttpClient.Request.Headers : args.HttpClient.Response.Headers;
headers.AddHeader(name, value);
});
try
{
// recreate the decoder when new value is bigger
// should we recreate when smaller, too?
if (decoder == null || headerTableSize < localSettings.HeaderTableSize)
{
headerTableSize = localSettings.HeaderTableSize;
decoder = new Decoder(8192, headerTableSize);
}
decoder.Decode(new BinaryReader(new MemoryStream(buffer, offset, dataLength)),
headerListener);
decoder.EndHeaderBlock();
if (rr is Request request)
{
request.HttpVersion = HttpVersion.Version20;
request.Method = headerListener.Method;
request.OriginalUrl = headerListener.Path;
request.RequestUri = headerListener.GetUri();
}
else
{
var response = (Response)rr;
response.HttpVersion = HttpVersion.Version20;
int.TryParse(headerListener.Status, out int statusCode);
response.StatusCode = statusCode;
}
}
catch (Exception ex)
{
exceptionFunc(new ProxyHttpException("Failed to decode HTTP/2 headers", ex, args));
}
catch (Exception)
if (!endHeaders)
{
breakpoint();
}
if (endHeaders)
{
var tcs = new TaskCompletionSource<bool>();
rr.ReadHttp2BeforeHandlerTaskCompletionSource = tcs;
var handler = onBeforeRequestResponse(args);
rr.Http2BeforeHandlerTask = handler;
if (handler == await Task.WhenAny(tcs.Task, handler))
{
rr.ReadHttp2BeforeHandlerTaskCompletionSource = null;
tcs.SetResult(true);
await sendHeader(remoteSettings, frameHeader, rr, endStream, output, args.IsPromise);
}
else
{
rr.Http2IgnoreBodyFrames = true;
}
await output.WriteAsync(headerBuffer, 0, headerBuffer.Length, cancellationToken);
await output.WriteAsync(buffer, 0, length, cancellationToken);
rr.Locked = true;
}
/*using (var fs = new System.IO.FileStream($@"c:\11\{connectionId}.{streamId}.dat", FileMode.Append))
sendPacket = false;
}
else if (type == Http2FrameType.Continuation)
{
// todo: implementing this type is mandatory for multi-part headers
breakpoint();
}
else if (type == Http2FrameType.Settings)
{
if (length % 6 != 0)
{
// https://httpwg.org/specs/rfc7540.html#SETTINGS
// 6.5. SETTINGS
// A SETTINGS frame with a length other than a multiple of 6 octets MUST be treated as a connection error (Section 5.4.1) of type FRAME_SIZE_ERROR
throw new ProxyHttpException("Invalid settings length", null, null);
}
int pos = 0;
while (pos < length)
{
int identifier = (buffer[pos++] << 8) + buffer[pos++];
int value = (buffer[pos++] << 24) + (buffer[pos++] << 16) + (buffer[pos++] << 8) + buffer[pos++];
if (identifier == 1 /*SETTINGS_HEADER_TABLE_SIZE*/)
{
//System.Diagnostics.Debug.WriteLine("HEADER SIZE CONN: " + connectionId + ", CLIENT: " + isClient + ", value: " + value);
remoteSettings.HeaderTableSize = value;
}
else if (identifier == 5 /*SETTINGS_MAX_FRAME_SIZE*/)
{
remoteSettings.MaxFrameSize = value;
}
}
}
if (type == Http2FrameType.RstStream)
{
int errorCode = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + buffer[3];
if (streamId == 0)
{
// connection error
exceptionFunc(new ProxyHttpException("HTTP/2 connection error. Error code: " + errorCode, null, args));
return;
}
else
{
// stream error
sessions.TryRemove(streamId, out _);
if (errorCode != 8 /*cancel*/)
{
exceptionFunc(new ProxyHttpException("HTTP/2 stream error. Error code: " + errorCode, null, args));
}
}
}
if (endStream && rr.ReadHttp2BodyTaskCompletionSource != null)
{
if (!rr.BodyAvailable)
{
var data = rr.Http2BodyData;
var body = data.ToArray();
if (rr.ContentEncoding != null)
{
using (var ms = new MemoryStream())
{
using (var zip =
DecompressionFactory.Create(rr.ContentEncoding, new MemoryStream(body)))
{
zip.CopyTo(ms);
}
body = ms.ToArray();
}
}
rr.Body = body;
}
rr.IsBodyRead = true;
var tcs = rr.ReadHttp2BodyTaskCompletionSource;
rr.ReadHttp2BodyTaskCompletionSource = null;
if (!tcs.Task.IsCompleted)
{
tcs.SetResult(true);
}
rr.Http2BodyData = null;
if (rr.Http2BeforeHandlerTask != null)
{
await rr.Http2BeforeHandlerTask;
}
if (args.IsPromise)
{
breakpoint();
}
await sendBody(remoteSettings, rr, frameHeader, buffer, output);
}
if (!isClient && endStream)
{
sessions.TryRemove(streamId, out _);
System.Diagnostics.Debug.WriteLine("REMOVED CONN: " + connectionId + ", CLIENT: " + isClient + ", STREAM: " + streamId + ", TYPE: " + type);
}
if (sendPacket)
{
// do not cancel the write operation
var buf = frameHeader.CopyToBuffer();
await output.WriteAsync(buf, 0, buf.Length/*, cancellationToken*/);
await output.WriteAsync(buffer, 0, length /*, cancellationToken*/);
}
if (cancellationToken.IsCancellationRequested)
{
return;
}
/*using (var fs = new System.IO.FileStream($@"c:\temp\{connectionId}.{streamId}.dat", FileMode.Append))
{
fs.Write(headerBuffer, 0, headerBuffer.Length);
fs.Write(buffer, 0, length);
......@@ -131,14 +419,112 @@ namespace Titanium.Web.Proxy.Http2
}
}
private static async Task<int> ForceRead(Stream input, byte[] buffer, int offset, int bytesToRead,
[Conditional("DEBUG")]
private static void breakpoint()
{
// when this method is called something received which is not yet implemented
;
}
private static async Task sendHeader(Http2Settings settings, Http2FrameHeader frameHeader, RequestResponseBase rr, bool endStream, Stream output, bool pushPromise)
{
var encoder = new Encoder(settings.HeaderTableSize);
var ms = new MemoryStream();
var writer = new BinaryWriter(ms);
if (rr.Priority.HasValue)
{
long p = rr.Priority.Value;
writer.Write((byte)((p >> 32) & 0xff));
writer.Write((byte)((p >> 24) & 0xff));
writer.Write((byte)((p >> 16) & 0xff));
writer.Write((byte)((p >> 8) & 0xff));
writer.Write((byte)(p & 0xff));
}
if (rr is Request request)
{
encoder.EncodeHeader(writer, ":method", request.Method);
encoder.EncodeHeader(writer, ":authority", request.RequestUri.Host);
encoder.EncodeHeader(writer, ":scheme", request.RequestUri.Scheme);
encoder.EncodeHeader(writer, ":path", request.RequestUriString, false,
HpackUtil.IndexType.None, false);
}
else
{
var response = (Response)rr;
encoder.EncodeHeader(writer, ":status", response.StatusCode.ToString());
}
foreach (var header in rr.Headers)
{
encoder.EncodeHeader(writer, header.Name.ToLower(), header.Value);
}
var data = ms.ToArray();
int newLength = data.Length;
frameHeader.Length = newLength;
frameHeader.Type = pushPromise ? Http2FrameType.PushPromise : Http2FrameType.Headers;
var flags = Http2FrameFlag.EndHeaders;
if (endStream)
{
flags |= Http2FrameFlag.EndStream;
}
if (rr.Priority.HasValue)
{
flags |= Http2FrameFlag.Priority;
}
frameHeader.Flags = flags;
// clear the padding flag
//headerBuffer[4] = (byte)(flags & ~((int)Http2FrameFlag.Padded));
// send the header
var buf = frameHeader.CopyToBuffer();
await output.WriteAsync(buf, 0, buf.Length/*, cancellationToken*/);
await output.WriteAsync(data, 0, data.Length /*, cancellationToken*/);
}
private static async Task sendBody(Http2Settings settings, RequestResponseBase rr, Http2FrameHeader frameHeader, byte[] buffer, Stream output)
{
var body = rr.CompressBodyAndUpdateContentLength();
await sendHeader(settings, frameHeader, rr, !(rr.HasBody && rr.IsBodyRead), output, false);
if (rr.HasBody && rr.IsBodyRead)
{
int pos = 0;
while (pos < body.Length)
{
int bodyFrameLength = Math.Min(buffer.Length, body.Length - pos);
Buffer.BlockCopy(body, pos, buffer, 0, bodyFrameLength);
pos += bodyFrameLength;
frameHeader.Length = bodyFrameLength;
frameHeader.Type = Http2FrameType.Data;
frameHeader.Flags = pos < body.Length ? (Http2FrameFlag)0 : Http2FrameFlag.EndStream;
var buf = frameHeader.CopyToBuffer();
await output.WriteAsync(buf, 0, buf.Length/*, cancellationToken*/);
await output.WriteAsync(buffer, 0, bodyFrameLength /*, cancellationToken*/);
}
}
else
{
;
}
}
private static async Task<int> forceRead(Stream input, byte[] buffer, int offset, int bytesToRead,
CancellationToken cancellationToken)
{
int totalRead = 0;
while (bytesToRead > 0)
{
int read = await input.ReadAsync(buffer, offset, bytesToRead, cancellationToken);
if (read == -1)
if (read == 0)
{
break;
}
......@@ -151,11 +537,69 @@ namespace Titanium.Web.Proxy.Http2
return totalRead;
}
class Http2Settings
{
public int HeaderTableSize { get; set; } = 4096;
public int MaxFrameSize { get; set; } = 16384;
}
class MyHeaderListener : IHeaderListener
{
private readonly Action<string, string> addHeaderFunc;
public string Method { get; private set; }
public string Status { get; private set; }
private string authority;
private string scheme;
public string Path { get; private set; }
public MyHeaderListener(Action<string, string> addHeaderFunc)
{
this.addHeaderFunc = addHeaderFunc;
}
public void AddHeader(string name, string value, bool sensitive)
{
Console.WriteLine(name + ": " + value + " " + sensitive);
if (name[0] == ':')
{
switch (name)
{
case ":method":
Method = value;
return;
case ":authority":
authority = value;
return;
case ":scheme":
scheme = value;
return;
case ":path":
Path = value;
return;
case ":status":
Status = value;
return;
}
}
addHeaderFunc(name, value);
}
public Uri GetUri()
{
if (authority == null)
{
// todo
authority = "abc.abc";
}
return new Uri(scheme + "://" + authority + Path);
}
}
}
......
......@@ -31,7 +31,7 @@ namespace Titanium.Web.Proxy.Models
/// Intercept tunnel connect request.
/// Valid only for explicit endpoints.
/// 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>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectRequest;
......@@ -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)
{
if (BeforeTunnelConnectResponse != null)
......
......@@ -70,7 +70,7 @@ namespace Titanium.Web.Proxy.Models
public int Port { get; set; }
/// <summary>
/// Get cache key for Tcp connection cahe.
/// Get cache key for Tcp connection cache.
/// </summary>
/// <returns></returns>
internal string GetCacheKey()
......
......@@ -35,17 +35,24 @@ namespace Titanium.Web.Proxy.Models
{
if (string.IsNullOrEmpty(name))
{
throw new Exception("Name cannot be null");
throw new Exception("Name cannot be null or empty");
}
Name = name.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>
/// Header Name.
/// </summary>
public string Name { get; set; }
public string Name { get; }
/// <summary>
/// Header Value.
......
......@@ -143,8 +143,16 @@ namespace Titanium.Web.Proxy.Network.Certificate
#if NET45
// 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);
}
#else
var x509Certificate = withPrivateKey(certificate, rsaparams);
#endif
......
using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
......@@ -49,7 +49,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary>
/// 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.
/// </summary>
private readonly ConcurrentDictionary<string, Task<X509Certificate2>> pendingCertificateCreationTasks
......@@ -149,7 +149,7 @@ namespace Titanium.Web.Proxy.Network
set
{
// For Mono (or Non-Windows) only Bouncy Castle is supported
if (!RunTime.IsWindows || RunTime.IsRunningOnMono)
if (!RunTime.IsWindows)
{
value = CertificateEngine.BouncyCastle;
}
......@@ -662,7 +662,7 @@ namespace Titanium.Web.Proxy.Network
/// <returns>True if success.</returns>
public bool TrustRootCertificateAsAdmin(bool machineTrusted = false)
{
if (!RunTime.IsWindows || RunTime.IsRunningOnMono)
if (!RunTime.IsWindows)
{
return false;
}
......@@ -805,7 +805,7 @@ namespace Titanium.Web.Proxy.Network
/// <returns>Should also remove from machine store?</returns>
public bool RemoveTrustedRootCertificateAsAdmin(bool machineTrusted = false)
{
if (!RunTime.IsWindows || RunTime.IsRunningOnMono)
if (!RunTime.IsWindows)
{
return false;
}
......
#if DEBUG

using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
#if DEBUG
using System;
using System.IO;
using System.Text;
using System.Threading;
using StreamExtended;
using StreamExtended.Network;
namespace Titanium.Web.Proxy.Network
{
......
......@@ -59,6 +59,12 @@ namespace Titanium.Web.Proxy.Network
private X509Certificate2 loadCertificate(string path, string password, X509KeyStorageFlags storageFlags)
{
byte[] exported;
if (!File.Exists(path))
{
return null;
}
try
{
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.StreamExtended.Network;
namespace Titanium.Web.Proxy.Network
{
......
......@@ -7,6 +7,8 @@ using System.Net.Security;
using System.Net.Sockets;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Network.Tcp
{
......@@ -34,11 +36,42 @@ namespace Titanium.Web.Proxy.Network.Tcp
private readonly TcpClient tcpClient;
private int? processId;
public Stream 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>
/// Dispose.
/// </summary>
......
......@@ -8,12 +8,12 @@ using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Network.Tcp
{
......@@ -38,11 +38,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
internal TcpConnectionFactory(ProxyServer server)
{
this.server = server;
this.Server = server;
Task.Run(async () => await clearOutdatedConnections());
}
internal ProxyServer server { get; set; }
internal ProxyServer Server { get; }
internal string GetConnectionCacheKey(string remoteHostName, int remotePort,
bool isHttps, List<SslApplicationProtocol> applicationProtocols,
......@@ -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
//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.
var cacheKeyBuilder = new StringBuilder($"{remoteHostName}-{remotePort}-" +
//when creating Tcp client isConnect won't matter
......@@ -232,7 +232,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
CancellationToken cancellationToken)
{
//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))
{
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
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))
{
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
NoDelay = proxyServer.NoDelay,
ReceiveTimeout = proxyServer.ConnectionTimeOutSeconds * 1000,
SendTimeout = proxyServer.ConnectionTimeOutSeconds * 1000,
SendBufferSize = proxyServer.BufferSize,
ReceiveBufferSize = proxyServer.BufferSize,
LingerState = new LingerOption(true, proxyServer.TcpTimeWaitSeconds)
};
//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);
}
......@@ -418,7 +416,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
return;
}
if (close || connection.IsWinAuthenticated || !server.EnableConnectionPool)
if (close || connection.IsWinAuthenticated || !Server.EnableConnectionPool || connection.IsClosed)
{
disposalBag.Add(connection);
return;
......@@ -434,7 +432,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
if (cache.TryGetValue(connection.CacheKey, out var existingConnections))
{
while (existingConnections.Count >= server.MaxCachedConnections)
while (existingConnections.Count >= Server.MaxCachedConnections)
{
if (existingConnections.TryDequeue(out var staleConnection))
{
......@@ -491,19 +489,20 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
if (queue.TryDequeue(out var connection))
{
var cutOff = DateTime.Now.AddSeconds(-1 * server.ConnectionTimeOutSeconds);
if (!server.EnableConnectionPool
var cutOff = DateTime.Now.AddSeconds(-1 * Server.ConnectionTimeOutSeconds);
if (!Server.EnableConnectionPool
|| connection.LastAccess < cutOff)
{
disposalBag.Add(connection);
continue;
}
else
{
queue.Enqueue(connection);
break;
}
}
}
}
try
{
......@@ -531,7 +530,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
}
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
{
......
......@@ -5,10 +5,10 @@ using System.Net.Security;
#endif
using System.Net.Sockets;
using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.Network.Tcp
{
......@@ -27,6 +27,8 @@ namespace Titanium.Web.Proxy.Network.Tcp
private ProxyServer proxyServer { get; }
internal bool IsClosed => Stream.IsClosed;
internal ExternalProxy UpStreamProxy { get; set; }
internal string HostName { get; set; }
......
//
//
// Mono.Security.BitConverterLE.cs
// Like System.BitConverter but always little endian
//
......
......@@ -11,7 +11,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Titanium.Web.Proxy")]
[assembly: AssemblyCopyright("Copyright Titanium 2015-2017")]
[assembly: AssemblyCopyright("Copyright Titanium 2015-2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: InternalsVisibleTo("Titanium.Web.Proxy.UnitTests, PublicKey=" +
......
......@@ -7,8 +7,6 @@ using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
......@@ -16,6 +14,8 @@ using Titanium.Web.Proxy.Helpers.WinHttp;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy
{
......@@ -57,6 +57,7 @@ namespace Titanium.Web.Proxy
/// </summary>
private WinHttpWebProxyFinder systemProxyResolver;
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of ProxyServer class with provided parameters.
......@@ -102,7 +103,7 @@ namespace Titanium.Web.Proxy
ProxyEndPoints = new List<ProxyEndPoint>();
tcpConnectionFactory = new TcpConnectionFactory(this);
if (!RunTime.IsRunningOnMono && RunTime.IsWindows && !RunTime.IsUwpOnWindows)
if (RunTime.IsWindows && !RunTime.IsUwpOnWindows)
{
systemProxySettingsManager = new SystemProxyManager();
}
......@@ -145,7 +146,15 @@ namespace Titanium.Web.Proxy
public bool EnableWinAuth { get; set; }
/// <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.
/// </summary>
public X509RevocationMode CheckCertificateRevocation { get; set; }
......@@ -168,7 +177,7 @@ namespace Titanium.Web.Proxy
/// When enabled, as soon as we receive a client connection we concurrently initiate
/// corresponding server connection process using CONNECT hostname or SNI hostname on a separate task so that after parsing client request
/// we will have the server connection immediately ready or in the process of getting ready.
/// If a server connection is available in cache then this prefetch task will 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.
/// </summary>
public bool EnableTcpServerConnectionPrefetch { get; set; } = true;
......@@ -352,6 +361,11 @@ namespace Titanium.Web.Proxy
/// </summary>
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>
/// Add a proxy end point.
/// </summary>
......@@ -374,7 +388,7 @@ namespace Titanium.Web.Proxy
/// <summary>
/// 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>
/// <param name="endPoint">The existing endpoint to remove.</param>
public void RemoveEndPoint(ProxyEndPoint endPoint)
......@@ -417,9 +431,10 @@ namespace Titanium.Web.Proxy
/// <param name="protocolType">The proxy protocol type.</param>
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);
......@@ -510,9 +525,10 @@ namespace Titanium.Web.Proxy
/// </summary>
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);
......@@ -523,9 +539,10 @@ namespace Titanium.Web.Proxy
/// </summary>
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();
......@@ -541,6 +558,8 @@ namespace Titanium.Web.Proxy
throw new Exception("Proxy is already running.");
}
setThreadPoolMinThread(ThreadPoolWorkerThread);
if (ProxyEndPoints.OfType<ExplicitProxyEndPoint>().Any(x => x.GenericCertificate == null))
{
CertificateManager.EnsureRootCertificate();
......@@ -599,7 +618,7 @@ namespace Titanium.Web.Proxy
throw new Exception("Proxy is not running.");
}
if (!RunTime.IsRunningOnMono && RunTime.IsWindows && !RunTime.IsUwpOnWindows)
if (RunTime.IsWindows && !RunTime.IsUwpOnWindows)
{
bool setAsSystemProxy = ProxyEndPoints.OfType<ExplicitProxyEndPoint>()
.Any(x => x.IsSystemHttpProxy || x.IsSystemHttpsProxy);
......@@ -632,7 +651,7 @@ namespace Titanium.Web.Proxy
endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port);
//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);
}
......@@ -718,13 +737,32 @@ namespace Titanium.Web.Proxy
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.
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>
/// Handle the client.
/// </summary>
......@@ -735,8 +773,7 @@ namespace Titanium.Web.Proxy
{
tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000;
tcpClient.SendTimeout = ConnectionTimeOutSeconds * 1000;
tcpClient.SendBufferSize = BufferSize;
tcpClient.ReceiveBufferSize = BufferSize;
tcpClient.LingerState = new LingerOption(true, TcpTimeWaitSeconds);
await InvokeConnectionCreateEvent(tcpClient, true);
......
......@@ -2,13 +2,13 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
#if NETCOREAPP2_1
using System.Net.Security;
#endif
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions;
......@@ -18,6 +18,7 @@ using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.Shared;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy
{
......@@ -27,7 +28,7 @@ namespace Titanium.Web.Proxy
public partial class ProxyServer
{
private bool isWindowsAuthenticationEnabledAndSupported =>
EnableWinAuth && RunTime.IsWindows && !RunTime.IsRunningOnMono;
EnableWinAuth && RunTime.IsWindows;
/// <summary>
/// This is the core request handler method for a particular connection from client.
......@@ -43,7 +44,7 @@ namespace Titanium.Web.Proxy
/// The https hostname as appeared in CONNECT request if this is a HTTPS request from
/// explicit endpoint.
/// </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>
private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientConnection clientConnection,
CustomBufferedStream clientStream, HttpResponseWriter clientStreamWriter,
......@@ -60,7 +61,7 @@ namespace Titanium.Web.Proxy
{
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)
while (true)
{
......@@ -187,9 +188,21 @@ namespace Titanium.Web.Proxy
//If prefetch task is available.
if (connection == null && prefetchTask != null)
{
try
{
connection = await prefetchTask;
}
catch (SocketException e)
{
if(e.SocketErrorCode != SocketError.HostNotFound)
{
throw;
}
}
prefetchTask = null;
}
// create a new connection if cache key changes.
......@@ -299,6 +312,8 @@ namespace Titanium.Web.Proxy
if (args.HttpClient.Request.UpgradeToWebSocket)
{
args.HttpClient.ConnectRequest.TunnelType = TunnelType.Websocket;
// if upgrading to websocket then relay the request without reading the contents
await handleWebSocketUpgrade(httpCmd, args, args.HttpClient.Request,
args.HttpClient.Response, args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamWriter,
......@@ -360,7 +375,7 @@ namespace Titanium.Web.Proxy
}
/// <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>
private void prepareRequestHeaders(HeaderCollection requestHeaders)
{
......
......@@ -14,7 +14,7 @@ namespace Titanium.Web.Proxy
public partial class ProxyServer
{
/// <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>
/// <param name="args">The session event arguments.</param>
/// <returns> The task.</returns>
......@@ -92,7 +92,7 @@ namespace Titanium.Web.Proxy
// clear current response
await args.ClearResponse(cancellationToken);
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,
cancellationToken, args.CancellationTokenSource);
return;
......@@ -125,7 +125,6 @@ namespace Titanium.Web.Proxy
}
args.TimeLine["Response Sent"] = DateTime.Now;
}
/// <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);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Titanium.Web.Proxy.StreamExtended.Models;
namespace Titanium.Web.Proxy.StreamExtended
{
/// <summary>
/// Wraps up the client SSL hello information.
/// </summary>
public class ClientHelloInfo
{
private static readonly string[] compressions = {
"null",
"DEFLATE"
};
public int HandshakeVersion { get; set; }
public int MajorVersion { get; set; }
public int MinorVersion { get; set; }
public byte[] Random { get; set; }
public DateTime Time
{
get
{
DateTime time = DateTime.MinValue;
if (Random.Length > 3)
{
time = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)
.AddSeconds(((uint)Random[3] << 24) + ((uint)Random[2] << 16) + ((uint)Random[1] << 8) + (uint)Random[0]).ToLocalTime();
}
return time;
}
}
public byte[] SessionId { get; set; }
public int[] Ciphers { get; set; }
public byte[] CompressionData { get; set; }
internal int ClientHelloLength { get; set; }
internal int EntensionsStartPosition { get; set; }
public Dictionary<string, SslExtension> Extensions { get; set; }
private static string SslVersionToString(int major, int minor)
{
string str = "Unknown";
if (major == 3 && minor == 3)
str = "TLS/1.2";
else if (major == 3 && minor == 2)
str = "TLS/1.1";
else if (major == 3 && minor == 1)
str = "TLS/1.0";
else if (major == 3 && minor == 0)
str = "SSL/3.0";
else if (major == 2 && minor == 0)
str = "SSL/2.0";
return $"{major}.{minor} ({str})";
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine($"A SSLv{HandshakeVersion}-compatible ClientHello handshake was found. Titanium extracted the parameters below.");
sb.AppendLine();
sb.AppendLine($"Version: {SslVersionToString(MajorVersion, MinorVersion)}");
sb.AppendLine($"Random: {string.Join(" ", Random.Select(x => x.ToString("X2")))}");
sb.AppendLine($"\"Time\": {Time}");
sb.AppendLine($"SessionID: {string.Join(" ", SessionId.Select(x => x.ToString("X2")))}");
if (Extensions != null)
{
sb.AppendLine("Extensions:");
foreach (var extension in Extensions.Values.OrderBy(x => x.Position))
{
sb.AppendLine($"{extension.Name}: {extension.Data}");
}
}
if (CompressionData != null && CompressionData.Length > 0)
{
int compressionMethod = CompressionData[0];
string compression = compressions.Length > compressionMethod
? compressions[compressionMethod]
: $"unknown [0x{compressionMethod:X2}]";
sb.AppendLine($"Compression: {compression}");
}
if (Ciphers.Length > 0)
{
sb.AppendLine("Ciphers:");
foreach (int cipherSuite in Ciphers)
{
if (!SslCiphers.Ciphers.TryGetValue(cipherSuite, out string cipherStr))
{
cipherStr = "unknown";
}
sb.AppendLine($"[0x{cipherSuite:X4}] {cipherStr}");
}
}
return sb.ToString();
}
}
}
\ No newline at end of file
using System.Collections.Generic;
namespace Titanium.Web.Proxy.StreamExtended.Models
{
internal static class SslCiphers
{
internal static readonly Dictionary<int, string> Ciphers = new Dictionary<int, string>
{
{ 0x0000, "TLS_NULL_WITH_NULL_NULL" },
{ 0x0001, "TLS_RSA_WITH_NULL_MD5" },
{ 0x0002, "TLS_RSA_WITH_NULL_SHA" },
{ 0x0003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5" },
{ 0x0004, "TLS_RSA_WITH_RC4_128_MD5" },
{ 0x0005, "TLS_RSA_WITH_RC4_128_SHA" },
{ 0x0006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5" },
{ 0x0007, "TLS_RSA_WITH_IDEA_CBC_SHA" },
{ 0x0008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA" },
{ 0x0009, "TLS_RSA_WITH_DES_CBC_SHA" },
{ 0x000A, "TLS_RSA_WITH_3DES_EDE_CBC_SHA" },
{ 0x000B, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA" },
{ 0x000C, "TLS_DH_DSS_WITH_DES_CBC_SHA" },
{ 0x000D, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA" },
{ 0x000E, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA" },
{ 0x000F, "TLS_DH_RSA_WITH_DES_CBC_SHA" },
{ 0x0010, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA" },
{ 0x0011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" },
{ 0x0012, "TLS_DHE_DSS_WITH_DES_CBC_SHA" },
{ 0x0013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA" },
{ 0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA" },
{ 0x0015, "TLS_DHE_RSA_WITH_DES_CBC_SHA" },
{ 0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA" },
{ 0x0017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5" },
{ 0x0018, "TLS_DH_anon_WITH_RC4_128_MD5" },
{ 0x0019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA" },
{ 0x001A, "TLS_DH_anon_WITH_DES_CBC_SHA" },
{ 0x001B, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA" },
{ 0x001C, "SSL_FORTEZZA_KEA_WITH_NULL_SHA" },
{ 0x001D, "SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA" },
//{ 0x001E, "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA" },
// RFC 2712
{ 0x001E, "TLS_KRB5_WITH_DES_CBC_SHA" },
{ 0x001F, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA" },
{ 0x0020, "TLS_KRB5_WITH_RC4_128_SHA" },
{ 0x0021, "TLS_KRB5_WITH_IDEA_CBC_SHA" },
{ 0x0022, "TLS_KRB5_WITH_DES_CBC_MD5" },
{ 0x0023, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5" },
{ 0x0024, "TLS_KRB5_WITH_RC4_128_MD5" },
{ 0x0025, "TLS_KRB5_WITH_IDEA_CBC_MD5" },
{ 0x0026, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA" },
{ 0x0027, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA" },
{ 0x0028, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA" },
{ 0x0029, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5" },
{ 0x002A, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5" },
{ 0x002B, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5" },
// RFC 4785
{ 0x002C, "TLS_PSK_WITH_NULL_SHA" },
{ 0x002D, "TLS_DHE_PSK_WITH_NULL_SHA" },
{ 0x002E, "TLS_RSA_PSK_WITH_NULL_SHA" },
// RFC 5246
{ 0x002F, "TLS_RSA_WITH_AES_128_CBC_SHA" },
{ 0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA" },
{ 0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA" },
{ 0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA" },
{ 0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" },
{ 0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA" },
{ 0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA" },
{ 0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA" },
{ 0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA" },
{ 0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA" },
{ 0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" },
{ 0x003A, "TLS_DH_anon_WITH_AES_256_CBC_SHA" },
{ 0x003B, "TLS_RSA_WITH_NULL_SHA256" },
{ 0x003C, "TLS_RSA_WITH_AES_128_CBC_SHA256" },
{ 0x003D, "TLS_RSA_WITH_AES_256_CBC_SHA256" },
{ 0x003E, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256" },
{ 0x003F, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256" },
{ 0x0040, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256" },
{ 0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA" },
{ 0x0042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA" },
{ 0x0043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA" },
{ 0x0044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA" },
{ 0x0045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA" },
{ 0x0046, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA" },
{ 0x0047, "TLS_ECDH_ECDSA_WITH_NULL_SHA" },
{ 0x0048, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA" },
{ 0x0049, "TLS_ECDH_ECDSA_WITH_DES_CBC_SHA" },
{ 0x004A, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA" },
{ 0x004B, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA" },
{ 0x004C, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA" },
{ 0x0060, "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5" },
{ 0x0061, "TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5" },
{ 0x0062, "TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA" },
{ 0x0063, "TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA" },
{ 0x0064, "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA" },
{ 0x0065, "TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA" },
{ 0x0066, "TLS_DHE_DSS_WITH_RC4_128_SHA" },
{ 0x0067, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" },
{ 0x0068, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256" },
{ 0x0069, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256" },
{ 0x006A, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256" },
{ 0x006B, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" },
{ 0x006C, "TLS_DH_anon_WITH_AES_128_CBC_SHA256" },
{ 0x006D, "TLS_DH_anon_WITH_AES_256_CBC_SHA256" },
{ 0x0084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA" },
{ 0x0085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA" },
{ 0x0086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA" },
{ 0x0087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA" },
{ 0x0088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA" },
{ 0x0089, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA" },
// RFC 4279
{ 0x008A, "TLS_PSK_WITH_RC4_128_SHA" },
{ 0x008B, "TLS_PSK_WITH_3DES_EDE_CBC_SHA" },
{ 0x008C, "TLS_PSK_WITH_AES_128_CBC_SHA" },
{ 0x008D, "TLS_PSK_WITH_AES_256_CBC_SHA" },
{ 0x008E, "TLS_DHE_PSK_WITH_RC4_128_SHA" },
{ 0x008F, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA" },
{ 0x0090, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA" },
{ 0x0091, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA" },
{ 0x0092, "TLS_RSA_PSK_WITH_RC4_128_SHA" },
{ 0x0093, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA" },
{ 0x0094, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA" },
{ 0x0095, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA" },
// RFC 4162
{ 0x0096, "TLS_RSA_WITH_SEED_CBC_SHA" },
{ 0x0097, "TLS_DH_DSS_WITH_SEED_CBC_SHA" },
{ 0x0098, "TLS_DH_RSA_WITH_SEED_CBC_SHA" },
{ 0x0099, "TLS_DHE_DSS_WITH_SEED_CBC_SHA" },
{ 0x009A, "TLS_DHE_RSA_WITH_SEED_CBC_SHA" },
{ 0x009B, "TLS_DH_anon_WITH_SEED_CBC_SHA" },
// RFC 5288
{ 0x009C, "TLS_RSA_WITH_AES_128_GCM_SHA256" },
{ 0x009D, "TLS_RSA_WITH_AES_256_GCM_SHA384" },
{ 0x009E, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256" },
{ 0x009F, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384" },
{ 0x00A0, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256" },
{ 0x00A1, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384" },
{ 0x00A2, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256" },
{ 0x00A3, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384" },
{ 0x00A4, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256" },
{ 0x00A5, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384" },
{ 0x00A6, "TLS_DH_anon_WITH_AES_128_GCM_SHA256" },
{ 0x00A7, "TLS_DH_anon_WITH_AES_256_GCM_SHA384" },
// RFC 5487
{ 0x00A8, "TLS_PSK_WITH_AES_128_GCM_SHA256" },
{ 0x00A9, "TLS_PSK_WITH_AES_256_GCM_SHA384" },
{ 0x00AA, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256" },
{ 0x00AB, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384" },
{ 0x00AC, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256" },
{ 0x00AD, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384" },
{ 0x00AE, "TLS_PSK_WITH_AES_128_CBC_SHA256" },
{ 0x00AF, "TLS_PSK_WITH_AES_256_CBC_SHA384" },
{ 0x00B0, "TLS_PSK_WITH_NULL_SHA256" },
{ 0x00B1, "TLS_PSK_WITH_NULL_SHA384" },
{ 0x00B2, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256" },
{ 0x00B3, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384" },
{ 0x00B4, "TLS_DHE_PSK_WITH_NULL_SHA256" },
{ 0x00B5, "TLS_DHE_PSK_WITH_NULL_SHA384" },
{ 0x00B6, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256" },
{ 0x00B7, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384" },
{ 0x00B8, "TLS_RSA_PSK_WITH_NULL_SHA256" },
{ 0x00B9, "TLS_RSA_PSK_WITH_NULL_SHA384" },
// RFC 5932
{ 0x00BA, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0x00BB, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0x00BC, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0x00BD, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0x00BE, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0x00BF, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0x00C0, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256" },
{ 0x00C1, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256" },
{ 0x00C2, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256" },
{ 0x00C3, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256" },
{ 0x00C4, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256" },
{ 0x00C5, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256" },
{ 0x00FF, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" },
{ 0x5600, "TLS_FALLBACK_SCSV" },
// RFC 4492
{ 0xC001, "TLS_ECDH_ECDSA_WITH_NULL_SHA" },
{ 0xC002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA" },
{ 0xC003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA" },
{ 0xC004, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA" },
{ 0xC005, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA" },
{ 0xC006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA" },
{ 0xC007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA" },
{ 0xC008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA" },
{ 0xC009, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA" },
{ 0xC00A, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" },
{ 0xC00B, "TLS_ECDH_RSA_WITH_NULL_SHA" },
{ 0xC00C, "TLS_ECDH_RSA_WITH_RC4_128_SHA" },
{ 0xC00D, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA" },
{ 0xC00E, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA" },
{ 0xC00F, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA" },
{ 0xC010, "TLS_ECDHE_RSA_WITH_NULL_SHA" },
{ 0xC011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA" },
{ 0xC012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA" },
{ 0xC013, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" },
{ 0xC014, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" },
{ 0xC015, "TLS_ECDH_anon_WITH_NULL_SHA" },
{ 0xC016, "TLS_ECDH_anon_WITH_RC4_128_SHA" },
{ 0xC017, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA" },
{ 0xC018, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA" },
{ 0xC019, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA" },
// RFC 5054
{ 0xC01A, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA" },
{ 0xC01B, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA" },
{ 0xC01C, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA" },
{ 0xC01D, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA" },
{ 0xC01E, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA" },
{ 0xC01F, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA" },
{ 0xC020, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA" },
{ 0xC021, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA" },
{ 0xC022, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA" },
// RFC 5589
{ 0xC023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" },
{ 0xC024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" },
{ 0xC025, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256" },
{ 0xC026, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384" },
{ 0xC027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" },
{ 0xC028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" },
{ 0xC029, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256" },
{ 0xC02A, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384" },
{ 0xC02B, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" },
{ 0xC02C, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" },
{ 0xC02D, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256" },
{ 0xC02E, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384" },
{ 0xC02F, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" },
{ 0xC030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" },
{ 0xC031, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256" },
{ 0xC032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384" },
// RFC 5489
{ 0xC033, "TLS_ECDHE_PSK_WITH_RC4_128_SHA" },
{ 0xC034, "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA" },
{ 0xC035, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA" },
{ 0xC036, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA" },
{ 0xC037, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256" },
{ 0xC038, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384" },
{ 0xC039, "TLS_ECDHE_PSK_WITH_NULL_SHA" },
{ 0xC03A, "TLS_ECDHE_PSK_WITH_NULL_SHA256" },
{ 0xC03B, "TLS_ECDHE_PSK_WITH_NULL_SHA384" },
{ 0xC03C, "TLS_RSA_WITH_ARIA_128_CBC_SHA256" },
{ 0xC03D, "TLS_RSA_WITH_ARIA_256_CBC_SHA384" },
{ 0xC03E, "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256" },
{ 0xC03F, "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384" },
{ 0xC040, "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256" },
{ 0xC041, "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384" },
{ 0xC042, "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256" },
{ 0xC043, "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384" },
{ 0xC044, "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256" },
{ 0xC045, "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384" },
{ 0xC046, "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256" },
{ 0xC047, "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384" },
{ 0xC048, "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256" },
{ 0xC049, "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384" },
{ 0xC04A, "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256" },
{ 0xC04B, "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384" },
{ 0xC04C, "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256" },
{ 0xC04D, "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384" },
{ 0xC04E, "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256" },
{ 0xC04F, "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384" },
{ 0xC050, "TLS_RSA_WITH_ARIA_128_GCM_SHA256" },
{ 0xC051, "TLS_RSA_WITH_ARIA_256_GCM_SHA384" },
{ 0xC052, "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256" },
{ 0xC053, "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384" },
{ 0xC054, "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256" },
{ 0xC055, "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384" },
{ 0xC056, "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256" },
{ 0xC057, "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384" },
{ 0xC058, "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256" },
{ 0xC059, "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384" },
{ 0xC05A, "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256" },
{ 0xC05B, "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384" },
{ 0xC05C, "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256" },
{ 0xC05D, "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384" },
{ 0xC05E, "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256" },
{ 0xC05F, "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384" },
{ 0xC060, "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256" },
{ 0xC061, "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384" },
{ 0xC062, "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256" },
{ 0xC063, "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384" },
{ 0xC064, "TLS_PSK_WITH_ARIA_128_CBC_SHA256" },
{ 0xC065, "TLS_PSK_WITH_ARIA_256_CBC_SHA384" },
{ 0xC066, "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256" },
{ 0xC067, "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384" },
{ 0xC068, "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256" },
{ 0xC069, "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384" },
{ 0xC06A, "TLS_PSK_WITH_ARIA_128_GCM_SHA256" },
{ 0xC06B, "TLS_PSK_WITH_ARIA_256_GCM_SHA384" },
{ 0xC06C, "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256" },
{ 0xC06D, "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384" },
{ 0xC06E, "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256" },
{ 0xC06F, "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384" },
{ 0xC070, "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256" },
{ 0xC071, "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384" },
{ 0xC072, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0xC073, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384" },
{ 0xC074, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0xC075, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384" },
{ 0xC076, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0xC077, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384" },
{ 0xC078, "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0xC079, "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384" },
{ 0xC07A, "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC07B, "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC07C, "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC07D, "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC07E, "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC07F, "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC080, "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC081, "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC082, "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC083, "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC084, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC085, "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC086, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC087, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC088, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC089, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC08A, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC08B, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC08C, "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC08D, "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC08E, "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC08F, "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC090, "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC091, "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC092, "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256" },
{ 0xC093, "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384" },
{ 0xC094, "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0xC095, "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384" },
{ 0xC096, "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0xC097, "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384" },
{ 0xC098, "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0xC099, "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384" },
{ 0xC09A, "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256" },
{ 0xC09B, "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384" },
{ 0xC09C, "TLS_RSA_WITH_AES_128_CCM" },
{ 0xC09D, "TLS_RSA_WITH_AES_256_CCM" },
{ 0xC09E, "TLS_DHE_RSA_WITH_AES_128_CCM" },
{ 0xC09F, "TLS_DHE_RSA_WITH_AES_256_CCM" },
{ 0xC0A0, "TLS_RSA_WITH_AES_128_CCM_8" },
{ 0xC0A1, "TLS_RSA_WITH_AES_256_CCM_8" },
{ 0xC0A2, "TLS_DHE_RSA_WITH_AES_128_CCM_8" },
{ 0xC0A3, "TLS_DHE_RSA_WITH_AES_256_CCM_8" },
{ 0xC0A4, "TLS_PSK_WITH_AES_128_CCM" },
{ 0xC0A5, "TLS_PSK_WITH_AES_256_CCM" },
{ 0xC0A6, "TLS_DHE_PSK_WITH_AES_128_CCM" },
{ 0xC0A7, "TLS_DHE_PSK_WITH_AES_256_CCM" },
{ 0xC0A8, "TLS_PSK_WITH_AES_128_CCM_8" },
{ 0xC0A9, "TLS_PSK_WITH_AES_256_CCM_8" },
{ 0xC0AA, "TLS_PSK_DHE_WITH_AES_128_CCM_8" },
{ 0xC0AB, "TLS_PSK_DHE_WITH_AES_256_CCM_8" },
{ 0xC0AC, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM" },
{ 0xC0AD, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM" },
{ 0xC0AE, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8" },
{ 0xC0AF, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8" },
// old numbers used in the beginning http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305
{ 0xCC13, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
{ 0xCC14, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" },
{ 0xCC15, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
// http://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305
{ 0xCCA8, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
{ 0xCCA9, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" },
{ 0xCCAA, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
{ 0xCCAB, "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256" },
{ 0xCCAC, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256" },
{ 0xCCAD, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256" },
{ 0xCCAE, "TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256" },
// http://tools.ietf.org/html/draft-josefsson-salsa20-tls
{ 0xE410, "TLS_RSA_WITH_ESTREAM_SALSA20_SHA1" },
{ 0xE411, "TLS_RSA_WITH_SALSA20_SHA1" },
{ 0xE412, "TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1" },
{ 0xE413, "TLS_ECDHE_RSA_WITH_SALSA20_SHA1" },
{ 0xE414, "TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1" },
{ 0xE415, "TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1" },
{ 0xE416, "TLS_PSK_WITH_ESTREAM_SALSA20_SHA1" },
{ 0xE417, "TLS_PSK_WITH_SALSA20_SHA1" },
{ 0xE418, "TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1" },
{ 0xE419, "TLS_ECDHE_PSK_WITH_SALSA20_SHA1" },
{ 0xE41A, "TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1" },
{ 0xE41B, "TLS_RSA_PSK_WITH_SALSA20_SHA1" },
{ 0xE41C, "TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1" },
{ 0xE41D, "TLS_DHE_PSK_WITH_SALSA20_SHA1" },
{ 0xE41E, "TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1" },
{ 0xE41F, "TLS_DHE_RSA_WITH_SALSA20_SHA1" },
// these from http://www.mozilla.org/projects/security/pki/nss/ssl/fips-ssl-ciphersuites.html
{ 0xFEFE, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
{ 0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA" },
{ 0xFFE0, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA" },
{ 0xFFE1, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
// note that ciphersuites of {0x00????} are TLS cipher suites in
// a sslv2 client hello message; the ???? above is the two-byte
// tls cipher suite id
{ 0x010080, "SSL2_RC4_128_WITH_MD5" },
{ 0x020080, "SSL2_RC4_128_EXPORT40_WITH_MD5" },
{ 0x030080, "SSL2_RC2_128_CBC_WITH_MD5" },
{ 0x040080, "SSL2_RC2_128_CBC_EXPORT40_WITH_MD5" },
{ 0x050080, "SSL2_IDEA_128_CBC_WITH_MD5" },
{ 0x060040, "SSL2_DES_64_CBC_WITH_MD5" },
{ 0x0700C0, "SSL2_DES_192_EDE3_CBC_WITH_MD5" },
{ 0x080080, "SSL2_RC4_64_WITH_MD5" },
// Microsoft's old PCT protocol. These are from Eric Rescorla's book "SSL and TLS"
{ 0x800001, "PCT_SSL_CERT_TYPE | PCT1_CERT_X509" },
{ 0x800003, "PCT_SSL_CERT_TYPE | PCT1_CERT_X509_CHAIN" },
{ 0x810001, "PCT_SSL_HASH_TYPE | PCT1_HASH_MD5" },
{ 0x810003, "PCT_SSL_HASH_TYPE | PCT1_HASH_SHA" },
{ 0x820001, "PCT_SSL_EXCH_TYPE | PCT1_EXCH_RSA_PKCS1" },
{ 0x830004, "PCT_SSL_CIPHER_TYPE_1ST_HALF | PCT1_CIPHER_RC4" },
{ 0x842840, "PCT_SSL_CIPHER_TYPE_2ND_HALF | PCT1_ENC_BITS_40 | PCT1_MAC_BITS_128" },
{ 0x848040, "PCT_SSL_CIPHER_TYPE_2ND_HALF | PCT1_ENC_BITS_128 | PCT1_MAC_BITS_128" },
{ 0x8F8001, "PCT_SSL_COMPAT | PCT_VERSION_1" },
};
}
}
namespace Titanium.Web.Proxy.StreamExtended.Models
{
/// <summary>
/// The SSL extension information.
/// </summary>
public class SslExtension
{
/// <summary>
/// Gets the value.
/// </summary>
/// <value>
/// The value.
/// </value>
public int Value { get; }
/// <summary>
/// Gets the name.
/// </summary>
/// <value>
/// The name.
/// </value>
public string Name { get; }
/// <summary>
/// Gets the data.
/// </summary>
/// <value>
/// The data.
/// </value>
public string Data { get; }
/// <summary>
/// Gets the position.
/// </summary>
/// <value>
/// The position.
/// </value>
public int Position { get; }
/// <summary>
/// Initializes a new instance of the <see cref="SslExtension"/> class.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="name">The name.</param>
/// <param name="data">The data.</param>
/// <param name="position">The position.</param>
public SslExtension(int value, string name, string data, int position)
{
Value = value;
Name = name;
Data = data;
Position = position;
}
}
}
\ No newline at end of file
using System.Diagnostics;
using System.IO;
using System.Threading;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
public class ClientHelloAlpnAdderStream : Stream
{
private readonly CustomBufferedStream stream;
private readonly IBufferPool bufferPool;
private bool called;
public ClientHelloAlpnAdderStream(CustomBufferedStream stream, IBufferPool bufferPool)
{
this.stream = stream;
}
public override void Flush()
{
stream.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
return stream.Seek(offset, origin);
}
public override void SetLength(long value)
{
stream.SetLength(value);
}
[DebuggerStepThrough]
public override int Read(byte[] buffer, int offset, int count)
{
return stream.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
if (called)
{
stream.Write(buffer, offset, count);
return;
}
called = true;
var ms = new MemoryStream(buffer, offset, count);
//this can be non async, because reads from a memory stream
var cts = new CancellationTokenSource();
var clientHello = SslTools.PeekClientHello(new CustomBufferedStream(ms, bufferPool, (int)ms.Length), bufferPool, cts.Token).Result;
if (clientHello != null)
{
// 0x00 0x10: ALPN identifier
// 0x00 0x0e: length of ALPN data
// 0x00 0x0c: length of ALPN data again:)
var dataToAdd = new byte[]
{
0x0, 0x10, 0x0, 0xE, 0x0, 0xC,
2, (byte)'h', (byte)'2',
8, (byte)'h', (byte)'t', (byte)'t', (byte)'p', (byte)'/', (byte)'1', (byte)'.', (byte)'1'
};
int newByteCount = clientHello.Extensions == null ? dataToAdd.Length + 2 : dataToAdd.Length;
var buffer2 = new byte[buffer.Length + newByteCount];
for (int i = 0; i < buffer.Length; i++)
{
buffer2[i] = buffer[i];
}
//this is a hacky solution, but works
int length = (buffer[offset + 3] << 8) + buffer[offset + 4];
length += newByteCount;
buffer2[offset + 3] = (byte)(length >> 8);
buffer2[offset + 4] = (byte)length;
length = (buffer[offset + 6] << 16) + (buffer[offset + 7] << 8) + buffer[offset + 8];
length += newByteCount;
buffer2[offset + 6] = (byte)(length >> 16);
buffer2[offset + 7] = (byte)(length >> 8);
buffer2[offset + 8] = (byte)length;
int pos = offset + clientHello.EntensionsStartPosition;
int endPos = offset + clientHello.ClientHelloLength;
if (clientHello.Extensions != null)
{
// update ALPN length
length = (buffer[pos] << 8) + buffer[pos + 1];
length += newByteCount;
buffer2[pos] = (byte)(length >> 8);
buffer2[pos + 1] = (byte)length;
}
else
{
// add ALPN length
length = dataToAdd.Length;
buffer2[pos] = (byte)(length >> 8);
buffer2[pos + 1] = (byte)length;
endPos += 2;
}
for (int i = 0; i < dataToAdd.Length; i++)
{
buffer2[endPos + i] = dataToAdd[i];
}
// copy the reamining data if any
for (int i = clientHello.ClientHelloLength; i < count; i++)
{
buffer2[offset + newByteCount + i] = buffer[offset + i];
}
buffer = buffer2;
count += newByteCount;
}
stream.Write(buffer, offset, count);
}
public override bool CanRead => stream.CanRead;
public override bool CanSeek => stream.CanSeek;
public override bool CanWrite => stream.CanWrite;
public override long Length => stream.Length;
public override long Position
{
get => stream.Position;
set => stream.Position = value;
}
}
}
\ No newline at end of file
using System;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
/// <summary>
/// Copies the source stream to destination stream.
/// But this let users to peek and read the copying process.
/// </summary>
public class CopyStream : ICustomStreamReader, IDisposable
{
private readonly ICustomStreamReader reader;
private readonly ICustomStreamWriter writer;
private readonly IBufferPool bufferPool;
public int BufferSize { get; }
private int bufferLength;
private byte[] buffer;
private bool disposed;
public int Available => reader.Available;
public bool DataAvailable => reader.DataAvailable;
public long ReadBytes { get; private set; }
public CopyStream(ICustomStreamReader reader, ICustomStreamWriter writer, IBufferPool bufferPool, int bufferSize)
{
this.reader = reader;
this.writer = writer;
BufferSize = bufferSize;
buffer = bufferPool.GetBuffer(bufferSize);
this.bufferPool = bufferPool;
}
public async Task<bool> FillBufferAsync(CancellationToken cancellationToken = default)
{
await FlushAsync(cancellationToken);
return await reader.FillBufferAsync(cancellationToken);
}
public byte PeekByteFromBuffer(int index)
{
return reader.PeekByteFromBuffer(index);
}
public Task<int> PeekByteAsync(int index, CancellationToken cancellationToken = default)
{
return reader.PeekByteAsync(index, cancellationToken);
}
public Task<int> PeekBytesAsync(byte[] buffer, int offset, int index, int size, CancellationToken cancellationToken = default)
{
return reader.PeekBytesAsync(buffer, offset, index, size, cancellationToken);
}
public void Flush()
{
//send out the current data from from the buffer
if (bufferLength > 0)
{
writer.Write(buffer, 0, bufferLength);
bufferLength = 0;
}
}
public async Task FlushAsync(CancellationToken cancellationToken = default)
{
//send out the current data from from the buffer
if (bufferLength > 0)
{
await writer.WriteAsync(buffer, 0, bufferLength, cancellationToken);
bufferLength = 0;
}
}
public byte ReadByteFromBuffer()
{
byte b = reader.ReadByteFromBuffer();
buffer[bufferLength++] = b;
ReadBytes++;
return b;
}
public int Read(byte[] buffer, int offset, int count)
{
int result = reader.Read(buffer, offset, count);
if (result > 0)
{
if (bufferLength + result > BufferSize)
{
Flush();
}
Buffer.BlockCopy(buffer, offset, this.buffer, bufferLength, result);
bufferLength += result;
ReadBytes += result;
Flush();
}
return result;
}
public async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default)
{
int result = await reader.ReadAsync(buffer, offset, count, cancellationToken);
if (result > 0)
{
if (bufferLength + result > BufferSize)
{
await FlushAsync(cancellationToken);
}
Buffer.BlockCopy(buffer, offset, this.buffer, bufferLength, result);
bufferLength += result;
ReadBytes += result;
await FlushAsync(cancellationToken);
}
return result;
}
public Task<string> ReadLineAsync(CancellationToken cancellationToken = default)
{
return CustomBufferedStream.ReadLineInternalAsync(this, bufferPool, cancellationToken);
}
public void Dispose()
{
if (!disposed)
{
disposed = true;
var b = buffer;
buffer = null;
bufferPool.ReturnBuffer(b);
}
}
}
}
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
internal class CustomBufferedPeekStream : ICustomStreamReader
{
private readonly IBufferPool bufferPool;
private readonly ICustomStreamReader baseStream;
internal int Position { get; private set; }
internal CustomBufferedPeekStream(ICustomStreamReader baseStream, IBufferPool bufferPool, int startPosition = 0)
{
this.bufferPool = bufferPool;
this.baseStream = baseStream;
Position = startPosition;
}
int ICustomStreamReader.BufferSize => baseStream.BufferSize;
/// <summary>
/// Gets a value indicating whether data is available.
/// </summary>
bool ICustomStreamReader.DataAvailable => Available > 0;
/// <summary>
/// Gets the available data size.
/// </summary>
public int Available => baseStream.Available - Position;
internal async Task<bool> EnsureBufferLength(int length, CancellationToken cancellationToken)
{
var val = await baseStream.PeekByteAsync(Position + length - 1, cancellationToken);
return val != -1;
}
internal byte ReadByte()
{
return baseStream.PeekByteFromBuffer(Position++);
}
internal int ReadInt16()
{
int i1 = ReadByte();
int i2 = ReadByte();
return (i1 << 8) + i2;
}
internal int ReadInt24()
{
int i1 = ReadByte();
int i2 = ReadByte();
int i3 = ReadByte();
return (i1 << 16) + (i2 << 8) + i3;
}
internal byte[] ReadBytes(int length)
{
var buffer = new byte[length];
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = ReadByte();
}
return buffer;
}
/// <summary>
/// Fills the buffer asynchronous.
/// </summary>
/// <returns></returns>
Task<bool> ICustomStreamReader.FillBufferAsync(CancellationToken cancellationToken)
{
return baseStream.FillBufferAsync(cancellationToken);
}
/// <summary>
/// Peeks a byte from buffer.
/// </summary>
/// <param name="index">The index.</param>
/// <returns></returns>
byte ICustomStreamReader.PeekByteFromBuffer(int index)
{
return baseStream.PeekByteFromBuffer(index);
}
/// <summary>
/// Peeks bytes asynchronous.
/// </summary>
/// <param name="buffer">The buffer to copy.</param>
/// <param name="offset">The offset where copying.</param>
/// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
Task<int> ICustomStreamReader.PeekBytesAsync(byte[] buffer, int offset, int index, int size, CancellationToken cancellationToken)
{
return baseStream.PeekBytesAsync(buffer, offset, index, size, cancellationToken);
}
/// <summary>
/// Peeks a byte asynchronous.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
Task<int> ICustomStreamReader.PeekByteAsync(int index, CancellationToken cancellationToken)
{
return baseStream.PeekByteAsync(index, cancellationToken);
}
/// <summary>
/// Reads a byte from buffer.
/// </summary>
/// <returns></returns>
/// <exception cref="Exception">Buffer is empty</exception>
byte ICustomStreamReader.ReadByteFromBuffer()
{
return ReadByte();
}
int ICustomStreamReader.Read(byte[] buffer, int offset, int count)
{
return baseStream.Read(buffer, offset, count);
}
/// <summary>
/// Reads the asynchronous.
/// </summary>
/// <param name="buffer">The buffer.</param>
/// <param name="offset">The offset.</param>
/// <param name="count">The count.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
Task<int> ICustomStreamReader.ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return baseStream.ReadAsync(buffer, offset, count, cancellationToken);
}
/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<string> ICustomStreamReader.ReadLineAsync(CancellationToken cancellationToken)
{
return CustomBufferedStream.ReadLineInternalAsync(this, bufferPool, cancellationToken);
}
}
}
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
/// <summary>
/// A custom network stream inherited from stream
/// with an underlying read buffer supporting both read/write
/// of UTF-8 encoded string or raw bytes asynchronously from last read position.
/// </summary>
/// <seealso cref="System.IO.Stream" />
public class CustomBufferedStream : Stream, ICustomStreamReader
{
private readonly Stream baseStream;
private readonly bool leaveOpen;
private byte[] streamBuffer;
// default to UTF-8
private static readonly Encoding encoding = Encoding.UTF8;
private int bufferLength;
private int bufferPos;
private bool disposed;
private bool closed;
private readonly IBufferPool bufferPool;
public int BufferSize { get; }
public event EventHandler<DataEventArgs> DataRead;
public event EventHandler<DataEventArgs> DataWrite;
public bool IsClosed => closed;
/// <summary>
/// Initializes a new instance of the <see cref="CustomBufferedStream"/> class.
/// </summary>
/// <param name="baseStream">The base stream.</param>
/// <param name="bufferPool">Bufferpool.</param>
/// <param name="bufferSize">Size of the buffer.</param>
/// <param name="leaveOpen"><see langword="true" /> to leave the stream open after disposing the <see cref="T:CustomBufferedStream" /> object; otherwise, <see langword="false" />.</param>
public CustomBufferedStream(Stream baseStream, IBufferPool bufferPool, int bufferSize, bool leaveOpen = false)
{
this.baseStream = baseStream;
BufferSize = bufferSize;
this.leaveOpen = leaveOpen;
streamBuffer = bufferPool.GetBuffer(bufferSize);
this.bufferPool = bufferPool;
}
/// <summary>
/// When overridden in a derived class, clears all buffers for this stream and causes any buffered data to be written to the underlying device.
/// </summary>
public override void Flush()
{
baseStream.Flush();
}
/// <summary>
/// When overridden in a derived class, sets the position within the current stream.
/// </summary>
/// <param name="offset">A byte offset relative to the <paramref name="origin" /> parameter.</param>
/// <param name="origin">A value of type <see cref="T:System.IO.SeekOrigin" /> indicating the reference point used to obtain the new position.</param>
/// <returns>
/// The new position within the current stream.
/// </returns>
public override long Seek(long offset, SeekOrigin origin)
{
bufferLength = 0;
bufferPos = 0;
return baseStream.Seek(offset, origin);
}
/// <summary>
/// When overridden in a derived class, sets the length of the current stream.
/// </summary>
/// <param name="value">The desired length of the current stream in bytes.</param>
public override void SetLength(long value)
{
baseStream.SetLength(value);
}
/// <summary>
/// When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
/// </summary>
/// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between <paramref name="offset" /> and (<paramref name="offset" /> + <paramref name="count" /> - 1) replaced by the bytes read from the current source.</param>
/// <param name="offset">The zero-based byte offset in <paramref name="buffer" /> at which to begin storing the data read from the current stream.</param>
/// <param name="count">The maximum number of bytes to be read from the current stream.</param>
/// <returns>
/// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
/// </returns>
public override int Read(byte[] buffer, int offset, int count)
{
if (bufferLength == 0)
{
FillBuffer();
}
int available = Math.Min(bufferLength, count);
if (available > 0)
{
Buffer.BlockCopy(streamBuffer, bufferPos, buffer, offset, available);
bufferPos += available;
bufferLength -= available;
}
return available;
}
/// <summary>
/// When overridden in a derived class, writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
/// </summary>
/// <param name="buffer">An array of bytes. This method copies <paramref name="count" /> bytes from <paramref name="buffer" /> to the current stream.</param>
/// <param name="offset">The zero-based byte offset in <paramref name="buffer" /> at which to begin copying bytes to the current stream.</param>
/// <param name="count">The number of bytes to be written to the current stream.</param>
[DebuggerStepThrough]
public override void Write(byte[] buffer, int offset, int count)
{
OnDataWrite(buffer, offset, count);
baseStream.Write(buffer, offset, count);
}
/// <summary>
/// Asynchronously reads the bytes from the current stream and writes them to another stream, using a specified buffer size and cancellation token.
/// </summary>
/// <param name="destination">The stream to which the contents of the current stream will be copied.</param>
/// <param name="bufferSize">The size, in bytes, of the buffer. This value must be greater than zero. The default size is 81920.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param>
/// <returns>
/// A task that represents the asynchronous copy operation.
/// </returns>
public override async Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken = default)
{
if (bufferLength > 0)
{
await destination.WriteAsync(streamBuffer, bufferPos, bufferLength, cancellationToken);
bufferLength = 0;
}
await base.CopyToAsync(destination, bufferSize, cancellationToken);
}
/// <summary>
/// Asynchronously clears all buffers for this stream, causes any buffered data to be written to the underlying device, and monitors cancellation requests.
/// </summary>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param>
/// <returns>
/// A task that represents the asynchronous flush operation.
/// </returns>
public override Task FlushAsync(CancellationToken cancellationToken = default)
{
return baseStream.FlushAsync(cancellationToken);
}
/// <summary>
/// Asynchronously reads a sequence of bytes from the current stream,
/// advances the position within the stream by the number of bytes read,
/// and monitors cancellation requests.
/// </summary>
/// <param name="buffer">The buffer to write the data into.</param>
/// <param name="offset">The byte offset in <paramref name="buffer" /> at which
/// to begin writing data from the stream.</param>
/// <param name="count">The maximum number of bytes to read.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.
/// The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param>
/// <returns>
/// A task that represents the asynchronous read operation.
/// The value of the parameter contains the total
/// number of bytes read into the buffer.
/// The result value can be less than the number of bytes
/// requested if the number of bytes currently available is
/// less than the requested number, or it can be 0 (zero)
/// if the end of the stream has been reached.
/// </returns>
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default)
{
if (bufferLength == 0)
{
await FillBufferAsync(cancellationToken);
}
int available = Math.Min(bufferLength, count);
if (available > 0)
{
Buffer.BlockCopy(streamBuffer, bufferPos, buffer, offset, available);
bufferPos += available;
bufferLength -= available;
}
return available;
}
/// <summary>
/// Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream.
/// </summary>
/// <returns>
/// The unsigned byte cast to an Int32, or -1 if at the end of the stream.
/// </returns>
public override int ReadByte()
{
if (bufferLength == 0)
{
FillBuffer();
}
if (bufferLength == 0)
{
return -1;
}
bufferLength--;
return streamBuffer[bufferPos++];
}
/// <summary>
/// Peeks a byte asynchronous.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public async Task<int> PeekByteAsync(int index, CancellationToken cancellationToken = default)
{
if (Available <= index)
{
await FillBufferAsync(cancellationToken);
}
//When index is greater than the buffer size
if (streamBuffer.Length <= index)
{
throw new Exception("Requested Peek index exceeds the buffer size. Consider increasing the buffer size.");
}
//When index is greater than the buffer size
if (Available <= index)
{
return -1;
}
return streamBuffer[bufferPos + index];
}
/// <summary>
/// Peeks bytes asynchronous.
/// </summary>
/// <param name="buffer">The buffer to copy.</param>
/// <param name="offset">The offset where copying.</param>
/// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public async Task<int> PeekBytesAsync(byte[] buffer, int offset, int index, int size, CancellationToken cancellationToken = default)
{
if (Available <= index)
{
await FillBufferAsync(cancellationToken);
}
//When index is greater than the buffer size
if (streamBuffer.Length <= (index + size))
{
throw new Exception("Requested Peek index and size exceeds the buffer size. Consider increasing the buffer size.");
}
if (Available <= (index + size))
{
return -1;
}
Buffer.BlockCopy(streamBuffer, index, buffer, offset, size);
return size;
}
/// <summary>
/// Peeks a byte from buffer.
/// </summary>
/// <param name="index">The index.</param>
/// <returns></returns>
/// <exception cref="Exception">Index is out of buffer size</exception>
public byte PeekByteFromBuffer(int index)
{
if (bufferLength <= index)
{
throw new Exception("Index is out of buffer size");
}
return streamBuffer[bufferPos + index];
}
/// <summary>
/// Reads a byte from buffer.
/// </summary>
/// <returns></returns>
/// <exception cref="Exception">Buffer is empty</exception>
public byte ReadByteFromBuffer()
{
if (bufferLength == 0)
{
throw new Exception("Buffer is empty");
}
bufferLength--;
return streamBuffer[bufferPos++];
}
/// <summary>
/// Asynchronously writes a sequence of bytes to the current stream, advances the current position within this stream by the number of bytes written, and monitors cancellation requests.
/// </summary>
/// <param name="buffer">The buffer to write data from.</param>
/// <param name="offset">The zero-based byte offset in <paramref name="buffer" /> from which to begin copying bytes to the stream.</param>
/// <param name="count">The maximum number of bytes to write.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <see cref="P:System.Threading.CancellationToken.None" />.</param>
/// <returns>
/// A task that represents the asynchronous write operation.
/// </returns>
[DebuggerStepThrough]
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken = default)
{
OnDataWrite(buffer, offset, count);
await baseStream.WriteAsync(buffer, offset, count, cancellationToken);
}
/// <summary>
/// Writes a byte to the current position in the stream and advances the position within the stream by one byte.
/// </summary>
/// <param name="value">The byte to write to the stream.</param>
public override void WriteByte(byte value)
{
var buffer = bufferPool.GetBuffer(BufferSize);
try
{
buffer[0] = value;
OnDataWrite(buffer, 0, 1);
baseStream.Write(buffer, 0, 1);
}
finally
{
bufferPool.ReturnBuffer(buffer);
}
}
protected virtual void OnDataWrite(byte[] buffer, int offset, int count)
{
DataWrite?.Invoke(this, new DataEventArgs(buffer, offset, count));
}
protected virtual void OnDataRead(byte[] buffer, int offset, int count)
{
DataRead?.Invoke(this, new DataEventArgs(buffer, offset, count));
}
/// <summary>
/// Releases the unmanaged resources used by the <see cref="T:System.IO.Stream" /> and optionally releases the managed resources.
/// </summary>
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
protected override void Dispose(bool disposing)
{
if (!disposed)
{
disposed = true;
closed = true;
if (!leaveOpen)
{
baseStream.Dispose();
}
var buffer = streamBuffer;
streamBuffer = null;
bufferPool.ReturnBuffer(buffer);
}
}
/// <summary>
/// When overridden in a derived class, gets a value indicating whether the current stream supports reading.
/// </summary>
public override bool CanRead => baseStream.CanRead;
/// <summary>
/// When overridden in a derived class, gets a value indicating whether the current stream supports seeking.
/// </summary>
public override bool CanSeek => baseStream.CanSeek;
/// <summary>
/// When overridden in a derived class, gets a value indicating whether the current stream supports writing.
/// </summary>
public override bool CanWrite => baseStream.CanWrite;
/// <summary>
/// Gets a value that determines whether the current stream can time out.
/// </summary>
public override bool CanTimeout => baseStream.CanTimeout;
/// <summary>
/// When overridden in a derived class, gets the length in bytes of the stream.
/// </summary>
public override long Length => baseStream.Length;
/// <summary>
/// Gets a value indicating whether data is available.
/// </summary>
public bool DataAvailable => bufferLength > 0;
/// <summary>
/// Gets the available data size.
/// </summary>
public int Available => bufferLength;
/// <summary>
/// When overridden in a derived class, gets or sets the position within the current stream.
/// </summary>
public override long Position
{
get => baseStream.Position;
set => baseStream.Position = value;
}
/// <summary>
/// Gets or sets a value, in miliseconds, that determines how long the stream will attempt to read before timing out.
/// </summary>
public override int ReadTimeout
{
get => baseStream.ReadTimeout;
set => baseStream.ReadTimeout = value;
}
/// <summary>
/// Gets or sets a value, in miliseconds, that determines how long the stream will attempt to write before timing out.
/// </summary>
public override int WriteTimeout
{
get => baseStream.WriteTimeout;
set => baseStream.WriteTimeout = value;
}
/// <summary>
/// Fills the buffer.
/// </summary>
public bool FillBuffer()
{
if (closed)
{
return false;
}
if (bufferLength > 0)
{
//normally we fill the buffer only when it is empty, but sometimes we need more data
//move the remanining data to the beginning of the buffer
Buffer.BlockCopy(streamBuffer, bufferPos, streamBuffer, 0, bufferLength);
}
bufferPos = 0;
int readBytes = baseStream.Read(streamBuffer, bufferLength, streamBuffer.Length - bufferLength);
bool result = readBytes > 0;
if (result)
{
OnDataRead(streamBuffer, bufferLength, readBytes);
bufferLength += readBytes;
}
else
{
closed = true;
throw new EndOfStreamException();
}
return result;
}
/// <summary>
/// Fills the buffer asynchronous.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public async Task<bool> FillBufferAsync(CancellationToken cancellationToken = default)
{
if (closed)
{
return false;
}
if (bufferLength > 0)
{
//normally we fill the buffer only when it is empty, but sometimes we need more data
//move the remaining data to the beginning of the buffer
Buffer.BlockCopy(streamBuffer, bufferPos, streamBuffer, 0, bufferLength);
}
int bytesToRead = streamBuffer.Length - bufferLength;
if (bytesToRead == 0)
{
return false;
}
bufferPos = 0;
int readBytes = await baseStream.ReadAsync(streamBuffer, bufferLength, bytesToRead, cancellationToken);
bool result = readBytes > 0;
if (result)
{
OnDataRead(streamBuffer, bufferLength, readBytes);
bufferLength += readBytes;
}
else
{
closed = true;
throw new EndOfStreamException();
}
return result;
}
/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <returns></returns>
public Task<string> ReadLineAsync(CancellationToken cancellationToken = default)
{
return ReadLineInternalAsync(this, bufferPool, cancellationToken);
}
/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <returns></returns>
internal static async Task<string> ReadLineInternalAsync(ICustomStreamReader reader, IBufferPool bufferPool, CancellationToken cancellationToken = default)
{
byte lastChar = default;
int bufferDataLength = 0;
// try to use buffer from the buffer pool, usually it is enough
var bufferPoolBuffer = bufferPool.GetBuffer(reader.BufferSize);
var buffer = bufferPoolBuffer;
try
{
while (reader.DataAvailable || await reader.FillBufferAsync(cancellationToken))
{
byte newChar = reader.ReadByteFromBuffer();
buffer[bufferDataLength] = newChar;
//if new line
if (newChar == '\n')
{
if (lastChar == '\r')
{
return encoding.GetString(buffer, 0, bufferDataLength - 1);
}
return encoding.GetString(buffer, 0, bufferDataLength);
}
bufferDataLength++;
//store last char for new line comparison
lastChar = newChar;
if (bufferDataLength == buffer.Length)
{
ResizeBuffer(ref buffer, bufferDataLength * 2);
}
}
}
finally
{
bufferPool.ReturnBuffer(bufferPoolBuffer);
}
if (bufferDataLength == 0)
{
return null;
}
return encoding.GetString(buffer, 0, bufferDataLength);
}
/// <summary>
/// Read until the last new line, ignores the result
/// </summary>
/// <returns></returns>
public async Task ReadAndIgnoreAllLinesAsync(CancellationToken cancellationToken = default)
{
while (!string.IsNullOrEmpty(await ReadLineAsync(cancellationToken)))
{
}
}
/// <summary>
/// Increase size of buffer and copy existing content to new buffer
/// </summary>
/// <param name="buffer"></param>
/// <param name="size"></param>
private static void ResizeBuffer(ref byte[] buffer, long size)
{
var newBuffer = new byte[size];
Buffer.BlockCopy(buffer, 0, newBuffer, 0, buffer.Length);
buffer = newBuffer;
}
#if NET45 || NETSTANDARD2_0
/// <summary>
/// Base Stream.BeginRead will call this.Read and block thread (we don't want this, Network stream handles async)
/// In order to really async Reading Launch this.ReadAsync as Task will fire NetworkStream.ReadAsync
/// See Threads here :
/// https://github.com/justcoding121/Stream-Extended/pull/43
/// https://github.com/justcoding121/Titanium-Web-Proxy/issues/575
/// </summary>
/// <returns></returns>
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
var vAsyncResult = this.ReadAsync(buffer, offset, count);
vAsyncResult.ContinueWith(pAsyncResult =>
{
//use TaskExtended to pass State as AsyncObject
//callback will call EndRead (otherwise, it will block)
callback?.Invoke(new TaskResult<int>(pAsyncResult, state));
});
return vAsyncResult;
}
/// <summary>
/// override EndRead to handle async Reading (see BeginRead comment)
/// </summary>
/// <returns></returns>
public override int EndRead(IAsyncResult asyncResult)
{
return ((TaskResult<int>)asyncResult).Result;
}
/// <summary>
/// Fix the .net bug with SslStream slow WriteAsync
/// https://github.com/justcoding121/Titanium-Web-Proxy/issues/495
/// Stream.BeginWrite + Stream.BeginRead uses the same SemaphoreSlim(1)
/// That's why we need to call NetworkStream.BeginWrite only (while read is waiting SemaphoreSlim)
/// </summary>
/// <returns></returns>
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
var vAsyncResult = this.WriteAsync(buffer, offset, count);
vAsyncResult.ContinueWith(pAsyncResult =>
{
callback?.Invoke(new TaskResult(pAsyncResult, state));
});
return vAsyncResult;
}
public override void EndWrite(IAsyncResult asyncResult)
{
((TaskResult)asyncResult).GetResult();
}
#endif
}
}
using System;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
/// <summary>
/// Wraps the data sent/received event argument.
/// </summary>
public class DataEventArgs : EventArgs
{
public DataEventArgs(byte[] buffer, int offset, int count)
{
Buffer = buffer;
Offset = offset;
Count = count;
}
/// <summary>
/// The buffer with data.
/// </summary>
public byte[] Buffer { get; }
/// <summary>
/// Offset in buffer from which valid data begins.
/// </summary>
public int Offset { get; }
/// <summary>
/// Length from offset in buffer with valid data.
/// </summary>
public int Count { get; }
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
/// <summary>
/// This concrete implemetation of interface acts as the source stream for CopyStream class.
/// </summary>
public interface ICustomStreamReader
{
int BufferSize { get; }
int Available { get; }
bool DataAvailable { get; }
/// <summary>
/// Fills the buffer asynchronous.
/// </summary>
/// <returns></returns>
Task<bool> FillBufferAsync(CancellationToken cancellationToken = default);
/// <summary>
/// Peeks a byte from buffer.
/// </summary>
/// <param name="index">The index.</param>
/// <returns></returns>
/// <exception cref="Exception">Index is out of buffer size</exception>
byte PeekByteFromBuffer(int index);
/// <summary>
/// Peeks a byte asynchronous.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
Task<int> PeekByteAsync(int index, CancellationToken cancellationToken = default);
/// <summary>
/// Peeks bytes asynchronous.
/// </summary>
/// <param name="buffer">The buffer to copy.</param>
/// <param name="offset">The offset where copying.</param>
/// <param name="index">The index.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
Task<int> PeekBytesAsync(byte[] buffer, int offset, int index, int size, CancellationToken cancellationToken = default);
byte ReadByteFromBuffer();
/// <summary>
/// When overridden in a derived class, reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
/// </summary>
/// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between <paramref name="offset" /> and (<paramref name="offset" /> + <paramref name="count" /> - 1) replaced by the bytes read from the current source.</param>
/// <param name="offset">The zero-based byte offset in <paramref name="buffer" /> at which to begin storing the data read from the current stream.</param>
/// <param name="count">The maximum number of bytes to be read from the current stream.</param>
/// <returns>
/// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
/// </returns>
int Read(byte[] buffer, int offset, int count);
/// <summary>
/// Read the specified number (or less) of raw bytes from the base stream to the given buffer to the specified offset
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="bytesToRead"></param>
/// <param name="cancellationToken"></param>
/// <returns>The number of bytes read</returns>
Task<int> ReadAsync(byte[] buffer, int offset, int bytesToRead,
CancellationToken cancellationToken = default);
/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <returns></returns>
Task<string> ReadLineAsync(CancellationToken cancellationToken = default);
}
}
using System.Threading;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
/// <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
using System.Diagnostics;
using System.IO;
using System.Threading;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.StreamExtended.Network
{
public class ServerHelloAlpnAdderStream : Stream
{
private readonly IBufferPool bufferPool;
private readonly CustomBufferedStream stream;
private bool called;
public ServerHelloAlpnAdderStream(CustomBufferedStream stream, IBufferPool bufferPool)
{
this.bufferPool = bufferPool;
this.stream = stream;
}
public override void Flush()
{
stream.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
return stream.Seek(offset, origin);
}
public override void SetLength(long value)
{
stream.SetLength(value);
}
[DebuggerStepThrough]
public override int Read(byte[] buffer, int offset, int count)
{
return stream.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
if (called)
{
stream.Write(buffer, offset, count);
return;
}
called = true;
var ms = new MemoryStream(buffer, offset, count);
//this can be non async, because reads from a memory stream
var cts = new CancellationTokenSource();
var serverHello = SslTools.PeekServerHello(new CustomBufferedStream(ms, bufferPool, (int)ms.Length), bufferPool, cts.Token).Result;
if (serverHello != null)
{
// 0x00 0x10: ALPN identifier
// 0x00 0x0e: length of ALPN data
// 0x00 0x0c: length of ALPN data again:)
var dataToAdd = new byte[]
{
0x0, 0x10, 0x0, 0x5, 0x0, 0x3,
2, (byte)'h', (byte)'2'
};
int newByteCount = serverHello.Extensions == null ? dataToAdd.Length + 2 : dataToAdd.Length;
var buffer2 = new byte[buffer.Length + newByteCount];
for (int i = 0; i < buffer.Length; i++)
{
buffer2[i] = buffer[i];
}
//this is a hacky solution, but works
int length = (buffer[offset + 3] << 8) + buffer[offset + 4];
length += newByteCount;
buffer2[offset + 3] = (byte)(length >> 8);
buffer2[offset + 4] = (byte)length;
length = (buffer[offset + 6] << 16) + (buffer[offset + 7] << 8) + buffer[offset + 8];
length += newByteCount;
buffer2[offset + 6] = (byte)(length >> 16);
buffer2[offset + 7] = (byte)(length >> 8);
buffer2[offset + 8] = (byte)length;
int pos = offset + serverHello.EntensionsStartPosition;
int endPos = offset + serverHello.ServerHelloLength;
if (serverHello.Extensions != null)
{
// update ALPN length
length = (buffer[pos] << 8) + buffer[pos + 1];
length += newByteCount;
buffer2[pos] = (byte)(length >> 8);
buffer2[pos + 1] = (byte)length;
}
else
{
// add ALPN length
length = dataToAdd.Length;
buffer2[pos] = (byte)(length >> 8);
buffer2[pos + 1] = (byte)length;
endPos += 2;
}
for (int i = 0; i < dataToAdd.Length; i++)
{
buffer2[endPos + i] = dataToAdd[i];
}
// copy the reamining data if any
for (int i = serverHello.ServerHelloLength; i < count; i++)
{
buffer2[offset + newByteCount + i] = buffer[offset + i];
}
buffer = buffer2;
count += newByteCount;
}
stream.Write(buffer, offset, count);
}
public override bool CanRead => stream.CanRead;
public override bool CanSeek => stream.CanSeek;
public override bool CanWrite => stream.CanWrite;
public override long Length => stream.Length;
public override long Position
{
get => stream.Position;
set => stream.Position = value;
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Titanium.Web.Proxy.StreamExtended.Models;
namespace Titanium.Web.Proxy.StreamExtended
{
/// <summary>
/// Wraps up the server SSL hello information.
/// </summary>
public class ServerHelloInfo
{
private static readonly string[] compressions = {
"null",
"DEFLATE"
};
public int HandshakeVersion { get; set; }
public int MajorVersion { get; set; }
public int MinorVersion { get; set; }
public byte[] Random { get; set; }
public DateTime Time
{
get
{
DateTime time = DateTime.MinValue;
if (Random.Length > 3)
{
time = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)
.AddSeconds(((uint)Random[3] << 24) + ((uint)Random[2] << 16) + ((uint)Random[1] << 8) + (uint)Random[0]).ToLocalTime();
}
return time;
}
}
public byte[] SessionId { get; set; }
public int CipherSuite { get; set; }
public byte CompressionMethod { get; set; }
internal int ServerHelloLength { get; set; }
internal int EntensionsStartPosition { get; set; }
public Dictionary<string, SslExtension> Extensions { get; set; }
private static string SslVersionToString(int major, int minor)
{
string str = "Unknown";
if (major == 3 && minor == 3)
str = "TLS/1.2";
else if (major == 3 && minor == 2)
str = "TLS/1.1";
else if (major == 3 && minor == 1)
str = "TLS/1.0";
else if (major == 3 && minor == 0)
str = "SSL/3.0";
else if (major == 2 && minor == 0)
str = "SSL/2.0";
return $"{major}.{minor} ({str})";
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine($"A SSLv{HandshakeVersion}-compatible ServerHello handshake was found. Titanium extracted the parameters below.");
sb.AppendLine();
sb.AppendLine($"Version: {SslVersionToString(MajorVersion, MinorVersion)}");
sb.AppendLine($"Random: {string.Join(" ", Random.Select(x => x.ToString("X2")))}");
sb.AppendLine($"\"Time\": {Time}");
sb.AppendLine($"SessionID: {string.Join(" ", SessionId.Select(x => x.ToString("X2")))}");
if (Extensions != null)
{
sb.AppendLine("Extensions:");
foreach (var extension in Extensions.Values.OrderBy(x => x.Position))
{
sb.AppendLine($"{extension.Name}: {extension.Data}");
}
}
string compression = compressions.Length > CompressionMethod
? compressions[CompressionMethod]
: $"unknown [0x{CompressionMethod:X2}]";
sb.AppendLine($"Compression: {compression}");
sb.Append("Cipher:");
if (!SslCiphers.Ciphers.TryGetValue(CipherSuite, out string cipherStr))
{
cipherStr = "unknown";
}
sb.AppendLine($"[0x{CipherSuite:X4}] {cipherStr}");
return sb.ToString();
}
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Titanium.Web.Proxy.StreamExtended.Models;
namespace Titanium.Web.Proxy.StreamExtended
{
internal class SslExtensions
{
internal static SslExtension GetExtension(int value, byte[] data, int position)
{
string name = GetExtensionName(value);
string dataStr = GetExtensionData(value, data);
return new SslExtension(value, name, dataStr, position);
}
private static string GetExtensionData(int value, byte[] data)
{
//https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
switch (value)
{
case 0:
var stringBuilder = new StringBuilder();
int index = 2;
while (index < data.Length)
{
int nameType = data[index];
int count = (data[index + 1] << 8) + data[index + 2];
string str = Encoding.ASCII.GetString(data, index + 3, count);
if (nameType == 0)
{
stringBuilder.AppendFormat("{0}{1}", stringBuilder.Length > 1 ? "; " : string.Empty, str);
}
index += 3 + count;
}
return stringBuilder.ToString();
case 5:
if (data.Length == 5 && data[0] == 1 && data[1] == 0 && data[2] == 0 && data[3] == 0 && data[4] == 0)
{
return "OCSP - Implicit Responder";
}
return ByteArrayToString(data);
case 10:
return GetSupportedGroup(data);
case 11:
return GetEcPointFormats(data);
case 13:
return GetSignatureAlgorithms(data);
case 16:
return GetApplicationLayerProtocolNegotiation(data);
case 35655:
return $"{data.Length} bytes";
default:
return ByteArrayToString(data);
}
}
private static string GetSupportedGroup(byte[] data)
{
//https://datatracker.ietf.org/doc/draft-ietf-tls-rfc4492bis/?include_text=1
List<string> list = new List<string>();
if (data.Length < 2)
{
return string.Empty;
}
int i = 2;
while (i < data.Length - 1)
{
int namedCurve = (data[i] << 8) + data[i + 1];
switch (namedCurve)
{
case 1:
list.Add("sect163k1 [0x1]"); //deprecated
break;
case 2:
list.Add("sect163r1 [0x2]"); //deprecated
break;
case 3:
list.Add("sect163r2 [0x3]"); //deprecated
break;
case 4:
list.Add("sect193r1 [0x4]"); //deprecated
break;
case 5:
list.Add("sect193r2 [0x5]"); //deprecated
break;
case 6:
list.Add("sect233k1 [0x6]"); //deprecated
break;
case 7:
list.Add("sect233r1 [0x7]"); //deprecated
break;
case 8:
list.Add("sect239k1 [0x8]"); //deprecated
break;
case 9:
list.Add("sect283k1 [0x9]"); //deprecated
break;
case 10:
list.Add("sect283r1 [0xA]"); //deprecated
break;
case 11:
list.Add("sect409k1 [0xB]"); //deprecated
break;
case 12:
list.Add("sect409r1 [0xC]"); //deprecated
break;
case 13:
list.Add("sect571k1 [0xD]"); //deprecated
break;
case 14:
list.Add("sect571r1 [0xE]"); //deprecated
break;
case 15:
list.Add("secp160k1 [0xF]"); //deprecated
break;
case 16:
list.Add("secp160r1 [0x10]"); //deprecated
break;
case 17:
list.Add("secp160r2 [0x11]"); //deprecated
break;
case 18:
list.Add("secp192k1 [0x12]"); //deprecated
break;
case 19:
list.Add("secp192r1 [0x13]"); //deprecated
break;
case 20:
list.Add("secp224k1 [0x14]"); //deprecated
break;
case 21:
list.Add("secp224r1 [0x15]"); //deprecated
break;
case 22:
list.Add("secp256k1 [0x16]"); //deprecated
break;
case 23:
list.Add("secp256r1 [0x17]");
break;
case 24:
list.Add("secp384r1 [0x18]");
break;
case 25:
list.Add("secp521r1 [0x19]");
break;
case 26:
list.Add("brainpoolP256r1 [0x1A]");
break;
case 27:
list.Add("brainpoolP384r1 [0x1B]");
break;
case 28:
list.Add("brainpoolP512r1 [0x1C]");
break;
case 29:
list.Add("x25519 [0x1D]");
break;
case 30:
list.Add("x448 [0x1E]");
break;
case 256:
list.Add("ffdhe2048 [0x0100]");
break;
case 257:
list.Add("ffdhe3072 [0x0101]");
break;
case 258:
list.Add("ffdhe4096 [0x0102]");
break;
case 259:
list.Add("ffdhe6144 [0x0103]");
break;
case 260:
list.Add("ffdhe8192 [0x0104]");
break;
case 65281:
list.Add("arbitrary_explicit_prime_curves [0xFF01]"); //deprecated
break;
case 65282:
list.Add("arbitrary_explicit_char2_curves [0xFF02]"); //deprecated
break;
default:
list.Add($"unknown [0x{namedCurve:X4}]");
break;
}
i += 2;
}
return string.Join(", ", list.ToArray());
}
private static string GetEcPointFormats(byte[] data)
{
List<string> list = new List<string>();
if (data.Length < 1)
{
return string.Empty;
}
int i = 1;
while (i < data.Length)
{
switch (data[i])
{
case 0:
list.Add("uncompressed [0x0]");
break;
case 1:
list.Add("ansiX962_compressed_prime [0x1]");
break;
case 2:
list.Add("ansiX962_compressed_char2 [0x2]");
break;
default:
list.Add($"unknown [0x{data[i]:X2}]");
break;
}
i += 2;
}
return string.Join(", ", list.ToArray());
}
private static string GetSignatureAlgorithms(byte[] data)
{
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
int num = (data[0] << 8) + data[1];
var sb = new StringBuilder();
int index = 2;
while (index < num + 2)
{
switch (data[index])
{
case 0:
sb.Append("none");
break;
case 1:
sb.Append("md5");
break;
case 2:
sb.Append("sha1");
break;
case 3:
sb.Append("sha224");
break;
case 4:
sb.Append("sha256");
break;
case 5:
sb.Append("sha384");
break;
case 6:
sb.Append("sha512");
break;
case 8:
sb.Append("Intrinsic");
break;
default:
sb.AppendFormat("Unknown[0x{0:X2}]", data[index]);
break;
}
sb.AppendFormat("_");
switch (data[index + 1])
{
case 0:
sb.Append("anonymous");
break;
case 1:
sb.Append("rsa");
break;
case 2:
sb.Append("dsa");
break;
case 3:
sb.Append("ecdsa");
break;
case 7:
sb.Append("ed25519");
break;
case 8:
sb.Append("ed448");
break;
default:
sb.AppendFormat("Unknown[0x{0:X2}]", data[index + 1]);
break;
}
sb.AppendFormat(", ");
index += 2;
}
if (sb.Length > 1)
sb.Length -= 2;
return sb.ToString();
}
private static string GetApplicationLayerProtocolNegotiation(byte[] data)
{
List<string> stringList = new List<string>();
int index = 2;
while (index < data.Length)
{
int count = data[index];
stringList.Add(Encoding.ASCII.GetString(data, index + 1, count));
index += 1 + count;
}
return string.Join(", ", stringList.ToArray());
}
private static string GetExtensionName(int value)
{
//https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
switch (value)
{
case 0:
return "server_name";
case 1:
return "max_fragment_length";
case 2:
return "client_certificate_url";
case 3:
return "trusted_ca_keys";
case 4:
return "truncated_hmac";
case 5:
return "status_request";
case 6:
return "user_mapping";
case 7:
return "client_authz";
case 8:
return "server_authz";
case 9:
return "cert_type";
case 10:
return "supported_groups"; // renamed from "elliptic_curves" (RFC 7919 / TLS 1.3)
case 11:
return "ec_point_formats";
case 12:
return "srp";
case 13:
return "signature_algorithms";
case 14:
return "use_srtp";
case 15:
return "heartbeat";
case 16:
return "ALPN"; // application_layer_protocol_negotiation
case 17:
return "status_request_v2";
case 18:
return "signed_certificate_timestamp";
case 19:
return "client_certificate_type";
case 20:
return "server_certificate_type";
case 21:
return "padding";
case 22:
return "encrypt_then_mac";
case 23:
return "extended_master_secret";
case 24:
return "token_binding"; // TEMPORARY - registered 2016-02-04, extension registered 2017-01-12, expires 2018-02-04
case 25:
return "cached_info";
case 26:
return "quic_transports_parameters"; // Not yet assigned by IANA (QUIC-TLS Draft04)
case 35:
return "SessionTicket TLS";
// TLS 1.3 draft: https://tools.ietf.org/html/draft-ietf-tls-tls13
case 40:
return "key_share";
case 41:
return "pre_shared_key";
case 42:
return "early_data";
case 43:
return "supported_versions";
case 44:
return "cookie";
case 45:
return "psk_key_exchange_modes";
case 46:
return "ticket_early_data_info";
case 47:
return "certificate_authorities";
case 48:
return "oid_filters";
case 49:
return "post_handshake_auth";
case 2570: // 0a0a
case 6682: // 1a1a
case 10794: // 2a2a
case 14906: // 3a3a
case 19018: // 4a4a
case 23130: // 5a5a
case 27242: // 6a6a
case 31354: // 7a7a
case 35466: // 8a8a
case 39578: // 9a9a
case 43690: // aaaa
case 47802: // baba
case 51914: // caca
case 56026: // dada
case 60138: // eaea
case 64250: // fafa
return "Reserved (GREASE)";
case 13172:
return "next_protocol_negotiation";
case 30031:
return "channel_id_old"; // Google
case 30032:
return "channel_id"; // Google
case 35655:
return "draft-agl-tls-padding";
case 65281:
return "renegotiation_info";
case 65282:
return "Draft version of TLS 1.3"; // for experimentation only https://www.ietf.org/mail-archive/web/tls/current/msg20853.html
default:
return $"unknown_{value:x2}";
}
}
private static string ByteArrayToString(byte[] data)
{
return string.Join(" ", data.Select(x => x.ToString("X2")));
}
}
}
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.StreamExtended.BufferPool;
using Titanium.Web.Proxy.StreamExtended.Models;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy.StreamExtended
{
/// <summary>
/// Use this class to peek SSL client/server hello information.
/// </summary>
public class SslTools
{
/// <summary>
/// Is the given stream starts with an SSL client hello?
/// </summary>
/// <param name="stream"></param>
/// <param name="bufferPool"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<bool> IsClientHello(CustomBufferedStream stream, IBufferPool bufferPool, CancellationToken cancellationToken)
{
var clientHello = await PeekClientHello(stream, bufferPool, cancellationToken);
return clientHello != null;
}
/// <summary>
/// Peek the SSL client hello information.
/// </summary>
/// <param name="clientStream"></param>
/// <param name="bufferPool"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<ClientHelloInfo> PeekClientHello(CustomBufferedStream clientStream, IBufferPool bufferPool, CancellationToken cancellationToken = default)
{
//detects the HTTPS ClientHello message as it is described in the following url:
//https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format
int recordType = await clientStream.PeekByteAsync(0, cancellationToken);
if (recordType == -1)
{
return null;
}
if ((recordType & 0x80) == 0x80)
{
//SSL 2
var peekStream = new CustomBufferedPeekStream(clientStream, bufferPool, 1);
// length value + minimum length
if (!await peekStream.EnsureBufferLength(10, cancellationToken))
{
return null;
}
int recordLength = ((recordType & 0x7f) << 8) + peekStream.ReadByte();
if (recordLength < 9)
{
// Message body too short.
return null;
}
if (peekStream.ReadByte() != 0x01)
{
// should be ClientHello
return null;
}
int majorVersion = peekStream.ReadByte();
int minorVersion = peekStream.ReadByte();
int ciphersCount = peekStream.ReadInt16() / 3;
int sessionIdLength = peekStream.ReadInt16();
int randomLength = peekStream.ReadInt16();
if (!await peekStream.EnsureBufferLength(ciphersCount * 3 + sessionIdLength + randomLength, cancellationToken))
{
return null;
}
int[] ciphers = new int[ciphersCount];
for (int i = 0; i < ciphers.Length; i++)
{
ciphers[i] = (peekStream.ReadByte() << 16) + (peekStream.ReadByte() << 8) + peekStream.ReadByte();
}
byte[] sessionId = peekStream.ReadBytes(sessionIdLength);
byte[] random = peekStream.ReadBytes(randomLength);
var clientHelloInfo = new ClientHelloInfo
{
HandshakeVersion = 2,
MajorVersion = majorVersion,
MinorVersion = minorVersion,
Random = random,
SessionId = sessionId,
Ciphers = ciphers,
ClientHelloLength = peekStream.Position,
};
return clientHelloInfo;
}
else if (recordType == 0x16)
{
var peekStream = new CustomBufferedPeekStream(clientStream, bufferPool, 1);
//should contain at least 43 bytes
// 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length
if (!await peekStream.EnsureBufferLength(43, cancellationToken))
{
return null;
}
//SSL 3.0 or TLS 1.0, 1.1 and 1.2
int majorVersion = peekStream.ReadByte();
int minorVersion = peekStream.ReadByte();
int recordLength = peekStream.ReadInt16();
if (peekStream.ReadByte() != 0x01)
{
// should be ClientHello
return null;
}
var length = peekStream.ReadInt24();
majorVersion = peekStream.ReadByte();
minorVersion = peekStream.ReadByte();
byte[] random = peekStream.ReadBytes(32);
length = peekStream.ReadByte();
// sessionid + 2 ciphersData length
if (!await peekStream.EnsureBufferLength(length + 2, cancellationToken))
{
return null;
}
byte[] sessionId = peekStream.ReadBytes(length);
length = peekStream.ReadInt16();
// ciphersData + compressionData length
if (!await peekStream.EnsureBufferLength(length + 1, cancellationToken))
{
return null;
}
byte[] ciphersData = peekStream.ReadBytes(length);
int[] ciphers = new int[ciphersData.Length / 2];
for (int i = 0; i < ciphers.Length; i++)
{
ciphers[i] = (ciphersData[2 * i] << 8) + ciphersData[2 * i + 1];
}
length = peekStream.ReadByte();
if (length < 1)
{
return null;
}
// compressionData
if (!await peekStream.EnsureBufferLength(length, cancellationToken))
{
return null;
}
byte[] compressionData = peekStream.ReadBytes(length);
int extenstionsStartPosition = peekStream.Position;
Dictionary<string, SslExtension> extensions = null;
if(extenstionsStartPosition < recordLength + 5)
{
extensions = await ReadExtensions(majorVersion, minorVersion, peekStream, bufferPool, cancellationToken);
}
var clientHelloInfo = new ClientHelloInfo
{
HandshakeVersion = 3,
MajorVersion = majorVersion,
MinorVersion = minorVersion,
Random = random,
SessionId = sessionId,
Ciphers = ciphers,
CompressionData = compressionData,
ClientHelloLength = peekStream.Position,
EntensionsStartPosition = extenstionsStartPosition,
Extensions = extensions,
};
return clientHelloInfo;
}
return null;
}
/// <summary>
/// Is the given stream starts with an SSL client hello?
/// </summary>
/// <param name="stream"></param>
/// <param name="bufferPool"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<bool> IsServerHello(CustomBufferedStream stream, IBufferPool bufferPool, CancellationToken cancellationToken)
{
var serverHello = await PeekServerHello(stream, bufferPool, cancellationToken);
return serverHello != null;
}
/// <summary>
/// Peek the SSL client hello information.
/// </summary>
/// <param name="serverStream"></param>
/// <param name="bufferPool"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<ServerHelloInfo> PeekServerHello(CustomBufferedStream serverStream, IBufferPool bufferPool, CancellationToken cancellationToken = default)
{
//detects the HTTPS ClientHello message as it is described in the following url:
//https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format
int recordType = await serverStream.PeekByteAsync(0, cancellationToken);
if (recordType == -1)
{
return null;
}
if ((recordType & 0x80) == 0x80)
{
//SSL 2
// not tested. SSL2 is deprecated
var peekStream = new CustomBufferedPeekStream(serverStream, bufferPool, 1);
// length value + minimum length
if (!await peekStream.EnsureBufferLength(39, cancellationToken))
{
return null;
}
int recordLength = ((recordType & 0x7f) << 8) + peekStream.ReadByte();
if (recordLength < 38)
{
// Message body too short.
return null;
}
if (peekStream.ReadByte() != 0x04)
{
// should be ServerHello
return null;
}
int majorVersion = peekStream.ReadByte();
int minorVersion = peekStream.ReadByte();
// 32 bytes random + 1 byte sessionId + 2 bytes cipherSuite
if (!await peekStream.EnsureBufferLength(35, cancellationToken))
{
return null;
}
byte[] random = peekStream.ReadBytes(32);
byte[] sessionId = peekStream.ReadBytes(1);
int cipherSuite = peekStream.ReadInt16();
var serverHelloInfo = new ServerHelloInfo
{
HandshakeVersion = 2,
MajorVersion = majorVersion,
MinorVersion = minorVersion,
Random = random,
SessionId = sessionId,
CipherSuite = cipherSuite,
ServerHelloLength = peekStream.Position,
};
return serverHelloInfo;
}
else if (recordType == 0x16)
{
var peekStream = new CustomBufferedPeekStream(serverStream, bufferPool, 1);
//should contain at least 43 bytes
// 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length
if (!await peekStream.EnsureBufferLength(43, cancellationToken))
{
return null;
}
//SSL 3.0 or TLS 1.0, 1.1 and 1.2
int majorVersion = peekStream.ReadByte();
int minorVersion = peekStream.ReadByte();
int recordLength = peekStream.ReadInt16();
if (peekStream.ReadByte() != 0x02)
{
// should be ServerHello
return null;
}
var length = peekStream.ReadInt24();
majorVersion = peekStream.ReadByte();
minorVersion = peekStream.ReadByte();
byte[] random = peekStream.ReadBytes(32);
length = peekStream.ReadByte();
// sessionid + cipherSuite + compressionMethod
if (!await peekStream.EnsureBufferLength(length + 2 + 1, cancellationToken))
{
return null;
}
byte[] sessionId = peekStream.ReadBytes(length);
int cipherSuite = peekStream.ReadInt16();
byte compressionMethod = peekStream.ReadByte();
int extenstionsStartPosition = peekStream.Position;
Dictionary<string, SslExtension> extensions = null;
if (extenstionsStartPosition < recordLength + 5)
{
extensions = await ReadExtensions(majorVersion, minorVersion, peekStream, bufferPool, cancellationToken);
}
var serverHelloInfo = new ServerHelloInfo
{
HandshakeVersion = 3,
MajorVersion = majorVersion,
MinorVersion = minorVersion,
Random = random,
SessionId = sessionId,
CipherSuite = cipherSuite,
CompressionMethod = compressionMethod,
ServerHelloLength = peekStream.Position,
EntensionsStartPosition = extenstionsStartPosition,
Extensions = extensions,
};
return serverHelloInfo;
}
return null;
}
private static async Task<Dictionary<string, SslExtension>> ReadExtensions(int majorVersion, int minorVersion, CustomBufferedPeekStream peekStream, IBufferPool bufferPool, CancellationToken cancellationToken)
{
Dictionary<string, SslExtension> extensions = null;
if (majorVersion > 3 || majorVersion == 3 && minorVersion >= 1)
{
if (await peekStream.EnsureBufferLength(2, cancellationToken))
{
int extensionsLength = peekStream.ReadInt16();
if (await peekStream.EnsureBufferLength(extensionsLength, cancellationToken))
{
extensions = new Dictionary<string, SslExtension>();
int idx = 0;
while (extensionsLength > 3)
{
int id = peekStream.ReadInt16();
int length = peekStream.ReadInt16();
byte[] data = peekStream.ReadBytes(length);
var extension = SslExtensions.GetExtension(id, data, idx++);
extensions[extension.Name] = extension;
extensionsLength -= 4 + length;
}
}
}
}
return extensions;
}
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.StreamExtended
{
/// <summary>
/// Mimic a Task but you can set AsyncState
/// </summary>
/// <typeparam name="T"></typeparam>
public class TaskResult : IAsyncResult
{
Task Task;
object mAsyncState;
public TaskResult(Task pTask, object state)
{
Task = pTask;
mAsyncState = state;
}
public object AsyncState => mAsyncState;
public WaitHandle AsyncWaitHandle => ((IAsyncResult)Task).AsyncWaitHandle;
public bool CompletedSynchronously => ((IAsyncResult)Task).CompletedSynchronously;
public bool IsCompleted => Task.IsCompleted;
public void GetResult() { this.Task.GetAwaiter().GetResult(); }
}
/// <summary>
/// Mimic a Task<T> but you can set AsyncState
/// </summary>
/// <typeparam name="T"></typeparam>
public class TaskResult<T> : IAsyncResult
{
Task<T> Task;
object mAsyncState;
public TaskResult(Task<T> pTask, object state)
{
Task = pTask;
mAsyncState = state;
}
public object AsyncState => mAsyncState;
public WaitHandle AsyncWaitHandle => ((IAsyncResult)Task).AsyncWaitHandle;
public bool CompletedSynchronously => ((IAsyncResult)Task).CompletedSynchronously;
public bool IsCompleted => Task.IsCompleted;
public T Result => Task.Result;
}
}
......@@ -12,12 +12,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.1" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.3" />
<PackageReference Include="StreamExtended" Version="1.0.188-beta" />
<PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
<Reference Include="System.Web" />
</ItemGroup>
......
......@@ -12,9 +12,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.1" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.3" />
<PackageReference Include="StreamExtended" Version="1.0.188-beta" />
<PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
......
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net45;netstandard2.0;netcoreapp2.1</TargetFrameworks>
<RootNamespace>Titanium.Web.Proxy</RootNamespace>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<SignAssembly>True</SignAssembly>
......@@ -13,26 +13,25 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BrotliSharpLib" Version="0.3.1" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.3.37" />
<PackageReference Include="StreamExtended" Version="1.0.190" />
<PackageReference Include="BrotliSharpLib" Version="0.3.3" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.5" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.Win32.Registry">
<Version>4.4.0</Version>
<Version>4.5.0</Version>
</PackageReference>
<PackageReference Include="System.Security.Principal.Windows">
<Version>4.4.1</Version>
<Version>4.5.1</Version>
</PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
<PackageReference Include="Microsoft.Win32.Registry">
<Version>4.4.0</Version>
<Version>4.5.0</Version>
</PackageReference>
<PackageReference Include="System.Security.Principal.Windows">
<Version>4.4.1</Version>
<Version>4.5.1</Version>
</PackageReference>
</ItemGroup>
......
......@@ -15,16 +15,20 @@
<tags></tags>
<dependencies>
<group targetFramework="net45">
<dependency id="StreamExtended" version="1.0.190" />
<dependency id="Portable.BouncyCastle" version="1.8.3.37" />
<dependency id="BrotliSharpLib" version="0.3.1" />
<dependency id="Portable.BouncyCastle" version="1.8.5" />
<dependency id="BrotliSharpLib" version="0.3.3" />
</group>
<group targetFramework="netstandard2.0">
<dependency id="StreamExtended" version="1.0.190" />
<dependency id="Portable.BouncyCastle" version="1.8.3.37" />
<dependency id="BrotliSharpLib" version="0.3.1" />
<dependency id="Microsoft.Win32.Registry" version="4.4.0" />
<dependency id="System.Security.Principal.Windows" version="4.4.1" />
<dependency id="Portable.BouncyCastle" version="1.8.5" />
<dependency id="BrotliSharpLib" version="0.3.3" />
<dependency id="Microsoft.Win32.Registry" version="4.5.0" />
<dependency id="System.Security.Principal.Windows" version="4.5.1" />
</group>
<group targetFramework="netcoreapp2.1">
<dependency id="Portable.BouncyCastle" version="1.8.5" />
<dependency id="BrotliSharpLib" version="0.3.3" />
<dependency id="Microsoft.Win32.Registry" version="4.5.0" />
<dependency id="System.Security.Principal.Windows" version="4.5.1" />
</group>
</dependencies>
</metadata>
......
......@@ -7,14 +7,14 @@ using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using StreamExtended;
using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy
{
......@@ -67,7 +67,7 @@ namespace Titanium.Web.Proxy
X509Certificate2 certificate = null;
try
{
sslStream = new SslStream(clientStream, true);
sslStream = new SslStream(clientStream, false);
string certName = HttpHelper.GetWildCardDomainName(httpsHostName);
certificate = endPoint.GenericCertificate ??
......@@ -112,7 +112,7 @@ namespace Titanium.Web.Proxy
var data = BufferPool.GetBuffer(BufferSize);
try
{
// clientStream.Available sbould be at most BufferSize because it is using the same buffer size
// clientStream.Available should be at most BufferSize because it is using the same buffer size
await clientStream.ReadAsync(data, 0, available, cancellationToken);
serverStream = connection.Stream;
await serverStream.WriteAsync(data, 0, available, cancellationToken);
......
using StreamExtended.Network;
using System;
using System;
using System.Threading;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
......@@ -7,6 +6,7 @@ using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended.Network;
namespace Titanium.Web.Proxy
{
......
......@@ -150,7 +150,7 @@ namespace Titanium.Web.Proxy
}
// Need to revisit this.
// Should we cache all Set-Cokiee headers from server during auth process
// Should we cache all Set-Cookie headers from server during auth process
// and send it to client after auth?
// Let ResponseHandler send the updated request
......
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.8.3.1" targetFramework="net45" />
<package id="BrotliSharpLib" version="0.3.1" targetFramework="net45" />
<package id="StreamExtended" version="1.0.190" targetFramework="net45" />
</packages>
\ No newline at end of file
......@@ -20,7 +20,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
var request = new Request
{
Method = "POST",
OriginalUrl = "/",
RequestUriString = "/",
HttpVersion = new Version(1, 1)
};
request.Headers.AddHeader(KnownHeaders.Host, server);
......
......@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
RequestResponseBase request = new Request()
{
Method = method,
OriginalUrl = url,
RequestUriString = url,
HttpVersion = version
};
while (!string.IsNullOrEmpty(line = reader.ReadLine()))
......@@ -43,7 +43,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
if (!requireBody)
return request as Request;
if (ParseBody(reader, ref request))
if (parseBody(reader, ref request))
return request as Request;
}
catch { }
......@@ -84,7 +84,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
if (line?.Length != 0)
return null;
if (ParseBody(reader, ref response))
if (parseBody(reader, ref response))
return response as Response;
}
catch { }
......@@ -92,7 +92,7 @@ namespace Titanium.Web.Proxy.IntegrationTests.Helpers
return null;
}
private static bool ParseBody(StringReader reader, ref RequestResponseBase obj)
private static bool parseBody(StringReader reader, ref RequestResponseBase obj)
{
obj.OriginalContentLength = obj.ContentLength;
if (obj.ContentLength <= 0)
......
......@@ -33,5 +33,34 @@ namespace Titanium.Web.Proxy.IntegrationTests
Assert.AreEqual("I am server. I received your greetings.", body);
}
[TestMethod]
public async Task Can_Handle_Https_Fake_Tunnel_Request()
{
var testSuite = new TestSuite();
var server = testSuite.GetServer();
server.HandleRequest((context) =>
{
return context.Response.WriteAsync("I am server. I received your greetings.");
});
var proxy = testSuite.GetProxy();
proxy.BeforeRequest += async (sender, e) =>
{
e.HttpClient.Request.RequestUri = new Uri(server.ListeningHttpUrl);
await Task.FromResult(0);
};
var client = testSuite.GetClient(proxy);
var response = await client.PostAsync(new Uri($"https://{Guid.NewGuid().ToString()}.com"),
new StringContent("hello server. I am a client."));
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.AreEqual("I am server. I received your greetings.", body);
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
......@@ -17,7 +17,7 @@
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
</ItemGroup>
......
......@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyDescription("")]
[assembly: AssemblyCopyright("Copyright © Titanium 2015-2017")]
[assembly: AssemblyCopyright("Copyright © Titanium 2015-2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
......
......@@ -11,22 +11,22 @@ namespace Titanium.Web.Proxy.UnitTests
public class SystemProxyTest
{
[TestMethod]
public void CompareProxyAdddressReturendByWebProxyAndWinHttpProxyResolver()
public void CompareProxyAddressReturnedByWebProxyAndWinHttpProxyResolver()
{
var proxyManager = new SystemProxyManager();
try
{
CompareUrls();
compareUrls();
proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.Http);
CompareUrls();
compareUrls();
proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.Https);
CompareUrls();
compareUrls();
proxyManager.SetProxy("127.0.0.1", 8000, ProxyProtocolType.AllHttp);
CompareUrls();
compareUrls();
// for this test you need to add a proxy.pac file to a local webserver
//function FindProxyForURL(url, host)
......@@ -43,25 +43,25 @@ namespace Titanium.Web.Proxy.UnitTests
//CompareUrls();
proxyManager.SetProxyOverride("<-loopback>");
CompareUrls();
compareUrls();
proxyManager.SetProxyOverride("<local>");
CompareUrls();
compareUrls();
proxyManager.SetProxyOverride("yahoo.com");
CompareUrls();
compareUrls();
proxyManager.SetProxyOverride("*.local");
CompareUrls();
compareUrls();
proxyManager.SetProxyOverride("http://*.local");
CompareUrls();
compareUrls();
proxyManager.SetProxyOverride("<-loopback>;*.local");
CompareUrls();
compareUrls();
proxyManager.SetProxyOverride("<-loopback>;*.local;<local>");
CompareUrls();
compareUrls();
}
finally
{
......@@ -69,7 +69,7 @@ namespace Titanium.Web.Proxy.UnitTests
}
}
private void CompareUrls()
private void compareUrls()
{
var webProxy = WebRequest.GetSystemWebProxy();
......
......@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
<PackageReference Include="MSTest.TestFramework" Version="1.4.0" />
</ItemGroup>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment