Skip to content

Commit e2c6fcf

Browse files
authored
add SendTo/ReceiveFrom with SocketAddress (#88970)
* check * update * update * set length * feedback * update to match approved API * quic * update * fixes * GetHashCode * cleanup * PalTests * GetMaximumAddressSize * wasi * feedback * feedback * loose ends * feedback
1 parent 429a5c3 commit e2c6fcf

39 files changed

+748
-473
lines changed

src/libraries/Common/src/Interop/Unix/System.Native/Interop.Socket.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System;
55
using System.Net;
6-
using System.Net.Internals;
76
using System.Net.Sockets;
87
using System.Runtime.InteropServices;
98

@@ -12,6 +11,6 @@ internal static partial class Interop
1211
internal static partial class Sys
1312
{
1413
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_Socket")]
15-
internal static unsafe partial Error Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, IntPtr* socket);
14+
internal static unsafe partial Error Socket(int addressFamily, int socketType, int protocolType, IntPtr* socket);
1615
}
1716
}

src/libraries/Common/src/Interop/Unix/System.Native/Interop.SocketAddress.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ internal static partial class Interop
99
{
1010
internal static partial class Sys
1111
{
12-
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIPSocketAddressSizes")]
12+
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSocketAddressSizes")]
1313
[SuppressGCTransition]
14-
internal static unsafe partial Error GetIPSocketAddressSizes(int* ipv4SocketAddressSize, int* ipv6SocketAddressSize);
14+
internal static unsafe partial Error GetSocketAddressSizes(int* ipv4SocketAddressSize, int* ipv6SocketAddressSize, int* udsSocketAddressSize, int* maxSocketAddressSize);
1515

1616
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetAddressFamily")]
1717
[SuppressGCTransition]

src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.ICMP.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,6 @@ internal static partial uint IcmpSendEcho2(SafeCloseIcmpHandle icmpHandle, SafeW
104104

105105
[LibraryImport(Interop.Libraries.IpHlpApi, SetLastError = true)]
106106
internal static unsafe partial uint Icmp6SendEcho2(SafeCloseIcmpHandle icmpHandle, SafeWaitHandle Event, IntPtr apcRoutine, IntPtr apcContext,
107-
byte* sourceSocketAddress, byte[] destSocketAddress, SafeLocalAllocHandle data, ushort dataSize, ref IP_OPTION_INFORMATION options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout);
107+
Span<byte> sourceSocketAddress, Span<byte> destSocketAddress, SafeLocalAllocHandle data, ushort dataSize, ref IP_OPTION_INFORMATION options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout);
108108
}
109109
}

src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.NetworkInformation.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using System.Net.NetworkInformation;
99
using System.Net.Sockets;
1010
using System.Runtime.InteropServices;
11-
using Internals = System.Net.Internals;
1211

1312
internal static partial class Interop
1413
{
@@ -53,20 +52,14 @@ internal enum GetAdaptersAddressesFlags
5352
}
5453

5554
[StructLayout(LayoutKind.Sequential)]
56-
internal struct IpSocketAddress
55+
internal unsafe struct IpSocketAddress
5756
{
5857
internal IntPtr address;
5958
internal int addressLength;
6059

6160
internal IPAddress MarshalIPAddress()
6261
{
63-
// Determine the address family used to create the IPAddress.
64-
AddressFamily family = (addressLength > Internals.SocketAddress.IPv4AddressSize)
65-
? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork;
66-
Internals.SocketAddress sockAddress = new Internals.SocketAddress(family, addressLength);
67-
Marshal.Copy(address, sockAddress.Buffer, 0, addressLength);
68-
69-
return sockAddress.GetIPAddress();
62+
return IPEndPointExtensions.GetIPAddress(new Span<byte>((void*)address, addressLength));
7063
}
7164
}
7265

@@ -511,7 +504,7 @@ internal static unsafe partial uint GetAdaptersAddresses(
511504
uint* outBufLen);
512505

513506
[LibraryImport(Interop.Libraries.IpHlpApi)]
514-
internal static unsafe partial uint GetBestInterfaceEx(byte* ipAddress, int* index);
507+
internal static unsafe partial uint GetBestInterfaceEx(Span<byte> ipAddress, int* index);
515508

516509
[LibraryImport(Interop.Libraries.IpHlpApi)]
517510
internal static partial uint GetIfEntry2(ref MibIfRow2 pIfRow);

src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAConnect.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,22 @@ internal static partial class Interop
1010
internal static partial class Winsock
1111
{
1212
[LibraryImport(Interop.Libraries.Ws2_32, SetLastError = true)]
13-
internal static partial SocketError WSAConnect(
13+
private static partial SocketError WSAConnect(
1414
SafeSocketHandle socketHandle,
15-
byte[] socketAddress,
15+
ReadOnlySpan<byte> socketAddress,
1616
int socketAddressSize,
1717
IntPtr inBuffer,
1818
IntPtr outBuffer,
1919
IntPtr sQOS,
2020
IntPtr gQOS);
21+
22+
internal static SocketError WSAConnect(
23+
SafeSocketHandle socketHandle,
24+
ReadOnlySpan<byte> socketAddress,
25+
IntPtr inBuffer,
26+
IntPtr outBuffer,
27+
IntPtr sQOS,
28+
IntPtr gQOS) =>
29+
WSAConnect(socketHandle, socketAddress, socketAddress.Length, inBuffer, outBuffer, sQOS, gQOS);
2130
}
2231
}

src/libraries/Common/src/Interop/Windows/WinSock/Interop.accept.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ internal static partial class Winsock
1212
[LibraryImport(Interop.Libraries.Ws2_32, SetLastError = true)]
1313
internal static partial IntPtr accept(
1414
SafeSocketHandle socketHandle,
15-
byte[] socketAddress,
15+
Span<byte> socketAddress,
1616
ref int socketAddressSize);
1717
}
1818
}

src/libraries/Common/src/Interop/Windows/WinSock/Interop.recvfrom.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ internal static partial class Winsock
1313
[LibraryImport(Interop.Libraries.Ws2_32, SetLastError = true)]
1414
internal static unsafe partial int recvfrom(
1515
SafeSocketHandle socketHandle,
16-
byte* pinnedBuffer,
16+
Span<byte> pinnedBuffer,
1717
int len,
1818
SocketFlags socketFlags,
19-
byte[] socketAddress,
19+
Span<byte> socketAddress,
2020
ref int socketAddressSize);
2121
}
2222
}

src/libraries/Common/src/Interop/Windows/WinSock/Interop.sendto.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ internal static unsafe partial int sendto(
1515
byte* pinnedBuffer,
1616
int len,
1717
SocketFlags socketFlags,
18-
byte[] socketAddress,
18+
ReadOnlySpan<byte> socketAddress,
1919
int socketAddressSize);
2020
}
2121
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Diagnostics;
5+
using System.Net;
6+
7+
namespace System.Net.Sockets
8+
{
9+
internal static class IPEndPointExtensions
10+
{
11+
public static IPAddress GetIPAddress(ReadOnlySpan<byte> socketAddressBuffer)
12+
{
13+
AddressFamily family = SocketAddressPal.GetAddressFamily(socketAddressBuffer);
14+
15+
if (family == AddressFamily.InterNetworkV6)
16+
{
17+
Span<byte> address = stackalloc byte[IPAddressParserStatics.IPv6AddressBytes];
18+
uint scope;
19+
SocketAddressPal.GetIPv6Address(socketAddressBuffer, address, out scope);
20+
return new IPAddress(address, (long)scope);
21+
}
22+
else if (family == AddressFamily.InterNetwork)
23+
{
24+
return new IPAddress((long)SocketAddressPal.GetIPv4Address(socketAddressBuffer) & 0x0FFFFFFFF);
25+
}
26+
27+
throw new SocketException((int)SocketError.AddressFamilyNotSupported);
28+
}
29+
30+
public static void SetIPAddress(Span<byte> socketAddressBuffer, IPAddress address)
31+
{
32+
SocketAddressPal.SetAddressFamily(socketAddressBuffer, address.AddressFamily);
33+
SocketAddressPal.SetPort(socketAddressBuffer, 0);
34+
if (address.AddressFamily == AddressFamily.InterNetwork)
35+
{
36+
#pragma warning disable CS0618
37+
SocketAddressPal.SetIPv4Address(socketAddressBuffer, (uint)address.Address);
38+
#pragma warning restore CS0618
39+
}
40+
else
41+
{
42+
Span<byte> addressBuffer = stackalloc byte[IPAddressParserStatics.IPv6AddressBytes];
43+
address.TryWriteBytes(addressBuffer, out int written);
44+
Debug.Assert(written == IPAddressParserStatics.IPv6AddressBytes);
45+
SocketAddressPal.SetIPv6Address(socketAddressBuffer, addressBuffer, (uint)address.ScopeId);
46+
}
47+
}
48+
49+
public static IPEndPoint CreateIPEndPoint(ReadOnlySpan<byte> socketAddressBuffer)
50+
{
51+
return new IPEndPoint(GetIPAddress(socketAddressBuffer), SocketAddressPal.GetPort(socketAddressBuffer));
52+
}
53+
54+
// suggestion from https://github.com/dotnet/runtime/issues/78993
55+
public static void Serialize(this IPEndPoint endPoint, Span<byte> destination)
56+
{
57+
SocketAddressPal.SetAddressFamily(destination, endPoint.AddressFamily);
58+
SetIPAddress(destination, endPoint.Address);
59+
SocketAddressPal.SetPort(destination, (ushort)endPoint.Port);
60+
}
61+
}
62+
}

0 commit comments

Comments
 (0)