Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.

Commit 40c978d

Browse files
Merge pull request #446 from justcoding121/master
Fix prefetch connection leak
2 parents 02ea4ae + d0f5320 commit 40c978d

File tree

4 files changed

+55
-33
lines changed

4 files changed

+55
-33
lines changed

Titanium.Web.Proxy/ExplicitClientHandler.cs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,12 @@ await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response,
150150
}
151151

152152
SslStream sslStream = null;
153+
154+
//don't pass cancellation token here
155+
//it could cause floating server connections when client exits
153156
prefetchConnectionTask = getServerConnection(connectArgs, true,
154-
null, false, cancellationToken);
157+
null, false, CancellationToken.None);
158+
155159
try
156160
{
157161
sslStream = new SslStream(clientStream);
@@ -250,7 +254,7 @@ await TcpHelper.SendRaw(clientStream, connection.Stream, BufferPool, BufferSize,
250254
{
251255
await tcpConnectionFactory.Release(connection, true);
252256
}
253-
calledRequestHandler = true;
257+
254258
return;
255259
}
256260
}
@@ -331,19 +335,27 @@ await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientS
331335
}
332336
finally
333337
{
338+
if (!calledRequestHandler
339+
&& prefetchConnectionTask != null)
340+
{
341+
TcpServerConnection prefetchedConnection = null;
342+
try
343+
{
344+
prefetchedConnection = await prefetchConnectionTask;
345+
346+
}
347+
finally
348+
{
349+
await tcpConnectionFactory.Release(prefetchedConnection, closeServerConnection);
350+
}
351+
}
352+
334353
clientStream.Dispose();
335354

336355
if (!cancellationTokenSource.IsCancellationRequested)
337356
{
338357
cancellationTokenSource.Cancel();
339358
}
340-
341-
if (!calledRequestHandler
342-
&& prefetchConnectionTask != null)
343-
{
344-
var connection = await prefetchConnectionTask;
345-
await tcpConnectionFactory.Release(connection, closeServerConnection);
346-
}
347359
}
348360
}
349361
}

Titanium.Web.Proxy/ProxyServer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -815,12 +815,12 @@ private Policy retryPolicy<T>() where T : Exception
815815
.RetryAsync(retries,
816816
onRetryAsync: async (ex, i, context) =>
817817
{
818-
if (context.ContainsKey("connection"))
818+
if (context["connection"] != null)
819819
{
820820
//close connection on error
821821
var connection = (TcpServerConnection)context["connection"];
822822
await tcpConnectionFactory.Release(connection, true);
823-
context.Remove("connection");
823+
context["connection"] = null;
824824
}
825825

826826
});

Titanium.Web.Proxy/RequestHandler.cs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,14 @@ private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientCon
5858
CancellationTokenSource cancellationTokenSource, string httpsConnectHostname, ConnectRequest connectRequest,
5959
Task<TcpServerConnection> prefetchConnectionTask = null)
6060
{
61-
var cancellationToken = cancellationTokenSource.Token;
62-
6361
var prefetchTask = prefetchConnectionTask;
6462
TcpServerConnection connection = null;
6563
bool closeServerConnection = false;
6664

6765
try
6866
{
67+
var cancellationToken = cancellationTokenSource.Token;
68+
6969
// Loop through each subsequest request on this particular client connection
7070
// (assuming HTTP connection is kept alive by client)
7171
while (true)
@@ -204,21 +204,13 @@ await clientStreamWriter.WriteResponseAsync(args.WebSession.Response,
204204
connection = null;
205205
}
206206

207-
var contextData = new Dictionary<string, object>();
208-
if (connection != null)
209-
{
210-
contextData.Add("connection", connection);
211-
}
212-
213207
//for connection pool retry fails until cache is exhausted
214208
await retryPolicy<ServerConnectionException>().ExecuteAsync(async (context) =>
215209
{
216-
217-
connection = context.ContainsKey("connection")?
218-
(TcpServerConnection)context["connection"]
219-
: await getServerConnection(args, false,
220-
clientConnection.NegotiatedApplicationProtocol,
221-
false, cancellationToken);
210+
connection = context["connection"] as TcpServerConnection ??
211+
await getServerConnection(args, false,
212+
clientConnection.NegotiatedApplicationProtocol,
213+
false, cancellationToken);
222214

223215
context["connection"] = connection;
224216

@@ -235,8 +227,7 @@ await handleWebSocketUpgrade(httpCmd, args, request,
235227
// construct the web request that we are going to issue on behalf of the client.
236228
await handleHttpSessionRequestInternal(connection, args);
237229

238-
}, contextData);
239-
230+
}, new Dictionary<string, object> { { "connection", connection } });
240231

241232
//user requested
242233
if (args.WebSession.CloseServerConnection)
@@ -288,12 +279,21 @@ await handleWebSocketUpgrade(httpCmd, args, request,
288279
finally
289280
{
290281
await tcpConnectionFactory.Release(connection,
291-
closeServerConnection);
282+
closeServerConnection);
283+
292284

293285
if (prefetchTask != null)
294286
{
295-
await tcpConnectionFactory.Release(await prefetchTask,
296-
closeServerConnection);
287+
TcpServerConnection prefetchedConnection = null;
288+
try
289+
{
290+
prefetchedConnection = await prefetchTask;
291+
292+
}
293+
finally
294+
{
295+
await tcpConnectionFactory.Release(prefetchedConnection, closeServerConnection);
296+
}
297297
}
298298
}
299299
}

Titanium.Web.Proxy/TransparentClientHandler.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,11 @@ private async Task handleClient(TransparentProxyEndPoint endPoint, TcpClientConn
6363

6464
if (endPoint.DecryptSsl && args.DecryptSsl)
6565
{
66+
//don't pass cancellation token here
67+
//it could cause floating server connections when client exits
6668
prefetchConnectionTask = tcpConnectionFactory.GetClient(httpsHostName, endPoint.Port,
6769
null, true, null, false, this,
68-
UpStreamEndPoint, UpStreamHttpsProxy, false, cancellationToken);
70+
UpStreamEndPoint, UpStreamHttpsProxy, false, CancellationToken.None);
6971

7072
SslStream sslStream = null;
7173

@@ -163,8 +165,16 @@ await handleHttpSessionRequest(endPoint, clientConnection, clientStream, clientS
163165
if (!calledRequestHandler
164166
&& prefetchConnectionTask != null)
165167
{
166-
var connection = await prefetchConnectionTask;
167-
await tcpConnectionFactory.Release(connection, closeServerConnection);
168+
TcpServerConnection prefetchedConnection = null;
169+
try
170+
{
171+
prefetchedConnection = await prefetchConnectionTask;
172+
173+
}
174+
finally
175+
{
176+
await tcpConnectionFactory.Release(prefetchedConnection, closeServerConnection);
177+
}
168178
}
169179

170180
clientStream.Dispose();

0 commit comments

Comments
 (0)