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
0ff6870d
Commit
0ff6870d
authored
May 08, 2018
by
justcoding121
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Prepare for TCP connection pool
parent
24b0ffbd
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
174 additions
and
90 deletions
+174
-90
ExplicitClientHandler.cs
Titanium.Web.Proxy/ExplicitClientHandler.cs
+37
-35
ExternalProxy.cs
Titanium.Web.Proxy/Models/ExternalProxy.cs
+1
-0
TcpConnectionFactory.cs
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+103
-27
TcpServerConnection.cs
Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs
+5
-0
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+2
-2
TransparentClientHandler.cs
Titanium.Web.Proxy/TransparentClientHandler.cs
+26
-26
No files found.
Titanium.Web.Proxy/ExplicitClientHandler.cs
View file @
0ff6870d
...
...
@@ -136,10 +136,11 @@ namespace Titanium.Web.Proxy
{
// test server HTTP/2 support
// todo: this is a hack, because Titanium does not support HTTP protocol changing currently
using
(
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
,
SslExtensions
.
Http2ProtocolAsList
,
cancellationToken
))
{
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
,
SslExtensions
.
Http2ProtocolAsList
,
cancellationToken
);
http2Supproted
=
connection
.
NegotiatedApplicationProtocol
==
SslApplicationProtocol
.
Http2
;
}
tcpConnectionFactory
.
Release
(
connection
);
}
SslStream
sslStream
=
null
;
...
...
@@ -176,7 +177,6 @@ namespace Titanium.Web.Proxy
// HTTPS server created - we can now decrypt the client's traffic
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
}
catch
(
Exception
e
)
...
...
@@ -201,8 +201,9 @@ namespace Titanium.Web.Proxy
if
(!
decryptSsl
||
!
isClientHello
)
{
// create new connection
using
(
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
,
clientConnection
.
NegotiatedApplicationProtocol
,
cancellationToken
))
{
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
,
clientConnection
.
NegotiatedApplicationProtocol
,
cancellationToken
);
if
(
isClientHello
)
{
int
available
=
clientStream
.
Available
;
...
...
@@ -233,8 +234,8 @@ namespace Titanium.Web.Proxy
(
buffer
,
offset
,
count
)
=>
{
connectArgs
.
OnDataSent
(
buffer
,
offset
,
count
);
},
(
buffer
,
offset
,
count
)
=>
{
connectArgs
.
OnDataReceived
(
buffer
,
offset
,
count
);
},
connectArgs
.
CancellationTokenSource
,
ExceptionFunc
);
}
tcpConnectionFactory
.
Release
(
connection
);
return
;
}
}
...
...
@@ -265,8 +266,9 @@ namespace Titanium.Web.Proxy
}
// create new connection
using
(
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
,
SslExtensions
.
Http2ProtocolAsList
,
cancellationToken
))
{
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
,
SslExtensions
.
Http2ProtocolAsList
,
cancellationToken
);
await
connection
.
StreamWriter
.
WriteLineAsync
(
"PRI * HTTP/2.0"
,
cancellationToken
);
await
connection
.
StreamWriter
.
WriteLineAsync
(
cancellationToken
);
await
connection
.
StreamWriter
.
WriteLineAsync
(
"SM"
,
cancellationToken
);
...
...
@@ -278,7 +280,7 @@ namespace Titanium.Web.Proxy
(
buffer
,
offset
,
count
)
=>
{
connectArgs
.
OnDataReceived
(
buffer
,
offset
,
count
);
},
connectArgs
.
CancellationTokenSource
,
clientConnection
.
Id
,
ExceptionFunc
);
#endif
}
tcpConnectionFactory
.
Release
(
connection
);
}
}
...
...
Titanium.Web.Proxy/Models/ExternalProxy.cs
View file @
0ff6870d
...
...
@@ -77,5 +77,6 @@ namespace Titanium.Web.Proxy.Models
{
return
$"
{
HostName
}
:
{
Port
}
"
;
}
}
}
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
View file @
0ff6870d
using
System
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Net
;
using
System.Net.Security
;
using
System.Net.Sockets
;
...
...
@@ -13,30 +15,75 @@ using Titanium.Web.Proxy.Models;
namespace
Titanium.Web.Proxy.Network.Tcp
{
/// <summary>
/// A class that manages Tcp Connection to server used by this proxy server
/// A class that manages Tcp Connection to server used by this proxy server
.
/// </summary>
internal
class
TcpConnectionFactory
{
//private readonly ConcurrentDictionary<string, List<TcpServerConnection>> cache
// = new ConcurrentDictionary<string, List<TcpServerConnection>>();
/// <summary>
/// Gets a TCP connection to server from connection pool.
/// </summary>
/// <param name="remoteHostName">The remote hostname.</param>
/// <param name="remotePort">The remote port.</param>
/// <param name="httpVersion">The http version to use.</param>
/// <param name="isHttps">Is this a HTTPS request.</param>
/// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param>
/// <param name="isConnect">Is this a CONNECT request.</param>
/// <param name="proxyServer">The current ProxyServer instance.</param>
/// <param name="upStreamEndPoint">The upstream endpoint to make request via.</param>
/// <param name="externalProxy">The external proxy to make request via.</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns>
internal
async
Task
<
TcpServerConnection
>
GetClient
(
string
remoteHostName
,
int
remotePort
,
Version
httpVersion
,
bool
isHttps
,
List
<
SslApplicationProtocol
>
applicationProtocols
,
bool
isConnect
,
ProxyServer
proxyServer
,
IPEndPoint
upStreamEndPoint
,
ExternalProxy
externalProxy
,
CancellationToken
cancellationToken
)
{
//TODO fix cacheKey with all possible properties that uniquely identify a connection
//var cacheKey = $"{remoteHostName}{remotePort}{httpVersion}" +
// $"{isHttps}{isConnect}";
//if (cache.TryGetValue(cacheKey, out var existingConnections))
//{
// var recentConnection = existingConnections.Last();
// existingConnections.RemoveAt(existingConnections.Count - 1);
// //TODO check if connection is still active before returning
// return recentConnection;
//}
var
connection
=
await
CreateClient
(
remoteHostName
,
remotePort
,
httpVersion
,
isHttps
,
applicationProtocols
,
isConnect
,
proxyServer
,
upStreamEndPoint
,
externalProxy
,
cancellationToken
);
//connection.CacheKey = cacheKey;
return
connection
;
}
/// <summary>
/// Creates a TCP connection to server
/// </summary>
/// <param name="remoteHostName"></param>
/// <param name="remotePort"></param>
/// <param name="httpVersion"></param>
/// <param name="
decryptSsl">
</param>
/// <param name="applicationProtocols"></param>
/// <param name="isConnect"></param>
/// <param name="proxyServer"></param>
/// <param name="upStreamEndPoint"></param>
/// <param name="externalProxy"></param>
/// <param name="cancellationToken"></param>
/// <param name="remoteHostName">
The remote hostname.
</param>
/// <param name="remotePort">
The remote port.
</param>
/// <param name="httpVersion">
The http version to use.
</param>
/// <param name="
isHttps">Is this a HTTPS request.
</param>
/// <param name="applicationProtocols">
The list of HTTPS application level protocol to negotiate if needed.
</param>
/// <param name="isConnect">
Is this a CONNECT request.
</param>
/// <param name="proxyServer">
The current ProxyServer instance.
</param>
/// <param name="upStreamEndPoint">
The upstream endpoint to make request via.
</param>
/// <param name="externalProxy">
The external proxy to make request via.
</param>
/// <param name="cancellationToken">
The cancellation token for this async task.
</param>
/// <returns></returns>
internal
async
Task
<
TcpServerConnection
>
CreateClient
(
string
remoteHostName
,
int
remotePort
,
Version
httpVersion
,
bool
decryptSsl
,
List
<
SslApplicationProtocol
>
applicationProtocols
,
bool
isConnect
,
private
async
Task
<
TcpServerConnection
>
CreateClient
(
string
remoteHostName
,
int
remotePort
,
Version
httpVersion
,
bool
isHttps
,
List
<
SslApplicationProtocol
>
applicationProtocols
,
bool
isConnect
,
ProxyServer
proxyServer
,
IPEndPoint
upStreamEndPoint
,
ExternalProxy
externalProxy
,
CancellationToken
cancellationToken
)
{
bool
useUpstreamProxy
=
false
;
// check if external proxy is set for HTTP/HTTPS
...
...
@@ -59,12 +106,14 @@ namespace Titanium.Web.Proxy.Network.Tcp
try
{
tcpClient
=
new
TcpClient
(
upStreamEndPoint
);
tcpClient
=
new
TcpClient
(
upStreamEndPoint
)
{
ReceiveTimeout
=
proxyServer
.
ConnectionTimeOutSeconds
*
1000
,
SendTimeout
=
proxyServer
.
ConnectionTimeOutSeconds
*
1000
,
SendBufferSize
=
proxyServer
.
BufferSize
,
ReceiveBufferSize
=
proxyServer
.
BufferSize
};
tcpClient
.
ReceiveTimeout
=
proxyServer
.
ConnectionTimeOutSeconds
*
1000
;
tcpClient
.
SendTimeout
=
proxyServer
.
ConnectionTimeOutSeconds
*
1000
;
tcpClient
.
SendBufferSize
=
proxyServer
.
BufferSize
;
tcpClient
.
ReceiveBufferSize
=
proxyServer
.
BufferSize
;
await
proxyServer
.
InvokeConnectionCreateEvent
(
tcpClient
,
false
);
...
...
@@ -80,7 +129,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
stream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
proxyServer
.
BufferSize
);
if
(
useUpstreamProxy
&&
(
isConnect
||
decryptSsl
))
if
(
useUpstreamProxy
&&
(
isConnect
||
isHttps
))
{
var
writer
=
new
HttpRequestWriter
(
stream
,
proxyServer
.
BufferSize
);
var
connectRequest
=
new
ConnectRequest
...
...
@@ -113,18 +162,20 @@ namespace Titanium.Web.Proxy.Network.Tcp
await
stream
.
ReadAndIgnoreAllLinesAsync
(
cancellationToken
);
}
if
(
decryptSsl
)
if
(
isHttps
)
{
var
sslStream
=
new
SslStream
(
stream
,
false
,
proxyServer
.
ValidateServerCertificate
,
proxyServer
.
SelectClientCertificate
);
stream
=
new
CustomBufferedStream
(
sslStream
,
proxyServer
.
BufferSize
);
var
options
=
new
SslClientAuthenticationOptions
();
options
.
ApplicationProtocols
=
applicationProtocols
;
options
.
TargetHost
=
remoteHostName
;
options
.
ClientCertificates
=
null
;
options
.
EnabledSslProtocols
=
proxyServer
.
SupportedSslProtocols
;
options
.
CertificateRevocationCheckMode
=
proxyServer
.
CheckCertificateRevocation
;
var
options
=
new
SslClientAuthenticationOptions
{
ApplicationProtocols
=
applicationProtocols
,
TargetHost
=
remoteHostName
,
ClientCertificates
=
null
,
EnabledSslProtocols
=
proxyServer
.
SupportedSslProtocols
,
CertificateRevocationCheckMode
=
proxyServer
.
CheckCertificateRevocation
};
await
sslStream
.
AuthenticateAsClientAsync
(
options
,
cancellationToken
);
#if NETCOREAPP2_1
negotiatedApplicationProtocol
=
sslStream
.
NegotiatedApplicationProtocol
;
...
...
@@ -141,11 +192,12 @@ namespace Titanium.Web.Proxy.Network.Tcp
return
new
TcpServerConnection
(
proxyServer
,
tcpClient
)
{
//CacheKey = cacheKey,
UpStreamProxy
=
externalProxy
,
UpStreamEndPoint
=
upStreamEndPoint
,
HostName
=
remoteHostName
,
Port
=
remotePort
,
IsHttps
=
decryptSsl
,
IsHttps
=
isHttps
,
NegotiatedApplicationProtocol
=
negotiatedApplicationProtocol
,
UseUpstreamProxy
=
useUpstreamProxy
,
StreamWriter
=
new
HttpRequestWriter
(
stream
,
proxyServer
.
BufferSize
),
...
...
@@ -153,5 +205,29 @@ namespace Titanium.Web.Proxy.Network.Tcp
Version
=
httpVersion
};
}
/// <summary>
/// Release connection back to cache.
/// </summary>
/// <param name="connection">The Tcp server connection to return.</param>
internal
void
Release
(
TcpServerConnection
connection
)
{
//while (true)
//{
// if (cache.TryGetValue(connection.Key, out var existingConnections))
// {
// existingConnections.Add(connection);
// break;
// }
// if (cache.TryAdd(connection.Key, new List<TcpServerConnection> { connection }))
// {
// break;
// };
//}
connection
?.
Dispose
();
}
}
}
Titanium.Web.Proxy/Network/Tcp/TcpServerConnection.cs
View file @
0ff6870d
...
...
@@ -63,6 +63,11 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary>
internal
DateTime
LastAccess
{
get
;
set
;
}
/// <summary>
/// The cache key used to uniquely identify this connection properties
/// </summary>
internal
string
CacheKey
{
get
;
set
;
}
/// <summary>
/// Dispose.
/// </summary>
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
0ff6870d
...
...
@@ -268,7 +268,7 @@ namespace Titanium.Web.Proxy
}
finally
{
serverConnection
?.
Dispose
(
);
tcpConnectionFactory
.
Release
(
serverConnection
);
}
}
...
...
@@ -398,7 +398,7 @@ namespace Titanium.Web.Proxy
args
.
CustomUpStreamProxyUsed
=
customUpStreamProxy
;
return
await
tcpConnectionFactory
.
Create
Client
(
return
await
tcpConnectionFactory
.
Get
Client
(
args
.
WebSession
.
Request
.
RequestUri
.
Host
,
args
.
WebSession
.
Request
.
RequestUri
.
Port
,
args
.
WebSession
.
Request
.
HttpVersion
,
...
...
Titanium.Web.Proxy/TransparentClientHandler.cs
View file @
0ff6870d
using
System
;
using
System.Collections.Generic
;
using
System.IO
;
using
System.Net.Security
;
using
System.Net.Sockets
;
...
...
@@ -87,14 +88,12 @@ namespace Titanium.Web.Proxy
else
{
// create new connection
var
connection
=
new
TcpClient
(
UpStreamEndPoint
);
await
connection
.
ConnectAsync
(
httpsHostName
,
endPoint
.
Port
);
connection
.
ReceiveTimeout
=
ConnectionTimeOutSeconds
*
1000
;
connection
.
SendTimeout
=
ConnectionTimeOutSeconds
*
1000
;
var
connection
=
await
tcpConnectionFactory
.
GetClient
(
httpsHostName
,
endPoint
.
Port
,
null
,
false
,
new
List
<
SslApplicationProtocol
>
{
clientConnection
.
NegotiatedApplicationProtocol
},
true
,
this
,
UpStreamEndPoint
,
UpStreamHttpsProxy
,
cancellationToken
);
using
(
connection
)
{
var
serverStream
=
connection
.
GetStream
();
var
serverStream
=
connection
.
Stream
;
int
available
=
clientStream
.
Available
;
if
(
available
>
0
)
...
...
@@ -115,11 +114,12 @@ namespace Titanium.Web.Proxy
}
}
////var serverHelloInfo = await SslTools.PeekServerHello(serverStream);
await
TcpHelper
.
SendRaw
(
clientStream
,
serverStream
,
BufferSize
,
null
,
null
,
cancellationTokenSource
,
ExceptionFunc
);
}
tcpConnectionFactory
.
Release
(
connection
);
return
;
}
}
...
...
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