Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement more ServicePoint properties #97537

Merged
merged 41 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
97d4730
Implement more ServicePoint properties
liveans Jan 26, 2024
b9fdca4
Implement more properties
liveans Jan 31, 2024
69055bb
Make implementation correct
liveans Feb 1, 2024
3591f1a
Change UseNagleAlgorithm default to false
liveans Feb 1, 2024
d861319
Update src/libraries/System.Net.Requests/src/System/Net/HttpWebReques…
liveans Feb 5, 2024
340d7e4
Merge branch 'main' into httpwebrequest-implement-more-property
liveans Feb 5, 2024
043647c
Review feedback
liveans Feb 9, 2024
f843727
Start implement DnsRoundRobin
liveans Feb 9, 2024
f296718
Merge branch 'main' into httpwebrequest-implement-more-property
liveans Feb 9, 2024
c61e5ed
remove passing parameter over ctor for static prop
liveans Feb 9, 2024
30bd75c
Change DefaultMaximumErrorResponseLength default value to -1
liveans Feb 9, 2024
cf3003d
Update ServicePoint parameter passing, implement Certificate on Servi…
liveans Feb 11, 2024
33abd52
Change servicePoint to nullable parameter again and fix bind test
liveans Feb 12, 2024
3033c4a
Change static variable test to RemoteExecutor
liveans Feb 12, 2024
2ee83de
Fix bind throw test for linux and add async to remote executor
liveans Feb 12, 2024
3be4532
Update src/libraries/System.Net.Requests/src/System/Net/HttpWebReques…
liveans Feb 15, 2024
f1ea117
Review feedback
liveans Feb 15, 2024
9260105
Merge branch 'httpwebrequest-implement-more-property' of github.com:l…
liveans Feb 15, 2024
8d28f97
Skip throw bind on Linux
liveans Feb 16, 2024
970bbb1
Add disable reuseaddr
liveans Feb 18, 2024
d9ef66d
Revert "Add disable reuseaddr"
liveans Feb 18, 2024
67655be
some changes on tests
liveans Feb 18, 2024
86f156c
Refactor GetResponseStream method to use TruncatedReadStream
liveans Feb 20, 2024
ca6b379
Fix tests
liveans Feb 20, 2024
89040f6
Convert static property test to RemoteExecutor
liveans Feb 20, 2024
66f7abd
Delete unused NameResolution project from Requests csproj
liveans Feb 20, 2024
50a0f2f
Revert "Delete unused NameResolution project from Requests csproj"
liveans Feb 20, 2024
f9cb55f
Fix socket shutdown
liveans Feb 20, 2024
8c3f0c4
simple changes on test
liveans Feb 20, 2024
a5c136a
Change sync call inside RemoteExecutor
liveans Feb 22, 2024
1d9708d
Update src/libraries/System.Net.Requests/src/System/Net/HttpWebRespon…
liveans Feb 27, 2024
ab78cd1
Merge branch 'main' into httpwebrequest-implement-more-property
liveans Feb 27, 2024
06f8d95
Apply suggestions from code review
liveans Feb 28, 2024
05af2e0
Review feedback
liveans Feb 28, 2024
47d7f27
Change exception handling on remote executor test
liveans Feb 28, 2024
7aa734f
Change connection logic
liveans Feb 28, 2024
657a334
Revert "Change exception handling on remote executor test"
liveans Feb 28, 2024
06f1324
Add forgotten disposal
liveans Feb 28, 2024
520ba04
Revert "Change connection logic"
liveans Feb 28, 2024
a9368bf
Review feedback
liveans Feb 28, 2024
f8cdea3
Apply suggestions from code review
liveans Mar 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
<Reference Include="System.Diagnostics.Tracing" />
<Reference Include="System.Memory" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.NameResolution" />
<Reference Include="System.Net.Primitives" />
<Reference Include="System.Net.Security" />
<Reference Include="System.Net.Sockets" />
Expand Down
56 changes: 52 additions & 4 deletions src/libraries/System.Net.Requests/src/System/Net/HttpWebRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Cache;
using System.Net.Http;
using System.Net.Http.Headers;
Expand Down Expand Up @@ -806,10 +807,12 @@ public Version ProtocolVersion
if (value.Equals(HttpVersion.Version11))
{
IsVersionHttp10 = false;
ServicePoint.ProtocolVersion = HttpVersion.Version11;
MihaZupan marked this conversation as resolved.
Show resolved Hide resolved
}
else if (value.Equals(HttpVersion.Version10))
{
IsVersionHttp10 = true;
ServicePoint.ProtocolVersion = HttpVersion.Version10;
}
else
{
Expand Down Expand Up @@ -1196,7 +1199,7 @@ private async Task<WebResponse> SendRequest(bool async)

HttpResponseMessage responseMessage = await _sendRequestTask.ConfigureAwait(false);

HttpWebResponse response = new HttpWebResponse(responseMessage, _requestUri, _cookieContainer);
HttpWebResponse response = new HttpWebResponse(responseMessage, _requestUri, _cookieContainer, DefaultMaximumErrorResponseLength);

int maxSuccessStatusCode = AllowAutoRedirect ? 299 : 399;
if ((int)response.StatusCode > maxSuccessStatusCode || (int)response.StatusCode < 200)
Expand Down Expand Up @@ -1621,6 +1624,13 @@ private static HttpClient CreateHttpClient(HttpClientParameters parameters, Http
handler.UseCookies = false;
}

if (parameters.ServicePoint is { } servicePoint)
{
handler.MaxConnectionsPerServer = servicePoint.ConnectionLimit;
handler.PooledConnectionIdleTimeout = servicePoint.MaxIdleTime == -1 ? Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromMilliseconds(servicePoint.MaxIdleTime);
MihaZupan marked this conversation as resolved.
Show resolved Hide resolved
handler.PooledConnectionLifetime = servicePoint.ConnectionLeaseTimeout == -1 ? Threading.Timeout.InfiniteTimeSpan : TimeSpan.FromMilliseconds(servicePoint.ConnectionLeaseTimeout);
liveans marked this conversation as resolved.
Show resolved Hide resolved
liveans marked this conversation as resolved.
Show resolved Hide resolved
}

Debug.Assert(handler.UseProxy); // Default of handler.UseProxy is true.
Debug.Assert(handler.Proxy == null); // Default of handler.Proxy is null.

Expand Down Expand Up @@ -1669,6 +1679,9 @@ private static HttpClient CreateHttpClient(HttpClientParameters parameters, Http
{
var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

// Start resolve dns task
Task<IPAddress[]> addressesTask = Dns.GetHostAddressesAsync(context.DnsEndPoint.Host, cancellationToken);
IPAddress[]? addresses = null;
liveans marked this conversation as resolved.
Show resolved Hide resolved
try
{
if (parameters.ServicePoint is { } servicePoint)
Expand All @@ -1684,19 +1697,54 @@ private static HttpClient CreateHttpClient(HttpClientParameters parameters, Http
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, keepAlive.Time);
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, keepAlive.Interval);
}

if (servicePoint.BindIPEndPointDelegate != null)
{
addresses ??= await addressesTask.ConfigureAwait(false);
foreach (IPAddress address in addresses)
{
int retryCount = 0;
for (; retryCount < int.MaxValue; retryCount++)
{
IPEndPoint? endPoint = servicePoint.BindIPEndPointDelegate(servicePoint, new IPEndPoint(address, context.DnsEndPoint.Port), retryCount);
if (endPoint != null)
{
try
{
socket.Bind(endPoint);
break;
}
catch
{
continue;
}
}
}
MihaZupan marked this conversation as resolved.
Show resolved Hide resolved

if (retryCount == int.MaxValue)
{
throw new OverflowException(); //TODO (aaksoy): Add SR for this.
liveans marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

if (servicePoint.UseNagleAlgorithm is not true)
{
socket.NoDelay = true;
}
liveans marked this conversation as resolved.
Show resolved Hide resolved
}

socket.NoDelay = true;
addresses ??= await addressesTask.ConfigureAwait(false);

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

// Throw in case cancellation caused the socket to be disposed after the Connect completed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class HttpWebResponse : WebResponse, ISerializable
private WebHeaderCollection? _webHeaderCollection;
private string? _characterSet;
private readonly bool _isVersionHttp11 = true;
private readonly int _maxErrorResponseLength = -1;

[Obsolete("This API supports the .NET infrastructure and is not intended to be used directly from your code.", true)]
[EditorBrowsable(EditorBrowsableState.Never)]
Expand Down Expand Up @@ -53,10 +54,11 @@ protected override void GetObjectData(SerializationInfo serializationInfo, Strea
throw new PlatformNotSupportedException();
}

internal HttpWebResponse(HttpResponseMessage _message, Uri requestUri, CookieContainer? cookieContainer)
internal HttpWebResponse(HttpResponseMessage _message, Uri requestUri, CookieContainer? cookieContainer, int maxErrorResponseLength)
{
_httpResponseMessage = _message;
_requestUri = requestUri;
_maxErrorResponseLength = maxErrorResponseLength;

// Match Desktop behavior. If the request didn't set a CookieContainer, we don't populate the response's CookieCollection.
if (cookieContainer != null)
Expand Down Expand Up @@ -337,7 +339,28 @@ public override Stream GetResponseStream()
CheckDisposed();
if (_httpResponseMessage.Content != null)
{
return _httpResponseMessage.Content.ReadAsStream();
Stream contentStream = _httpResponseMessage.Content.ReadAsStream();
if (_maxErrorResponseLength == -1 || StatusCode <= (HttpStatusCode)399)
liveans marked this conversation as resolved.
Show resolved Hide resolved
{
return contentStream;
}

MemoryStream memoryStream = new MemoryStream();
byte[] buffer = new byte[1024];
int readLength = 0;

while (readLength < _maxErrorResponseLength)
{
int len = contentStream.Read(buffer, 0, Math.Min(_maxErrorResponseLength - readLength, buffer.Length));
if (len == 0)
{
break;
}
memoryStream.Write(buffer, 0, len);
readLength += len;
}
liveans marked this conversation as resolved.
Show resolved Hide resolved

return memoryStream;
}

return Stream.Null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public static int MaxServicePointIdleTime
}
}

public static bool UseNagleAlgorithm { get; set; } = true;
public static bool UseNagleAlgorithm { get; set; }

public static bool Expect100Continue { get; set; } = true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public static void ServerCertificateValidationCallback_Roundtrips()
[Fact]
public static void UseNagleAlgorithm_Roundtrips()
{
Assert.True(ServicePointManager.UseNagleAlgorithm);
Assert.False(ServicePointManager.UseNagleAlgorithm);
try
{
ServicePointManager.UseNagleAlgorithm = false;
Expand Down Expand Up @@ -325,7 +325,7 @@ public static void FindServicePoint_ReturnedServicePointMatchesExpectedValues()
Assert.Equal(new Version(1, 1), sp.ProtocolVersion);
Assert.Equal(-1, sp.ReceiveBufferSize);
Assert.True(sp.SupportsPipelining, "SupportsPipelining");
Assert.True(sp.UseNagleAlgorithm, "UseNagleAlgorithm");
Assert.False(sp.UseNagleAlgorithm, "UseNagleAlgorithm");
}).Dispose();
}

Expand Down
Loading