Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
T
Titanium-Web-Proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Titanium-Web-Proxy
Commits
c75ad1a5
Commit
c75ad1a5
authored
Sep 24, 2020
by
Honfika
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
prefetch fix
parent
37d1d6a2
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
55 additions
and
47 deletions
+55
-47
App.config
...les/Titanium.Web.Proxy.Examples.WindowsService/App.config
+1
-1
Settings.Designer.cs
...y.Examples.WindowsService/Properties/Settings.Designer.cs
+1
-1
Settings.settings
...roxy.Examples.WindowsService/Properties/Settings.settings
+1
-1
ExplicitClientHandler.cs
src/Titanium.Web.Proxy/ExplicitClientHandler.cs
+18
-26
TcpConnectionFactory.cs
src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+25
-12
ProxyServer.cs
src/Titanium.Web.Proxy/ProxyServer.cs
+2
-2
RequestHandler.cs
src/Titanium.Web.Proxy/RequestHandler.cs
+1
-1
TransparentClientHandler.cs
src/Titanium.Web.Proxy/TransparentClientHandler.cs
+2
-2
TestProxyServer.cs
...anium.Web.Proxy.IntegrationTests/Setup/TestProxyServer.cs
+4
-1
No files found.
examples/Titanium.Web.Proxy.Examples.WindowsService/App.config
View file @
c75ad1a5
...
...
@@ -45,7 +45,7 @@
<
value
>
True
</
value
>
</
setting
>
<
setting
name
=
"EnableTcpServerConnectionPrefetch"
serializeAs
=
"String"
>
<
value
>
Fals
e
</
value
>
<
value
>
Tru
e
</
value
>
</
setting
>
<
setting
name
=
"EnableWinAuth"
serializeAs
=
"String"
>
<
value
>
False
</
value
>
...
...
examples/Titanium.Web.Proxy.Examples.WindowsService/Properties/Settings.Designer.cs
View file @
c75ad1a5
...
...
@@ -95,7 +95,7 @@ namespace WindowsServiceExample.Properties
[
global
::
System
.
Configuration
.
ApplicationScopedSettingAttribute
()]
[
global
::
System
.
Diagnostics
.
DebuggerNonUserCodeAttribute
()]
[
global
::
System
.
Configuration
.
DefaultSettingValueAttribute
(
"
Fals
e"
)]
[
global
::
System
.
Configuration
.
DefaultSettingValueAttribute
(
"
Tru
e"
)]
public
bool
EnableTcpServerConnectionPrefetch
{
get
...
...
examples/Titanium.Web.Proxy.Examples.WindowsService/Properties/Settings.settings
View file @
c75ad1a5
...
...
@@ -21,7 +21,7 @@
<Value
Profile=
"(Default)"
>
True
</Value>
</Setting>
<Setting
Name=
"EnableTcpServerConnectionPrefetch"
Type=
"System.Boolean"
Scope=
"Application"
>
<Value
Profile=
"(Default)"
>
Fals
e
</Value>
<Value
Profile=
"(Default)"
>
Tru
e
</Value>
</Setting>
<Setting
Name=
"EnableWinAuth"
Type=
"System.Boolean"
Scope=
"Application"
>
<Value
Profile=
"(Default)"
>
False
</Value>
...
...
src/Titanium.Web.Proxy/ExplicitClientHandler.cs
View file @
c75ad1a5
...
...
@@ -35,7 +35,7 @@ namespace Titanium.Web.Proxy
var
clientStream
=
new
HttpClientStream
(
clientConnection
,
clientConnection
.
GetStream
(),
BufferPool
,
cancellationToken
);
Task
<
TcpServerConnection
>?
prefetchConnectionTask
=
null
;
Task
<
TcpServerConnection
?
>?
prefetchConnectionTask
=
null
;
bool
closeServerConnection
=
false
;
try
...
...
@@ -145,13 +145,16 @@ namespace Titanium.Web.Proxy
// todo: this is a hack, because Titanium does not support HTTP protocol changing currently
var
connection
=
await
tcpConnectionFactory
.
GetServerConnection
(
this
,
connectArgs
,
true
,
SslExtensions
.
Http2ProtocolAsList
,
true
,
cancellationToken
);
true
,
true
,
cancellationToken
);
http2Supported
=
connection
.
NegotiatedApplicationProtocol
==
SslApplicationProtocol
.
Http2
;
if
(
connection
!=
null
)
{
http2Supported
=
connection
.
NegotiatedApplicationProtocol
==
SslApplicationProtocol
.
Http2
;
// release connection back to pool instead of closing when connection pool is enabled.
await
tcpConnectionFactory
.
Release
(
connection
,
true
);
// release connection back to pool instead of closing when connection pool is enabled.
await
tcpConnectionFactory
.
Release
(
connection
,
true
);
}
}
catch
(
Exception
)
{
...
...
@@ -162,22 +165,11 @@ namespace Titanium.Web.Proxy
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
prefetchConnectionTask
=
tcpConnectionFactory
.
GetServerConnection
(
this
,
connectArgs
,
true
,
null
,
false
,
CancellationToken
.
None
);
}
// don't pass cancellation token here
// it could cause floating server connections when client exits
prefetchConnectionTask
=
tcpConnectionFactory
.
GetServerConnection
(
this
,
connectArgs
,
true
,
null
,
false
,
true
,
CancellationToken
.
None
);
}
string
connectHostname
=
requestLine
.
RequestUri
.
GetString
();
...
...
@@ -272,9 +264,9 @@ namespace Titanium.Web.Proxy
// 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.
var
connection
=
await
tcpConnectionFactory
.
GetServerConnection
(
this
,
connectArgs
,
var
connection
=
(
await
tcpConnectionFactory
.
GetServerConnection
(
this
,
connectArgs
,
true
,
null
,
true
,
cancellationToken
)
;
true
,
false
,
cancellationToken
))!
;
try
{
...
...
@@ -349,9 +341,9 @@ namespace Titanium.Web.Proxy
throw
new
Exception
(
$"HTTP/2 Protocol violation. Empty string expected, '
{
line
}
' received"
);
}
var
connection
=
await
tcpConnectionFactory
.
GetServerConnection
(
this
,
connectArgs
,
var
connection
=
(
await
tcpConnectionFactory
.
GetServerConnection
(
this
,
connectArgs
,
true
,
SslExtensions
.
Http2ProtocolAsList
,
true
,
cancellationToken
)
;
true
,
false
,
cancellationToken
))!
;
try
{
#if NETSTANDARD2_1
...
...
src/Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
View file @
c75ad1a5
...
...
@@ -154,7 +154,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
applicationProtocols
=
new
List
<
SslApplicationProtocol
>
{
applicationProtocol
};
}
return
GetServerConnection
(
proxyServer
,
session
,
isConnect
,
applicationProtocols
,
noCache
,
cancellationToken
)
;
return
GetServerConnection
(
proxyServer
,
session
,
isConnect
,
applicationProtocols
,
noCache
,
false
,
cancellationToken
)!
;
}
/// <summary>
...
...
@@ -165,10 +165,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="isConnect">Is this a CONNECT request.</param>
/// <param name="applicationProtocols"></param>
/// <param name="noCache">if set to <c>true</c> [no cache].</param>
/// <param name="prefetch">if set to <c>true</c> [prefetch].</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns>
internal
async
Task
<
TcpServerConnection
>
GetServerConnection
(
ProxyServer
proxyServer
,
SessionEventArgsBase
session
,
bool
isConnect
,
List
<
SslApplicationProtocol
>?
applicationProtocols
,
bool
noCache
,
CancellationToken
cancellationToken
)
internal
async
Task
<
TcpServerConnection
?
>
GetServerConnection
(
ProxyServer
proxyServer
,
SessionEventArgsBase
session
,
bool
isConnect
,
List
<
SslApplicationProtocol
>?
applicationProtocols
,
bool
noCache
,
bool
prefetch
,
CancellationToken
cancellationToken
)
{
var
customUpStreamProxy
=
session
.
CustomUpStreamProxy
;
...
...
@@ -208,7 +209,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
var
upStreamEndPoint
=
session
.
HttpClient
.
UpStreamEndPoint
??
proxyServer
.
UpStreamEndPoint
;
var
upStreamProxy
=
customUpStreamProxy
??
(
isHttps
?
proxyServer
.
UpStreamHttpsProxy
:
proxyServer
.
UpStreamHttpProxy
);
return
await
GetServerConnection
(
proxyServer
,
host
,
port
,
session
.
HttpClient
.
Request
.
HttpVersion
,
isHttps
,
applicationProtocols
,
isConnect
,
session
,
upStreamEndPoint
,
upStreamProxy
,
noCache
,
cancellationToken
);
applicationProtocols
,
isConnect
,
session
,
upStreamEndPoint
,
upStreamProxy
,
noCache
,
prefetch
,
cancellationToken
);
}
/// <summary>
...
...
@@ -225,12 +226,13 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
/// <param name="externalProxy">The external proxy to make request via.</param>
/// <param name="noCache">Not from cache/create new connection.</param>
/// <param name="prefetch">if set to <c>true</c> [prefetch].</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns>
internal
async
Task
<
TcpServerConnection
>
GetServerConnection
(
ProxyServer
proxyServer
,
string
remoteHostName
,
int
remotePort
,
internal
async
Task
<
TcpServerConnection
?
>
GetServerConnection
(
ProxyServer
proxyServer
,
string
remoteHostName
,
int
remotePort
,
Version
httpVersion
,
bool
isHttps
,
List
<
SslApplicationProtocol
>?
applicationProtocols
,
bool
isConnect
,
SessionEventArgsBase
sessionArgs
,
IPEndPoint
?
upStreamEndPoint
,
IExternalProxy
?
externalProxy
,
bool
noCache
,
CancellationToken
cancellationToken
)
bool
noCache
,
bool
prefetch
,
CancellationToken
cancellationToken
)
{
var
sslProtocol
=
sessionArgs
.
ClientConnection
.
SslProtocol
;
var
cacheKey
=
GetConnectionCacheKey
(
remoteHostName
,
remotePort
,
...
...
@@ -259,7 +261,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
}
var
connection
=
await
createServerConnection
(
remoteHostName
,
remotePort
,
httpVersion
,
isHttps
,
sslProtocol
,
applicationProtocols
,
isConnect
,
proxyServer
,
sessionArgs
,
upStreamEndPoint
,
externalProxy
,
cacheKey
,
cancellationToken
);
applicationProtocols
,
isConnect
,
proxyServer
,
sessionArgs
,
upStreamEndPoint
,
externalProxy
,
cacheKey
,
prefetch
,
cancellationToken
);
return
connection
;
}
...
...
@@ -279,12 +281,13 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
/// <param name="externalProxy">The external proxy to make request via.</param>
/// <param name="cacheKey">The connection cache key</param>
/// <param name="prefetch">if set to <c>true</c> [prefetch].</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns>
private
async
Task
<
TcpServerConnection
>
createServerConnection
(
string
remoteHostName
,
int
remotePort
,
private
async
Task
<
TcpServerConnection
?
>
createServerConnection
(
string
remoteHostName
,
int
remotePort
,
Version
httpVersion
,
bool
isHttps
,
SslProtocols
sslProtocol
,
List
<
SslApplicationProtocol
>?
applicationProtocols
,
bool
isConnect
,
ProxyServer
proxyServer
,
SessionEventArgsBase
sessionArgs
,
IPEndPoint
?
upStreamEndPoint
,
IExternalProxy
?
externalProxy
,
string
cacheKey
,
CancellationToken
cancellationToken
)
bool
prefetch
,
CancellationToken
cancellationToken
)
{
// deny connection to proxy end points to avoid infinite connection loop.
if
(
Server
.
ProxyEndPoints
.
Any
(
x
=>
x
.
Port
==
remotePort
)
...
...
@@ -350,6 +353,11 @@ retry:
var
ipAddresses
=
await
Dns
.
GetHostAddressesAsync
(
hostname
);
if
(
ipAddresses
==
null
||
ipAddresses
.
Length
==
0
)
{
if
(
prefetch
)
{
return
null
;
}
throw
new
Exception
(
$"Could not resolve the hostname
{
hostname
}
"
);
}
...
...
@@ -486,10 +494,15 @@ retry:
{
sessionArgs
.
CustomUpStreamProxyUsed
=
newUpstreamProxy
;
sessionArgs
.
TimeLine
[
"Retrying Upstream Proxy Connection"
]
=
DateTime
.
UtcNow
;
return
await
createServerConnection
(
remoteHostName
,
remotePort
,
httpVersion
,
isHttps
,
sslProtocol
,
applicationProtocols
,
isConnect
,
proxyServer
,
sessionArgs
,
upStreamEndPoint
,
externalProxy
,
cacheKey
,
cancellationToken
);
return
await
createServerConnection
(
remoteHostName
,
remotePort
,
httpVersion
,
isHttps
,
sslProtocol
,
applicationProtocols
,
isConnect
,
proxyServer
,
sessionArgs
,
upStreamEndPoint
,
externalProxy
,
cacheKey
,
prefetch
,
cancellationToken
);
}
}
if
(
prefetch
)
{
return
null
;
}
throw
new
Exception
(
$"Could not establish connection to
{
hostname
}
"
,
lastException
);
}
...
...
@@ -502,7 +515,7 @@ retry:
stream
=
new
HttpServerStream
(
new
NetworkStream
(
tcpServerSocket
,
true
),
proxyServer
.
BufferPool
,
cancellationToken
);
if
(
(
externalProxy
!=
null
&&
externalProxy
.
ProxyType
==
ExternalProxyType
.
Http
)
&&
(
isConnect
||
isHttps
))
if
(
externalProxy
!=
null
&&
externalProxy
.
ProxyType
==
ExternalProxyType
.
Http
&&
(
isConnect
||
isHttps
))
{
var
authority
=
$"
{
remoteHostName
}
:
{
remotePort
}
"
.
GetByteString
();
var
connectRequest
=
new
ConnectRequest
(
authority
)
...
...
@@ -658,7 +671,7 @@ retry:
}
}
internal
async
Task
Release
(
Task
<
TcpServerConnection
>?
connectionCreateTask
,
bool
closeServerConnection
)
internal
async
Task
Release
(
Task
<
TcpServerConnection
?
>?
connectionCreateTask
,
bool
closeServerConnection
)
{
if
(
connectionCreateTask
==
null
)
{
...
...
src/Titanium.Web.Proxy/ProxyServer.cs
View file @
c75ad1a5
...
...
@@ -182,9 +182,9 @@ namespace Titanium.Web.Proxy
/// corresponding server connection process using CONNECT hostname or SNI hostname on a separate task so that after parsing client request
/// we will have the server connection immediately ready or in the process of getting ready.
/// If a server connection is available in cache then this prefetch task will immediately return with the available connection from cache.
/// Defaults to
fals
e.
/// Defaults to
tru
e.
/// </summary>
public
bool
EnableTcpServerConnectionPrefetch
{
get
;
set
;
}
=
fals
e
;
public
bool
EnableTcpServerConnectionPrefetch
{
get
;
set
;
}
=
tru
e
;
/// <summary>
/// Gets or sets a Boolean value that specifies whether server and client stream Sockets are using the Nagle algorithm.
...
...
src/Titanium.Web.Proxy/RequestHandler.cs
View file @
c75ad1a5
...
...
@@ -35,7 +35,7 @@ namespace Titanium.Web.Proxy
/// <param name="isHttps">Is HTTPS</param>
private
async
Task
handleHttpSessionRequest
(
ProxyEndPoint
endPoint
,
HttpClientStream
clientStream
,
CancellationTokenSource
cancellationTokenSource
,
TunnelConnectSessionEventArgs
?
connectArgs
=
null
,
Task
<
TcpServerConnection
>?
prefetchConnectionTask
=
null
,
bool
isHttps
=
false
)
Task
<
TcpServerConnection
?
>?
prefetchConnectionTask
=
null
,
bool
isHttps
=
false
)
{
var
connectRequest
=
connectArgs
?.
HttpClient
.
ConnectRequest
;
...
...
src/Titanium.Web.Proxy/TransparentClientHandler.cs
View file @
c75ad1a5
...
...
@@ -91,10 +91,10 @@ namespace Titanium.Web.Proxy
else
{
var
sessionArgs
=
new
SessionEventArgs
(
this
,
endPoint
,
clientStream
,
null
,
cancellationTokenSource
);
var
connection
=
await
tcpConnectionFactory
.
GetServerConnection
(
this
,
httpsHostName
,
port
,
var
connection
=
(
await
tcpConnectionFactory
.
GetServerConnection
(
this
,
httpsHostName
,
port
,
HttpHeader
.
VersionUnknown
,
false
,
null
,
true
,
sessionArgs
,
UpStreamEndPoint
,
UpStreamHttpsProxy
,
true
,
cancellationToken
)
;
UpStreamHttpsProxy
,
true
,
false
,
cancellationToken
))!
;
try
{
...
...
tests/Titanium.Web.Proxy.IntegrationTests/Setup/TestProxyServer.cs
View file @
c75ad1a5
...
...
@@ -7,13 +7,16 @@ namespace Titanium.Web.Proxy.IntegrationTests.Setup
{
public
class
TestProxyServer
:
IDisposable
{
public
ProxyServer
ProxyServer
{
get
;
private
set
;
}
public
ProxyServer
ProxyServer
{
get
;
}
public
int
ListeningPort
=>
ProxyServer
.
ProxyEndPoints
[
0
].
Port
;
public
CertificateManager
CertificateManager
=>
ProxyServer
.
CertificateManager
;
public
TestProxyServer
(
bool
isReverseProxy
,
ProxyServer
upStreamProxy
=
null
)
{
ProxyServer
=
new
ProxyServer
();
var
explicitEndPoint
=
isReverseProxy
?
(
ProxyEndPoint
)
new
TransparentProxyEndPoint
(
IPAddress
.
Any
,
0
,
true
)
:
new
ExplicitProxyEndPoint
(
IPAddress
.
Any
,
0
,
true
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment