-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
add support for parallel Connect #106374
base: main
Are you sure you want to change the base?
add support for parallel Connect #106374
Conversation
Note regarding the
|
Note regarding the
|
Tagging subscribers to this area: @dotnet/ncl |
I'm not sure about the behavior of Because if either IPv6/IPv4 response is late or timeouts somehow, then it means we're delaying connection until we got both of the responses, this can be problematic for some specific cases. But on the other hand with this approach, OS is implementing |
} | ||
else | ||
{ | ||
if (nextAddressIndex == -1 && nextIPv6Addressindex == -1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (nextAddressIndex == -1 && nextIPv6Addressindex == -1) | |
if (nextAddressIndex < 0 && nextIPv6Addressindex < 0) |
The JIT can produce less and more optimized machine-code (if it matters here too, but the change is cheap...)
@@ -833,13 +1001,13 @@ async Task Core(MultiConnectSocketAsyncEventArgs internalArgs, Task<IPAddress[]> | |||
// Store the results. | |||
if (caughtException != null) | |||
{ | |||
SetResults(caughtException, 0, SocketFlags.None); | |||
SetResults(caughtException, 0, SocketFlags.None); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: there's a space too much
SetResults(caughtException, 0, SocketFlags.None); | |
SetResults(caughtException, 0, SocketFlags.None); |
@@ -1087,6 +1087,84 @@ public async Task SendTo_DifferentEP_Success(bool ipv4) | |||
result = await receiver2.ReceiveFromAsync(receiveBuffer, remoteEp).WaitAsync(TestSettings.PassingTestTimeout); | |||
Assert.Equal(sendBuffer.Length, result.ReceivedBytes); | |||
} | |||
|
|||
[ConditionalFact(typeof(DualModeBase), nameof(DualModeBase.LocalhostIsBothIPv4AndIPv6))] | |||
public void Connect_Parallel_Succss() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public void Connect_Parallel_Succss() | |
public void Connect_Parallel_Success() |
|
||
int nextAddressIndex = 0; | ||
int nextIPv6AddressIndex = GetNextAddress(addresses, AddressFamily.InterNetworkV6, -1); | ||
int nextUPv4AddressIndex = GetNextAddress(addresses, AddressFamily.InterNetwork, -1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this variable only used within parallelConnect
variable and that's it, perhaps delete this and call function directly in parallelConnect
.
{ | ||
address = addresses[nextAddressIndex]; | ||
nextAddressIndex = GetNextAddress(addresses, currentAddressFamily, nextAddressIndex); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | ||
internalArgs.SocketError = SocketError.IOPending; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | |
internalArgs.SocketError = SocketError.IOPending; | |
} | |
internalArgs.SocketError = SocketError.IOPending; |
address = addresses[nextIPv6AddressIndex]; | ||
internalArgs.SocketError = SocketError.IOPending; | ||
address2 = null; | ||
internalArgs.SecondarySaea = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we dispose this before null out?
{ | ||
if (nextIPv6AddressIndex >= 0) | ||
{ | ||
address2 = addresses[nextIPv6AddressIndex]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is duplicate assign on line 806
break; | ||
} | ||
|
||
if (internalArgs.SocketError != SocketError.IOPending) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we be more specific with this check, and propagate the error if the error is something else other than expected (e.g. SocketError.SystemNotReady
) ?
if (nextIPv6AddressIndex >= 0) | ||
{ | ||
address2 = addresses[nextIPv6AddressIndex]; | ||
if (address == null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (address == null) | |
if (address is not null) |
// defaul mechanism e.g. sequential processing | ||
Default = 0, | ||
|
||
// use a Happy Eyeballs-like algorithm to connect. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Please use XML comments
public static bool ConnectAsync(SocketType socketType, ProtocolType protocolType, SocketAsyncEventArgs e) | ||
public static bool ConnectAsync(SocketType socketType, ProtocolType protocolType, SocketAsyncEventArgs e) => | ||
ConnectAsync(socketType, protocolType, e, ConnectAlgorithm.Default); | ||
public static bool ConnectAsync(SocketType socketType, ProtocolType protocolType, SocketAsyncEventArgs e, ConnectAlgorithm connectAlgorithm) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validate that connectAlgorithm is one of the two known values?
int nextUPv4AddressIndex = GetNextAddress(addresses, AddressFamily.InterNetwork, -1); | ||
|
||
|
||
// We can do parallel connect only if siocket was not specified and when there is at least one address of each AF. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// We can do parallel connect only if siocket was not specified and when there is at least one address of each AF. | |
// We can do parallel connect only if socket was not specified and when there is at least one address of each AF. |
{ | ||
if (!parallelConnect) | ||
{ | ||
// We simply try addresses in sequence until we either try them all or operation is cancelled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
// We simply try addresses in sequence until we either try them all or operation is cancelled. | |
// We simply try addresses in sequence until we either try them all or operation is canceled. |
@@ -672,12 +672,27 @@ internal void FinishOperationAsyncFailure(SocketError socketError, int bytesTran | |||
} | |||
} | |||
|
|||
private static int GetNextAddress(IPAddress[] addresses, AddressFamily addressFamily, int index) | |||
{ | |||
for (int i = index + 1; i < addresses.Length; i++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the +1 and then using -1 later?
Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it. |
Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it. |
this adds API approved in #87932. It seems like this only supports SAEA. We may consider extending it to be also supported with
Task
.To limit possible risk, I added new member to existing and transient
MultiConnectSocketAsyncEventArgs
e.g. there should not be any penalty forSocket
. We also originally discussed some split DNS query with @liveans and that can be possibly done separately. This is basic snapshot I crafted when hoping to squeeze this to 9.0.Testing is tricky as it depends on DNS entries and particular behavior and speed.