Skip to content

Commit

Permalink
Change connection logic
Browse files Browse the repository at this point in the history
  • Loading branch information
liveans committed Feb 28, 2024
1 parent 47d7f27 commit 7aa734f
Showing 1 changed file with 54 additions and 34 deletions.
88 changes: 54 additions & 34 deletions src/libraries/System.Net.Requests/src/System/Net/HttpWebRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1713,60 +1713,80 @@ await Dns.GetHostAddressesAsync(context.DnsEndPoint.Host, cancellationToken).Con
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, keepAlive.Interval);
}

BindHelper(servicePoint, addresses, socket, context.DnsEndPoint.Port);
static void BindHelper(ServicePoint servicePoint, IPAddress[] addresses, Socket socket, int port)
{
if (servicePoint.BindIPEndPointDelegate is null)
{
return;
}
socket.NoDelay = !servicePoint.UseNagleAlgorithm;

const int MaxRetries = 100;
if (servicePoint.BindIPEndPointDelegate is not null)
{
foreach (IPAddress address in addresses)
{
int retryCount = 0;
for (; retryCount < MaxRetries; retryCount++)
IPEndPoint remoteEp = new IPEndPoint(address, context.DnsEndPoint.Port);
BindHelper(servicePoint, remoteEp, socket);
if (parameters.Async)
{
await socket.ConnectAsync(remoteEp, cancellationToken).ConfigureAwait(false);
}
else
{
IPEndPoint? endPoint = servicePoint.BindIPEndPointDelegate(servicePoint, new IPEndPoint(address, port), retryCount);
if (endPoint is null) // Get other address to try
using (cancellationToken.UnsafeRegister(s => ((Socket)s!).Dispose(), socket))
{
break;
socket.Connect(remoteEp);
}

try
{
socket.Bind(endPoint);
return; // Bind successful, exit loops.
}
catch
{
continue;
}
// Throw in case cancellation caused the socket to be disposed after the Connect completed
cancellationToken.ThrowIfCancellationRequested();
}
}
}
static void BindHelper(ServicePoint servicePoint, IPEndPoint remoteEp, Socket socket)
{
const int MaxRetries = 100;
int retryCount = 0;
for (; retryCount < MaxRetries; retryCount++)
{
IPEndPoint? endPoint = servicePoint.BindIPEndPointDelegate!(servicePoint, remoteEp, retryCount);
if (endPoint is null) // Get other address to try
{
return;
}

if (retryCount >= MaxRetries)
try
{
socket.Bind(endPoint);
return;
}
catch
{
throw new OverflowException(SR.net_maximumbindretries);
continue;
}
}

if (retryCount >= MaxRetries)
{
throw new OverflowException(SR.net_maximumbindretries);
}
}
}

socket.NoDelay = !(parameters.ServicePoint?.UseNagleAlgorithm) ?? true;

if (parameters.Async)
else
{
await socket.ConnectAsync(addresses, context.DnsEndPoint.Port, cancellationToken).ConfigureAwait(false);
socket.NoDelay = true;
}
else

if (!socket.Connected)
{
using (cancellationToken.UnsafeRegister(s => ((Socket)s!).Dispose(), socket))
if (parameters.Async)
{
socket.Connect(addresses, context.DnsEndPoint.Port);
await socket.ConnectAsync(addresses, context.DnsEndPoint.Port, cancellationToken).ConfigureAwait(false);
}
else
{
using (cancellationToken.UnsafeRegister(s => ((Socket)s!).Dispose(), socket))
{
socket.Connect(addresses, context.DnsEndPoint.Port);
}

// Throw in case cancellation caused the socket to be disposed after the Connect completed
cancellationToken.ThrowIfCancellationRequested();
// Throw in case cancellation caused the socket to be disposed after the Connect completed
cancellationToken.ThrowIfCancellationRequested();
}
}

if (parameters.ReadWriteTimeout > 0) // default is 5 minutes, so this is generally going to be true
Expand Down

0 comments on commit 7aa734f

Please sign in to comment.