-
Notifications
You must be signed in to change notification settings - Fork 5.4k
UdpClient with span support #53429
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
UdpClient with span support #53429
Changes from 2 commits
f05bfbf
e5cd921
32050da
d9c5e2b
d8e144c
05b0cf2
14465d0
0ca0fee
a368fff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
| using System.Diagnostics.CodeAnalysis; | ||
| using System.Threading.Tasks; | ||
| using System.Runtime.Versioning; | ||
| using System.Threading; | ||
|
|
||
| namespace System.Net.Sockets | ||
| { | ||
|
|
@@ -334,6 +335,17 @@ private void ValidateDatagram(byte[] datagram, int bytes, IPEndPoint? endPoint) | |
| } | ||
| } | ||
|
|
||
| private void ValidateDatagram(ReadOnlyMemory<byte> datagram, IPEndPoint? endPoint) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactored code to validate inside calling code. |
||
| { | ||
| ThrowIfDisposed(); | ||
|
|
||
| if (_active && endPoint != null) | ||
| { | ||
| // Do not allow sending packets to arbitrary host when connected. | ||
| throw new InvalidOperationException(SR.net_udpconnected); | ||
| } | ||
| } | ||
|
|
||
| private IPEndPoint? GetEndpoint(string? hostname, int port) | ||
| { | ||
| if (_active && ((hostname != null) || (port != 0))) | ||
|
|
@@ -600,6 +612,9 @@ public void DropMulticastGroup(IPAddress multicastAddr, int ifindex) | |
| public Task<int> SendAsync(byte[] datagram, int bytes) => | ||
| SendAsync(datagram, bytes, null); | ||
|
|
||
| public ValueTask<int> SendAsync(ReadOnlyMemory<byte> datagram, CancellationToken cancellationToken = default) => | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to a new rule, we need to add triple-slash docs for all new public methods right in product code PR-s. They will be fed to a tool to generate API docs. You can find examples in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added xml doc for new APIs.
Comment on lines
+615
to
+616
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is makes the bar really unfair for community contributors IMO, but I think we should also copy the Remarks sections when present: (This applies to all new overloads.) @carlossanlop any plans to make this process simpler and the code less bloated with long copy-pasted blocks? (Not sure if you are the right person to tag about this.)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The long-term plan is to merge the existing external docs back in to the code, so that the code is the one source of truth. I don't know when/how this will happen; @carlossanlop is the right person to talk to. |
||
| SendAsync(datagram, null, cancellationToken); | ||
|
|
||
| public Task<int> SendAsync(byte[] datagram, int bytes, string? hostname, int port) => | ||
| SendAsync(datagram, bytes, GetEndpoint(hostname, port)); | ||
|
|
||
|
|
@@ -618,6 +633,21 @@ public Task<int> SendAsync(byte[] datagram, int bytes, IPEndPoint? endPoint) | |
| } | ||
| } | ||
|
|
||
| public ValueTask<int> SendAsync(ReadOnlyMemory<byte> datagram, IPEndPoint? endPoint, CancellationToken cancellationToken = default) | ||
| { | ||
| ValidateDatagram(datagram, endPoint); | ||
|
|
||
| if (endPoint is null) | ||
| { | ||
| return _clientSocket.SendAsync(datagram, SocketFlags.None, cancellationToken); | ||
| } | ||
| else | ||
| { | ||
| CheckForBroadcast(endPoint.Address); | ||
| return _clientSocket.SendToAsync(datagram, SocketFlags.None, endPoint, cancellationToken); | ||
| } | ||
| } | ||
|
|
||
| public Task<UdpReceiveResult> ReceiveAsync() | ||
| { | ||
| ThrowIfDisposed(); | ||
|
|
@@ -892,45 +922,32 @@ public int Send(byte[] dgram, int bytes, IPEndPoint? endPoint) | |
| return Client.SendTo(dgram, 0, bytes, SocketFlags.None, endPoint); | ||
| } | ||
|
|
||
|
|
||
| // Sends a UDP datagram to the specified port on the specified remote host. | ||
| public int Send(byte[] dgram, int bytes, string? hostname, int port) | ||
| // Sends a UDP datagram to the host at the remote end point. | ||
| public int Send(ReadOnlySpan<byte> datagram, IPEndPoint? endPoint) | ||
| { | ||
| ThrowIfDisposed(); | ||
|
|
||
| if (dgram == null) | ||
| { | ||
| throw new ArgumentNullException(nameof(dgram)); | ||
| } | ||
| if (_active && ((hostname != null) || (port != 0))) | ||
| if (_active && endPoint != null) | ||
| { | ||
| // Do not allow sending packets to arbitrary host when connected | ||
| throw new InvalidOperationException(SR.net_udpconnected); | ||
| } | ||
|
|
||
| if (hostname == null || port == 0) | ||
| { | ||
| return Client.Send(dgram, 0, bytes, SocketFlags.None); | ||
| } | ||
|
|
||
| IPAddress[] addresses = Dns.GetHostAddresses(hostname); | ||
|
|
||
| int i = 0; | ||
| for (; i < addresses.Length && !IsAddressFamilyCompatible(addresses[i].AddressFamily); i++) | ||
| if (endPoint == null) | ||
| { | ||
| ; // just count the addresses | ||
| return Client.Send(datagram, SocketFlags.None); | ||
| } | ||
|
|
||
| if (addresses.Length == 0 || i == addresses.Length) | ||
| { | ||
| throw new ArgumentException(SR.net_invalidAddressList, nameof(hostname)); | ||
| } | ||
| CheckForBroadcast(endPoint.Address); | ||
|
|
||
| CheckForBroadcast(addresses[i]); | ||
| IPEndPoint ipEndPoint = new IPEndPoint(addresses[i], port); | ||
| return Client.SendTo(dgram, 0, bytes, SocketFlags.None, ipEndPoint); | ||
| return Client.SendTo(datagram, SocketFlags.None, endPoint); | ||
| } | ||
|
|
||
| // Sends a UDP datagram to the specified port on the specified remote host. | ||
| public int Send(byte[] dgram, int bytes, string? hostname, int port) => Send(dgram, bytes, GetEndpoint(hostname, port)); | ||
|
|
||
| // Sends a UDP datagram to the specified port on the specified remote host. | ||
| public int Send(ReadOnlySpan<byte> datagram, string? hostname, int port) => Send(datagram, GetEndpoint(hostname, port)); | ||
|
|
||
| // Sends a UDP datagram to a remote host. | ||
| public int Send(byte[] dgram, int bytes) | ||
|
|
@@ -950,6 +967,20 @@ public int Send(byte[] dgram, int bytes) | |
| return Client.Send(dgram, 0, bytes, SocketFlags.None); | ||
| } | ||
|
|
||
| // Sends a UDP datagram to a remote host. | ||
| public int Send(ReadOnlySpan<byte> datagram) | ||
| { | ||
| ThrowIfDisposed(); | ||
|
|
||
| if (!_active) | ||
| { | ||
| // only allowed on connected socket | ||
| throw new InvalidOperationException(SR.net_notconnected); | ||
| } | ||
|
|
||
| return Client.Send(datagram, SocketFlags.None); | ||
| } | ||
|
|
||
| private void ThrowIfDisposed() | ||
| { | ||
| if (_disposed) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.