@@ -22,6 +22,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
2222 /// </summary>
2323 internal class TcpConnectionFactory : IDisposable
2424 {
25+
2526 //Tcp server connection pool cache
2627 private readonly ConcurrentDictionary < string , ConcurrentQueue < TcpServerConnection > > cache
2728 = new ConcurrentDictionary < string , ConcurrentQueue < TcpServerConnection > > ( ) ;
@@ -74,10 +75,10 @@ internal string GetConnectionCacheKey(string remoteHostName, int remotePort,
7475 /// <summary>
7576 /// Gets the connection cache key.
7677 /// </summary>
77- /// <param name="args ">The session event arguments.</param>
78+ /// <param name="session ">The session event arguments.</param>
7879 /// <param name="applicationProtocol"></param>
7980 /// <returns></returns>
80- internal async Task < string > GetConnectionCacheKey ( ProxyServer server , SessionEventArgsBase args ,
81+ internal async Task < string > GetConnectionCacheKey ( ProxyServer server , SessionEventArgsBase session ,
8182 SslApplicationProtocol applicationProtocol )
8283 {
8384 List < SslApplicationProtocol > applicationProtocols = null ;
@@ -88,32 +89,32 @@ internal async Task<string> GetConnectionCacheKey(ProxyServer server, SessionEve
8889
8990 ExternalProxy customUpStreamProxy = null ;
9091
91- bool isHttps = args . IsHttps ;
92+ bool isHttps = session . IsHttps ;
9293 if ( server . GetCustomUpStreamProxyFunc != null )
9394 {
94- customUpStreamProxy = await server . GetCustomUpStreamProxyFunc ( args ) ;
95+ customUpStreamProxy = await server . GetCustomUpStreamProxyFunc ( session ) ;
9596 }
9697
97- args . CustomUpStreamProxyUsed = customUpStreamProxy ;
98+ session . CustomUpStreamProxyUsed = customUpStreamProxy ;
9899
99100 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 ,
102103 isHttps , applicationProtocols ,
103- server , args . WebSession . UpStreamEndPoint ?? server . UpStreamEndPoint ,
104+ server , session . WebSession . UpStreamEndPoint ?? server . UpStreamEndPoint ,
104105 customUpStreamProxy ?? ( isHttps ? server . UpStreamHttpsProxy : server . UpStreamHttpProxy ) ) ;
105106 }
106107
107108
108109 /// <summary>
109110 /// Create a server connection.
110111 /// </summary>
111- /// <param name="args ">The session event arguments.</param>
112+ /// <param name="session ">The session event arguments.</param>
112113 /// <param name="isConnect">Is this a CONNECT request.</param>
113114 /// <param name="applicationProtocol"></param>
114115 /// <param name="cancellationToken">The cancellation token for this async task.</param>
115116 /// <returns></returns>
116- internal Task < TcpServerConnection > GetServerConnection ( ProxyServer server , SessionEventArgsBase args , bool isConnect ,
117+ internal Task < TcpServerConnection > GetServerConnection ( ProxyServer server , SessionEventArgsBase session , bool isConnect ,
117118 SslApplicationProtocol applicationProtocol , bool noCache , CancellationToken cancellationToken )
118119 {
119120 List < SslApplicationProtocol > applicationProtocols = null ;
@@ -122,36 +123,36 @@ internal Task<TcpServerConnection> GetServerConnection(ProxyServer server, Sessi
122123 applicationProtocols = new List < SslApplicationProtocol > { applicationProtocol } ;
123124 }
124125
125- return GetServerConnection ( server , args , isConnect , applicationProtocols , noCache , cancellationToken ) ;
126+ return GetServerConnection ( server , session , isConnect , applicationProtocols , noCache , cancellationToken ) ;
126127 }
127128
128129 /// <summary>
129130 /// Create a server connection.
130131 /// </summary>
131- /// <param name="args ">The session event arguments.</param>
132+ /// <param name="session ">The session event arguments.</param>
132133 /// <param name="isConnect">Is this a CONNECT request.</param>
133134 /// <param name="applicationProtocols"></param>
134135 /// <param name="cancellationToken">The cancellation token for this async task.</param>
135136 /// <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 ,
137138 List < SslApplicationProtocol > applicationProtocols , bool noCache , CancellationToken cancellationToken )
138139 {
139140 ExternalProxy customUpStreamProxy = null ;
140141
141- bool isHttps = args . IsHttps ;
142+ bool isHttps = session . IsHttps ;
142143 if ( server . GetCustomUpStreamProxyFunc != null )
143144 {
144- customUpStreamProxy = await server . GetCustomUpStreamProxyFunc ( args ) ;
145+ customUpStreamProxy = await server . GetCustomUpStreamProxyFunc ( session ) ;
145146 }
146147
147- args . CustomUpStreamProxyUsed = customUpStreamProxy ;
148+ session . CustomUpStreamProxyUsed = customUpStreamProxy ;
148149
149150 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 ,
153154 isHttps , applicationProtocols , isConnect ,
154- server , args . WebSession . UpStreamEndPoint ?? server . UpStreamEndPoint ,
155+ server , session , session . WebSession . UpStreamEndPoint ?? server . UpStreamEndPoint ,
155156 customUpStreamProxy ?? ( isHttps ? server . UpStreamHttpsProxy : server . UpStreamHttpProxy ) ,
156157 noCache , cancellationToken ) ;
157158 }
@@ -172,7 +173,7 @@ internal async Task<TcpServerConnection> GetServerConnection(ProxyServer server,
172173 /// <returns></returns>
173174 internal async Task < TcpServerConnection > GetServerConnection ( string remoteHostName , int remotePort ,
174175 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 ,
176177 bool noCache , CancellationToken cancellationToken )
177178 {
178179 var cacheKey = GetConnectionCacheKey ( remoteHostName , remotePort ,
@@ -203,7 +204,7 @@ internal async Task<TcpServerConnection> GetServerConnection(string remoteHostNa
203204 }
204205
205206 var connection = await createServerConnection ( remoteHostName , remotePort , httpVersion , isHttps ,
206- applicationProtocols , isConnect , proxyServer , upStreamEndPoint , externalProxy , cancellationToken ) ;
207+ applicationProtocols , isConnect , proxyServer , session , upStreamEndPoint , externalProxy , cancellationToken ) ;
207208
208209 connection . CacheKey = cacheKey ;
209210
@@ -220,13 +221,14 @@ internal async Task<TcpServerConnection> GetServerConnection(string remoteHostNa
220221 /// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param>
221222 /// <param name="isConnect">Is this a CONNECT request.</param>
222223 /// <param name="proxyServer">The current ProxyServer instance.</param>
224+ /// <param name="session">The http session.</param>
223225 /// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
224226 /// <param name="externalProxy">The external proxy to make request via.</param>
225227 /// <param name="cancellationToken">The cancellation token for this async task.</param>
226228 /// <returns></returns>
227229 private async Task < TcpServerConnection > createServerConnection ( string remoteHostName , int remotePort ,
228230 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 ,
230232 CancellationToken cancellationToken )
231233 {
232234 //deny connection to proxy end points to avoid infinite connection loop.
@@ -282,16 +284,37 @@ private async Task<TcpServerConnection> createServerConnection(string remoteHost
282284 tcpClient . Client . SetSocketOption ( SocketOptionLevel . Socket , SocketOptionName . ReuseAddress , true ) ;
283285 }
284286
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 )
287292 {
288- await tcpClient . ConnectAsync ( externalProxy . HostName , externalProxy . Port ) ;
293+ throw new Exception ( $ "Could not resolve the hostname { hostname } " ) ;
289294 }
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 ++ )
291301 {
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+ }
293314 }
294315
316+ session . TimeLine [ "Connection Established" ] = DateTime . Now ;
317+
295318 await proxyServer . InvokeConnectionCreateEvent ( tcpClient , false ) ;
296319
297320 stream = new CustomBufferedStream ( tcpClient . GetStream ( ) , proxyServer . BufferPool , proxyServer . BufferSize ) ;
@@ -347,6 +370,7 @@ private async Task<TcpServerConnection> createServerConnection(string remoteHost
347370#if NETCOREAPP2_1
348371 negotiatedApplicationProtocol = sslStream . NegotiatedApplicationProtocol ;
349372#endif
373+ session . TimeLine [ "HTTPS Established" ] = DateTime . Now ;
350374 }
351375 }
352376 catch ( Exception )
0 commit comments