-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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 cache for Socket.LocalEndPoint #39313
Conversation
Tagging subscribers to this area: @dotnet/ncl |
/azp run runtime-libraries outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
Outdated
Show resolved
Hide resolved
/azp run runtime-libraries outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
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.
LGTM, but I let @antonfirsov make the final ok ;)
I'm concerned if we should maybe reset runtime/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs Lines 2685 to 2712 in f8e92ec
If I'm not missing anything there will be no user callback querying
Such a call may enforce caching a wrong value for @tmds maybe you have some thoughts on this? |
@antonfirsov Here is a list of all changes of _rightEndPoint that I have found in the code (sorry for the long list, I would put it under cut if I knew how)
You suggest to clear _localEndPoint on the reset of _rightEndPoint, which are items 2. and 3. on the list. If we look at subitems of item 1., we can see that most of them are if _rightEndPoint was null before or in the constructor, which means if we clear _localEndPoint at this time we won't actually change anything. And a change of _rightEndPoint after non-blocking connect will only happen once I believe. What I am trying to say is if we want to clear _localEndPoint on the reset of _rightEndPoint, maybe we could actually return to my original proposal of clearing _localEndPoint on every _rightEndPoint change? The only place where it might possibly unnesessary clear some cached value is this non-blocking connect part (item 1.2.) and we might use _rightEndPoint there instead of new property RightEndPoint specifically in this case. |
src/libraries/System.Net.Sockets/tests/FunctionalTests/LocalEndPointTest.cs
Outdated
Show resolved
Hide resolved
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run runtime-libraries outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
So the behavior with wildcard addresses is as follows.
I added clearing of cached wildcard local endpoints on |
/azp run runtime-libraries outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
Outdated
Show resolved
Hide resolved
/azp run runtime-libraries outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
Outdated
Show resolved
Hide resolved
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 need to make sure all independent implementations are covered in the tests, otherwise looks good now.
[Fact] | ||
public void UdpSocket_ClientNotBound_LocalEPBecomesWildcardOnSendTo() | ||
{ | ||
using (Socket server = CreateUdpSocket()) | ||
using (Socket client = CreateUdpSocket()) | ||
{ | ||
int serverPort = server.BindToAnonymousPort(Wildcard); | ||
|
||
Assert.Null(client.LocalEndPoint); // null before sendto | ||
|
||
var sendToEP = new IPEndPoint(Loopback, serverPort); | ||
|
||
client.SendTo(new byte[] { 1, 2, 3 }, sendToEP); | ||
|
||
Assert.Equal(Wildcard, GetLocalEPAddress(client)); // wildcard after sendto | ||
|
||
byte[] buf = new byte[3]; | ||
EndPoint receiveFromEP = new IPEndPoint(Wildcard, 0); | ||
server.ReceiveFrom(buf, ref receiveFromEP); | ||
|
||
Assert.Equal(new byte[] { 1, 2, 3 }, buf); | ||
} | ||
} | ||
|
||
[Fact] | ||
public void UdpSocket_ClientNotBound_LocalEPBecomesWildcardOnAsyncSendTo() | ||
{ | ||
using (Socket server = CreateUdpSocket()) | ||
using (Socket client = CreateUdpSocket()) | ||
{ | ||
int serverPort = server.BindToAnonymousPort(Wildcard); | ||
|
||
Assert.Null(client.LocalEndPoint); // null before async WSASendTo | ||
|
||
var sendToEP = new IPEndPoint(Loopback, serverPort); | ||
|
||
IAsyncResult sendToResult = client.BeginSendTo(new byte[] { 4, 5, 6 }, 0, 3, SocketFlags.None, sendToEP, null, null); | ||
sendToResult.AsyncWaitHandle.WaitOne(); | ||
client.EndSendTo(sendToResult); | ||
|
||
Assert.Equal(Wildcard, GetLocalEPAddress(client)); // wildcard after async WSASendTo | ||
|
||
byte[] buf = new byte[3]; | ||
EndPoint receiveFromEP = new IPEndPoint(Wildcard, 0); | ||
server.ReceiveFrom(buf, ref receiveFromEP); | ||
|
||
Assert.Equal(new byte[] { 4, 5, 6 }, buf); | ||
} | ||
} |
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.
These 2 tests seem to test the same thing for two different connect implementations. I suggest dedupe their code and also cover the remaining ones: ConnectAsync(SocketAsyncEventArgs)
and SocketTaskExtensions.ConnectAsync(this Socket, ....)
. For this the best would be to utilize SocketTestHelperBase<T>
.
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.
Rewrote the tests, please check that I understood you correctly :)
Added _localEndPoint field to cache LocalEndPoint value.
Introduced RightEndPoint property to encapsulate clearing _localEndPoint on _rightEndPoint change.Cached value is cleared on connect, error and disconnect.Cached value is cleared on error and disconnect. If the value is a wildcard address, it is also cleared on connect and accept.Fix #1482