@@ -22,6 +22,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
22
22
/// </summary>
23
23
internal class TcpConnectionFactory : IDisposable
24
24
{
25
+
25
26
//Tcp server connection pool cache
26
27
private readonly ConcurrentDictionary < string , ConcurrentQueue < TcpServerConnection > > cache
27
28
= new ConcurrentDictionary < string , ConcurrentQueue < TcpServerConnection > > ( ) ;
@@ -74,10 +75,10 @@ internal string GetConnectionCacheKey(string remoteHostName, int remotePort,
74
75
/// <summary>
75
76
/// Gets the connection cache key.
76
77
/// </summary>
77
- /// <param name="args ">The session event arguments.</param>
78
+ /// <param name="session ">The session event arguments.</param>
78
79
/// <param name="applicationProtocol"></param>
79
80
/// <returns></returns>
80
- internal async Task < string > GetConnectionCacheKey ( ProxyServer server , SessionEventArgsBase args ,
81
+ internal async Task < string > GetConnectionCacheKey ( ProxyServer server , SessionEventArgsBase session ,
81
82
SslApplicationProtocol applicationProtocol )
82
83
{
83
84
List < SslApplicationProtocol > applicationProtocols = null ;
@@ -88,32 +89,32 @@ internal async Task<string> GetConnectionCacheKey(ProxyServer server, SessionEve
88
89
89
90
ExternalProxy customUpStreamProxy = null ;
90
91
91
- bool isHttps = args . IsHttps ;
92
+ bool isHttps = session . IsHttps ;
92
93
if ( server . GetCustomUpStreamProxyFunc != null )
93
94
{
94
- customUpStreamProxy = await server . GetCustomUpStreamProxyFunc ( args ) ;
95
+ customUpStreamProxy = await server . GetCustomUpStreamProxyFunc ( session ) ;
95
96
}
96
97
97
- args . CustomUpStreamProxyUsed = customUpStreamProxy ;
98
+ session . CustomUpStreamProxyUsed = customUpStreamProxy ;
98
99
99
100
return GetConnectionCacheKey (
100
- args . WebSession . Request . RequestUri . Host ,
101
- args . WebSession . Request . RequestUri . Port ,
101
+ session . WebSession . Request . RequestUri . Host ,
102
+ session . WebSession . Request . RequestUri . Port ,
102
103
isHttps , applicationProtocols ,
103
- server , args . WebSession . UpStreamEndPoint ?? server . UpStreamEndPoint ,
104
+ server , session . WebSession . UpStreamEndPoint ?? server . UpStreamEndPoint ,
104
105
customUpStreamProxy ?? ( isHttps ? server . UpStreamHttpsProxy : server . UpStreamHttpProxy ) ) ;
105
106
}
106
107
107
108
108
109
/// <summary>
109
110
/// Create a server connection.
110
111
/// </summary>
111
- /// <param name="args ">The session event arguments.</param>
112
+ /// <param name="session ">The session event arguments.</param>
112
113
/// <param name="isConnect">Is this a CONNECT request.</param>
113
114
/// <param name="applicationProtocol"></param>
114
115
/// <param name="cancellationToken">The cancellation token for this async task.</param>
115
116
/// <returns></returns>
116
- internal Task < TcpServerConnection > GetServerConnection ( ProxyServer server , SessionEventArgsBase args , bool isConnect ,
117
+ internal Task < TcpServerConnection > GetServerConnection ( ProxyServer server , SessionEventArgsBase session , bool isConnect ,
117
118
SslApplicationProtocol applicationProtocol , bool noCache , CancellationToken cancellationToken )
118
119
{
119
120
List < SslApplicationProtocol > applicationProtocols = null ;
@@ -122,36 +123,36 @@ internal Task<TcpServerConnection> GetServerConnection(ProxyServer server, Sessi
122
123
applicationProtocols = new List < SslApplicationProtocol > { applicationProtocol } ;
123
124
}
124
125
125
- return GetServerConnection ( server , args , isConnect , applicationProtocols , noCache , cancellationToken ) ;
126
+ return GetServerConnection ( server , session , isConnect , applicationProtocols , noCache , cancellationToken ) ;
126
127
}
127
128
128
129
/// <summary>
129
130
/// Create a server connection.
130
131
/// </summary>
131
- /// <param name="args ">The session event arguments.</param>
132
+ /// <param name="session ">The session event arguments.</param>
132
133
/// <param name="isConnect">Is this a CONNECT request.</param>
133
134
/// <param name="applicationProtocols"></param>
134
135
/// <param name="cancellationToken">The cancellation token for this async task.</param>
135
136
/// <returns></returns>
136
- internal async Task < TcpServerConnection > GetServerConnection ( ProxyServer server , SessionEventArgsBase args , bool isConnect ,
137
+ internal async Task < TcpServerConnection > GetServerConnection ( ProxyServer server , SessionEventArgsBase session , bool isConnect ,
137
138
List < SslApplicationProtocol > applicationProtocols , bool noCache , CancellationToken cancellationToken )
138
139
{
139
140
ExternalProxy customUpStreamProxy = null ;
140
141
141
- bool isHttps = args . IsHttps ;
142
+ bool isHttps = session . IsHttps ;
142
143
if ( server . GetCustomUpStreamProxyFunc != null )
143
144
{
144
- customUpStreamProxy = await server . GetCustomUpStreamProxyFunc ( args ) ;
145
+ customUpStreamProxy = await server . GetCustomUpStreamProxyFunc ( session ) ;
145
146
}
146
147
147
- args . CustomUpStreamProxyUsed = customUpStreamProxy ;
148
+ session . CustomUpStreamProxyUsed = customUpStreamProxy ;
148
149
149
150
return await GetServerConnection (
150
- args . WebSession . Request . RequestUri . Host ,
151
- args . WebSession . Request . RequestUri . Port ,
152
- args . WebSession . Request . HttpVersion ,
151
+ session . WebSession . Request . RequestUri . Host ,
152
+ session . WebSession . Request . RequestUri . Port ,
153
+ session . WebSession . Request . HttpVersion ,
153
154
isHttps , applicationProtocols , isConnect ,
154
- server , args . WebSession . UpStreamEndPoint ?? server . UpStreamEndPoint ,
155
+ server , session , session . WebSession . UpStreamEndPoint ?? server . UpStreamEndPoint ,
155
156
customUpStreamProxy ?? ( isHttps ? server . UpStreamHttpsProxy : server . UpStreamHttpProxy ) ,
156
157
noCache , cancellationToken ) ;
157
158
}
@@ -172,7 +173,7 @@ internal async Task<TcpServerConnection> GetServerConnection(ProxyServer server,
172
173
/// <returns></returns>
173
174
internal async Task < TcpServerConnection > GetServerConnection ( string remoteHostName , int remotePort ,
174
175
Version httpVersion , bool isHttps , List < SslApplicationProtocol > applicationProtocols , bool isConnect ,
175
- ProxyServer proxyServer , IPEndPoint upStreamEndPoint , ExternalProxy externalProxy ,
176
+ ProxyServer proxyServer , SessionEventArgsBase session , IPEndPoint upStreamEndPoint , ExternalProxy externalProxy ,
176
177
bool noCache , CancellationToken cancellationToken )
177
178
{
178
179
var cacheKey = GetConnectionCacheKey ( remoteHostName , remotePort ,
@@ -203,7 +204,7 @@ internal async Task<TcpServerConnection> GetServerConnection(string remoteHostNa
203
204
}
204
205
205
206
var connection = await createServerConnection ( remoteHostName , remotePort , httpVersion , isHttps ,
206
- applicationProtocols , isConnect , proxyServer , upStreamEndPoint , externalProxy , cancellationToken ) ;
207
+ applicationProtocols , isConnect , proxyServer , session , upStreamEndPoint , externalProxy , cancellationToken ) ;
207
208
208
209
connection . CacheKey = cacheKey ;
209
210
@@ -220,13 +221,14 @@ internal async Task<TcpServerConnection> GetServerConnection(string remoteHostNa
220
221
/// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param>
221
222
/// <param name="isConnect">Is this a CONNECT request.</param>
222
223
/// <param name="proxyServer">The current ProxyServer instance.</param>
224
+ /// <param name="session">The http session.</param>
223
225
/// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
224
226
/// <param name="externalProxy">The external proxy to make request via.</param>
225
227
/// <param name="cancellationToken">The cancellation token for this async task.</param>
226
228
/// <returns></returns>
227
229
private async Task < TcpServerConnection > createServerConnection ( string remoteHostName , int remotePort ,
228
230
Version httpVersion , bool isHttps , List < SslApplicationProtocol > applicationProtocols , bool isConnect ,
229
- ProxyServer proxyServer , IPEndPoint upStreamEndPoint , ExternalProxy externalProxy ,
231
+ ProxyServer proxyServer , SessionEventArgsBase session , IPEndPoint upStreamEndPoint , ExternalProxy externalProxy ,
230
232
CancellationToken cancellationToken )
231
233
{
232
234
//deny connection to proxy end points to avoid infinite connection loop.
@@ -282,16 +284,37 @@ private async Task<TcpServerConnection> createServerConnection(string remoteHost
282
284
tcpClient . Client . SetSocketOption ( SocketOptionLevel . Socket , SocketOptionName . ReuseAddress , true ) ;
283
285
}
284
286
285
- // If this proxy uses another external proxy then create a tunnel request for HTTP/HTTPS connections
286
- if ( useUpstreamProxy )
287
+ var hostname = useUpstreamProxy ? externalProxy . HostName : remoteHostName ;
288
+ var port = useUpstreamProxy ? externalProxy . Port : remotePort ;
289
+
290
+ var ipHostEntry = await Dns . GetHostEntryAsync ( hostname ) ;
291
+ if ( ipHostEntry == null || ipHostEntry . AddressList . Length == 0 )
287
292
{
288
- await tcpClient . ConnectAsync ( externalProxy . HostName , externalProxy . Port ) ;
293
+ throw new Exception ( $ "Could not resolve the hostname { hostname } " ) ;
289
294
}
290
- else
295
+
296
+ session . TimeLine [ "Dns Resolved" ] = DateTime . Now ;
297
+
298
+ var ipAddresses = ipHostEntry . AddressList ;
299
+
300
+ for ( int i = 0 ; i < ipAddresses . Length ; i ++ )
291
301
{
292
- await tcpClient . ConnectAsync ( remoteHostName , remotePort ) ;
302
+ try
303
+ {
304
+ await tcpClient . ConnectAsync ( ipAddresses [ i ] , port ) ;
305
+ break ;
306
+ }
307
+ catch ( Exception e )
308
+ {
309
+ if ( i == ipAddresses . Length - 1 )
310
+ {
311
+ throw new Exception ( $ "Could not establish connection to { hostname } ", e ) ;
312
+ }
313
+ }
293
314
}
294
315
316
+ session . TimeLine [ "Connection Established" ] = DateTime . Now ;
317
+
295
318
await proxyServer . InvokeConnectionCreateEvent ( tcpClient , false ) ;
296
319
297
320
stream = new CustomBufferedStream ( tcpClient . GetStream ( ) , proxyServer . BufferPool , proxyServer . BufferSize ) ;
@@ -347,6 +370,7 @@ private async Task<TcpServerConnection> createServerConnection(string remoteHost
347
370
#if NETCOREAPP2_1
348
371
negotiatedApplicationProtocol = sslStream . NegotiatedApplicationProtocol ;
349
372
#endif
373
+ session . TimeLine [ "HTTPS Established" ] = DateTime . Now ;
350
374
}
351
375
}
352
376
catch ( Exception )
0 commit comments