Skip to content
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 SendTo/ReceiveFrom with SocketAddress #88970

Merged
merged 18 commits into from
Aug 1, 2023
Merged
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);
wfurt marked this conversation as resolved.
Show resolved Hide resolved
}
}
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);
}

wfurt marked this conversation as resolved.
Show resolved Hide resolved
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