Commit 40cd60cc authored by Honfika's avatar Honfika

Do not call LingerState on disposed sockets. (#107)

parent 9d037680
using Titanium.Web.Proxy.Helpers;
using System;
using System.Net.Sockets;
using System.Reflection;
using Titanium.Web.Proxy.Helpers;
namespace Titanium.Web.Proxy.Extensions
{
internal static class TcpExtensions
{
private static readonly Func<Socket, bool> socketCleanedUpGetter;
static TcpExtensions()
{
var property = typeof(Socket).GetProperty("CleanedUp", BindingFlags.NonPublic | BindingFlags.Instance);
if (property != null)
{
var method = property.GetMethod;
if (method != null && method.ReturnType == typeof(bool))
{
socketCleanedUpGetter = (Func<Socket, bool>)Delegate.CreateDelegate(typeof(Func<Socket, bool>), method);
}
}
}
/// <summary>
/// Gets the local port from a native TCP row object.
......@@ -24,5 +41,30 @@ namespace Titanium.Web.Proxy.Extensions
{
return (tcpRow.remotePort1 << 8) + tcpRow.remotePort2 + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16);
}
internal static void CloseSocket(this TcpClient tcpClient)
{
if (tcpClient == null)
{
return;
}
try
{
//This line is important!
//contributors please don't remove it without discussion
//It helps to avoid eventual deterioration of performance due to TCP port exhaustion
//due to default TCP CLOSE_WAIT timeout for 4 minutes
if (socketCleanedUpGetter == null || !socketCleanedUpGetter(tcpClient.Client))
{
tcpClient.LingerState = new LingerOption(true, 0);
}
tcpClient.Close();
}
catch
{
}
}
}
}
......@@ -111,6 +111,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
/// <param name="clientStream"></param>
/// <param name="serverStream"></param>
/// <param name="bufferSize"></param>
/// <param name="onDataSend"></param>
/// <param name="onDataReceive"></param>
/// <returns></returns>
......
......@@ -2,6 +2,7 @@
using System;
using System.Net;
using System.Net.Sockets;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models;
......@@ -68,21 +69,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
Stream?.Dispose();
try
{
if (TcpClient != null)
{
//This line is important!
//contributors please don't remove it without discussion
//It helps to avoid eventual deterioration of performance due to TCP port exhaustion
//due to default TCP CLOSE_WAIT timeout for 4 minutes
TcpClient.LingerState = new LingerOption(true, 0);
TcpClient.Close();
}
}
catch
{
}
TcpClient.CloseSocket();
}
}
}
......@@ -9,6 +9,7 @@ using System.Threading;
using System.Threading.Tasks;
using StreamExtended.Network;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Helpers.WinHttp;
using Titanium.Web.Proxy.Models;
......@@ -765,22 +766,7 @@ namespace Titanium.Web.Proxy
finally
{
UpdateClientConnectionCount(false);
try
{
if (tcpClient != null)
{
//This line is important!
//contributors please don't remove it without discussion
//It helps to avoid eventual deterioration of performance due to TCP port exhaustion
//due to default TCP CLOSE_WAIT timeout for 4 minutes
tcpClient.LingerState = new LingerOption(true, 0);
tcpClient.Close();
}
}
catch
{
}
tcpClient.CloseSocket();
}
}
......
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
......@@ -177,7 +178,8 @@ namespace Titanium.Web.Proxy
}
await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize,
(buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); });
(buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); },
(buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); });
}
finally
{
......@@ -193,8 +195,17 @@ namespace Titanium.Web.Proxy
disposed = await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
httpRemoteUri.Scheme == UriSchemeHttps ? httpRemoteUri.Host : null, endPoint, connectRequest);
}
catch (IOException e)
{
ExceptionFunc(new Exception("Connection was aborted", e));
}
catch (SocketException e)
{
ExceptionFunc(new Exception("Could not connect", e));
}
catch (Exception e)
{
// is this the correct error message?
ExceptionFunc(new Exception("Error whilst authorizing request", e));
}
finally
......@@ -392,7 +403,8 @@ namespace Titanium.Web.Proxy
}
await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize,
(buffer, offset, count) => { args.OnDataSent(buffer, offset, count); }, (buffer, offset, count) => { args.OnDataReceived(buffer, offset, count); });
(buffer, offset, count) => { args.OnDataSent(buffer, offset, count); },
(buffer, offset, count) => { args.OnDataReceived(buffer, offset, count); });
args.Dispose();
break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment