Skip to content

Commit

Permalink
add SendTo/ReceiveFrom with SocketAddress (#88970)
Browse files Browse the repository at this point in the history
* check

* update

* update

* set length

* feedback

* update to match approved API

* quic

* update

* fixes

* GetHashCode

* cleanup

* PalTests

* GetMaximumAddressSize

* wasi

* feedback

* feedback

* loose ends

* feedback
  • Loading branch information
wfurt authored Aug 1, 2023
1 parent 429a5c3 commit e2c6fcf
Show file tree
Hide file tree
Showing 39 changed files with 748 additions and 473 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System;
using System.Net;
using System.Net.Internals;
using System.Net.Sockets;
using System.Runtime.InteropServices;

Expand All @@ -12,6 +11,6 @@ internal static partial class Interop
internal static partial class Sys
{
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_Socket")]
internal static unsafe partial Error Socket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType, IntPtr* socket);
internal static unsafe partial Error Socket(int addressFamily, int socketType, int protocolType, IntPtr* socket);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ internal static partial class Interop
{
internal static partial class Sys
{
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIPSocketAddressSizes")]
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSocketAddressSizes")]
[SuppressGCTransition]
internal static unsafe partial Error GetIPSocketAddressSizes(int* ipv4SocketAddressSize, int* ipv6SocketAddressSize);
internal static unsafe partial Error GetSocketAddressSizes(int* ipv4SocketAddressSize, int* ipv6SocketAddressSize, int* udsSocketAddressSize, int* maxSocketAddressSize);

[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetAddressFamily")]
[SuppressGCTransition]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,6 @@ internal static partial uint IcmpSendEcho2(SafeCloseIcmpHandle icmpHandle, SafeW

[LibraryImport(Interop.Libraries.IpHlpApi, SetLastError = true)]
internal static unsafe partial uint Icmp6SendEcho2(SafeCloseIcmpHandle icmpHandle, SafeWaitHandle Event, IntPtr apcRoutine, IntPtr apcContext,
byte* sourceSocketAddress, byte[] destSocketAddress, SafeLocalAllocHandle data, ushort dataSize, ref IP_OPTION_INFORMATION options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout);
Span<byte> sourceSocketAddress, Span<byte> destSocketAddress, SafeLocalAllocHandle data, ushort dataSize, ref IP_OPTION_INFORMATION options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using Internals = System.Net.Internals;

internal static partial class Interop
{
Expand Down Expand Up @@ -53,20 +52,14 @@ internal enum GetAdaptersAddressesFlags
}

[StructLayout(LayoutKind.Sequential)]
internal struct IpSocketAddress
internal unsafe struct IpSocketAddress
{
internal IntPtr address;
internal int addressLength;

internal IPAddress MarshalIPAddress()
{
// Determine the address family used to create the IPAddress.
AddressFamily family = (addressLength > Internals.SocketAddress.IPv4AddressSize)
? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork;
Internals.SocketAddress sockAddress = new Internals.SocketAddress(family, addressLength);
Marshal.Copy(address, sockAddress.Buffer, 0, addressLength);

return sockAddress.GetIPAddress();
return IPEndPointExtensions.GetIPAddress(new Span<byte>((void*)address, addressLength));
}
}

Expand Down Expand Up @@ -511,7 +504,7 @@ internal static unsafe partial uint GetAdaptersAddresses(
uint* outBufLen);

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

[LibraryImport(Interop.Libraries.IpHlpApi)]
internal static partial uint GetIfEntry2(ref MibIfRow2 pIfRow);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,22 @@ internal static partial class Interop
internal static partial class Winsock
{
[LibraryImport(Interop.Libraries.Ws2_32, SetLastError = true)]
internal static partial SocketError WSAConnect(
private static partial SocketError WSAConnect(
SafeSocketHandle socketHandle,
byte[] socketAddress,
ReadOnlySpan<byte> socketAddress,
int socketAddressSize,
IntPtr inBuffer,
IntPtr outBuffer,
IntPtr sQOS,
IntPtr gQOS);

internal static SocketError WSAConnect(
SafeSocketHandle socketHandle,
ReadOnlySpan<byte> socketAddress,
IntPtr inBuffer,
IntPtr outBuffer,
IntPtr sQOS,
IntPtr gQOS) =>
WSAConnect(socketHandle, socketAddress, socketAddress.Length, inBuffer, outBuffer, sQOS, gQOS);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal static partial class Winsock
[LibraryImport(Interop.Libraries.Ws2_32, SetLastError = true)]
internal static partial IntPtr accept(
SafeSocketHandle socketHandle,
byte[] socketAddress,
Span<byte> socketAddress,
ref int socketAddressSize);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ internal static partial class Winsock
[LibraryImport(Interop.Libraries.Ws2_32, SetLastError = true)]
internal static unsafe partial int recvfrom(
SafeSocketHandle socketHandle,
byte* pinnedBuffer,
Span<byte> pinnedBuffer,
int len,
SocketFlags socketFlags,
byte[] socketAddress,
Span<byte> socketAddress,
ref int socketAddressSize);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal static unsafe partial int sendto(
byte* pinnedBuffer,
int len,
SocketFlags socketFlags,
byte[] socketAddress,
ReadOnlySpan<byte> socketAddress,
int socketAddressSize);
}
}
62 changes: 62 additions & 0 deletions src/libraries/Common/src/System/Net/IPEndPointExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Net;

namespace System.Net.Sockets
{
internal static class IPEndPointExtensions
{
public static IPAddress GetIPAddress(ReadOnlySpan<byte> socketAddressBuffer)
{
AddressFamily family = SocketAddressPal.GetAddressFamily(socketAddressBuffer);

if (family == AddressFamily.InterNetworkV6)
{
Span<byte> address = stackalloc byte[IPAddressParserStatics.IPv6AddressBytes];
uint scope;
SocketAddressPal.GetIPv6Address(socketAddressBuffer, address, out scope);
return new IPAddress(address, (long)scope);
}
else if (family == AddressFamily.InterNetwork)
{
return new IPAddress((long)SocketAddressPal.GetIPv4Address(socketAddressBuffer) & 0x0FFFFFFFF);
}

throw new SocketException((int)SocketError.AddressFamilyNotSupported);
}

public static void SetIPAddress(Span<byte> socketAddressBuffer, IPAddress address)
{
SocketAddressPal.SetAddressFamily(socketAddressBuffer, address.AddressFamily);
SocketAddressPal.SetPort(socketAddressBuffer, 0);
if (address.AddressFamily == AddressFamily.InterNetwork)
{
#pragma warning disable CS0618
SocketAddressPal.SetIPv4Address(socketAddressBuffer, (uint)address.Address);
#pragma warning restore CS0618
}
else
{
Span<byte> addressBuffer = stackalloc byte[IPAddressParserStatics.IPv6AddressBytes];
address.TryWriteBytes(addressBuffer, out int written);
Debug.Assert(written == IPAddressParserStatics.IPv6AddressBytes);
SocketAddressPal.SetIPv6Address(socketAddressBuffer, addressBuffer, (uint)address.ScopeId);
}
}

public static IPEndPoint CreateIPEndPoint(ReadOnlySpan<byte> socketAddressBuffer)
{
return new IPEndPoint(GetIPAddress(socketAddressBuffer), SocketAddressPal.GetPort(socketAddressBuffer));
}

// suggestion from https://github.com/dotnet/runtime/issues/78993
public static void Serialize(this IPEndPoint endPoint, Span<byte> destination)
{
SocketAddressPal.SetAddressFamily(destination, endPoint.AddressFamily);
SetIPAddress(destination, endPoint.Address);
SocketAddressPal.SetPort(destination, (ushort)endPoint.Port);
}
}
}
Loading

0 comments on commit e2c6fcf

Please sign in to comment.