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 TCP Keep-Alive for WinHttpHandler #44889

Merged
merged 7 commits into from
Nov 25, 2020

Conversation

antonfirsov
Copy link
Member

This implements the API proposal from #44025 (comment) except the [SupportedOSPlatform("windows10.0.2004")] bits. I prefer to handle that separately in a follow-up PR, since it doesn't seem to be a a functional concern, but rather focuses on managing build targets.

I decided to handle compatibility in a way consistent with other properties:
WinHttpException will be thrown, if OS doesn't support the property.

Contributes to #44025.

/cc @geoffkizer @wfurt @alnikola

@Dotnet-GitSync-Bot
Copy link
Collaborator

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@ghost
Copy link

ghost commented Nov 18, 2020

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details
Description:

This implements the API proposal from #44025 (comment) except the [SupportedOSPlatform("windows10.0.2004")] bits. I prefer to handle that separately in a follow-up PR, since it doesn't seem to be a a functional concern, but rather focuses on managing build targets.

I decided to handle compatibility in a way consistent with other properties:
WinHttpException will be thrown, if OS doesn't support the property.

Contributes to #44025.

/cc @geoffkizer @wfurt @alnikola

Author: antonfirsov
Assignees: -
Labels:

area-System.Net, new-api-needs-documentation

Milestone: -

CheckDisposedOrStarted();
_receiveDataTimeout = value;
}
}

public bool TcpKeepAliveEnabled { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the set here call CheckDisposedOrStarted?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default here is false? I'm just questioning that because the comment earlier says "The default settings when a TCP socket is initialized sets the keep-alive timeout to 2 hours and the keep-alive interval to 1 second" which suggests the default here should actually be true?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default settings when a TCP socket is initialized sets the keep-alive timeout to 2 hours and the keep-alive interval to 1 second

The same docs also state that :

The SO_KEEPALIVE option for a socket is disabled (set to FALSE) by default. [...] When this socket option is enabled, the TCP stack sends keep-alive packets when no data or acknowledgement packets have been received for the connection within an interval.

From this I concluded that if SO_KEEPALIVE or SIO_KEEPALIVE_VALS are left unchanged, no keepalive packets gonna be sent. We may want to double check with the winsock team since the wording is kinda contradictional.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's double-check, and then either update the implementation or the comment :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The defaults is false. This discussion resulted in an update of the docs ;)

MicrosoftDocs/win32#635

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I never see TCP keep-alive packets in HTTP network traces I get from customers, and that would be pretty obvious with the 1 second interval. I know we decided we're sticking with winsock defaults and violating RFC, but the RFC does say TCP keep-alives should default off in no uncertain terms:

            Implementors MAY include "keep-alives" in their TCP
            implementations, although this practice is not universally
            accepted.  If keep-alives are included, the application MUST
            be able to turn them on or off for each TCP connection, and
            they MUST default to off.

https://tools.ietf.org/html/rfc1122#page-101

I'm glad the winsock defaults at least align with the RFC on this part.

@@ -70,6 +70,8 @@ public static ProxyInfo RequestProxySettings

public static List<IntPtr> WinHttpOptionClientCertContext { get { return winHttpOptionClientCertContextList; } }

public static (uint KeepAliveTime, uint KeepAliveInterval)? TcpKeepaliveOptions { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the other properties here are named WinHttpOption*, should we do the same for this one?

Copy link
Contributor

@geoffkizer geoffkizer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple small issues above, otherwise LGTM

keepaliveinterval = (uint)_tcpKeepAliveInterval.TotalMilliseconds,
keepalivetime = (uint)_tcpKeepAliveTime.TotalMilliseconds
};
void* ptr = &tcpKeepalive;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this local seems unnecessary, and you can just use (IntPtr)&tcpKeepalive below.

@antonfirsov

This comment has been minimized.

@azure-pipelines

This comment has been minimized.

@antonfirsov
Copy link
Member Author

antonfirsov commented Nov 19, 2020

@geoffkizer I think all finding have been addressed, wondering if it's worth to wait for a few more approvals for this.

@geoffkizer
Copy link
Contributor

LGTM

@antonfirsov
Copy link
Member Author

antonfirsov commented Nov 23, 2020

@geoffkizer @stephentoub what about documentation? Should I add xmldoc right in the PR, or is it sufficient to have the new-api-needs-documentation label? Do we apply the same rules for NuGet libraries as for the rest?

@stephentoub
Copy link
Member

Should I add xmldoc right in the PR

Yup, thanks.
cc: @carlossanlop

Copy link
Contributor

@scalablecory scalablecory left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to improve validation, otherwise lgtm.

@antonfirsov
Copy link
Member Author

I've added the docs, can someone double-check the them before we merge?

@geoffkizer
Copy link
Contributor

LGTM

@antonfirsov antonfirsov merged commit 837785f into dotnet:master Nov 25, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 25, 2020
@karelz karelz added this to the 6.0.0 milestone Jan 26, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants