SetIPAddress(destination, endPoint.Address);
SocketAddressPal.SetPort(destination, (ushort)endPoint.Port);
}
+
+ public static bool Equals(this IPEndPoint endPoint, ReadOnlySpan<byte> socketAddressBuffer)
+ {
+ if (socketAddressBuffer.Length >= SocketAddress.GetMaximumAddressSize(endPoint.AddressFamily) &&
+ endPoint.AddressFamily == SocketAddressPal.GetAddressFamily(socketAddressBuffer) &&
+ endPoint.Port == (int)SocketAddressPal.GetPort(socketAddressBuffer))
+ {
+ if (endPoint.AddressFamily == AddressFamily.InterNetwork)
+ {
+#pragma warning disable CS0618
+ return endPoint.Address.Address == (long)SocketAddressPal.GetIPv4Address(socketAddressBuffer);
+#pragma warning restore CS0618
+ }
+ else
+ {
+ Span<byte> addressBuffer1 = stackalloc byte[IPAddressParserStatics.IPv6AddressBytes];
+ Span<byte> addressBuffer2 = stackalloc byte[IPAddressParserStatics.IPv6AddressBytes];
+ SocketAddressPal.GetIPv6Address(socketAddressBuffer, addressBuffer1, out uint scopeid);
+ if (endPoint.Address.ScopeId != (long)scopeid)
+ {
+ return false;
+ }
+ endPoint.Address.TryWriteBytes(addressBuffer2, out _);
+ return addressBuffer1.SequenceEqual(addressBuffer2);
+ }
+ }
+
+ return false;
+ }
}
}
+++ /dev/null
-// 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;
-
-namespace System.Net.Sockets
-{
- internal static class IPAddressExtensions
- {
- public static IPAddress Snapshot(this IPAddress original)
- {
- switch (original.AddressFamily)
- {
- case AddressFamily.InterNetwork:
-#pragma warning disable CS0618 // IPAddress.Address is obsoleted, but it's the most efficient way to get the Int32 IPv4 address
- return new IPAddress(original.Address);
-#pragma warning restore CS0618
-
- case AddressFamily.InterNetworkV6:
- Span<byte> addressBytes = stackalloc byte[IPAddressParserStatics.IPv6AddressBytes];
- original.TryWriteBytes(addressBytes, out int bytesWritten);
- Debug.Assert(bytesWritten == IPAddressParserStatics.IPv6AddressBytes);
- return new IPAddress(addressBytes, (uint)original.ScopeId);
-
- default:
- throw new InternalException(original.AddressFamily);
- }
- }
- }
-}
+++ /dev/null
-// 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;
-
-namespace System.Net.Sockets
-{
- internal static partial class IPEndPointExtensions
- {
- public static Internals.SocketAddress Serialize(EndPoint endpoint)
- {
- Debug.Assert(!(endpoint is DnsEndPoint));
-
- var ipEndPoint = endpoint as IPEndPoint;
- if (ipEndPoint != null)
- {
- return new Internals.SocketAddress(ipEndPoint.Address, ipEndPoint.Port);
- }
-
- System.Net.SocketAddress address = endpoint.Serialize();
- return GetInternalSocketAddress(address);
- }
-
- public static EndPoint Create(this EndPoint thisObj, Internals.SocketAddress socketAddress)
- {
- AddressFamily family = socketAddress.Family;
- if (family != thisObj.AddressFamily)
- {
- throw new ArgumentException(SR.Format(SR.net_InvalidAddressFamily, family.ToString(), thisObj.GetType().FullName, thisObj.AddressFamily.ToString()), nameof(socketAddress));
- }
-
- if (family == AddressFamily.InterNetwork || family == AddressFamily.InterNetworkV6)
- {
- if (socketAddress.Size < 8)
- {
- throw new ArgumentException(SR.Format(SR.net_InvalidSocketAddressSize, socketAddress.GetType().FullName, thisObj.GetType().FullName), nameof(socketAddress));
- }
-
- return socketAddress.GetIPEndPoint();
- }
- else if (family == AddressFamily.Unknown)
- {
- return thisObj;
- }
-
- System.Net.SocketAddress address = GetNetSocketAddress(socketAddress);
- return thisObj.Create(address);
- }
-
- private static Internals.SocketAddress GetInternalSocketAddress(System.Net.SocketAddress address)
- {
- var result = new Internals.SocketAddress(address.Family, address.Size);
- for (int index = 0; index < address.Size; index++)
- {
- result[index] = address[index];
- }
-
- return result;
- }
-
- internal static System.Net.SocketAddress GetNetSocketAddress(Internals.SocketAddress address)
- {
- var result = new System.Net.SocketAddress(address.Family, address.Size);
- for (int index = 0; index < address.Size; index++)
- {
- result[index] = address[index];
- }
-
- return result;
- }
- }
-}
+++ /dev/null
-Contracts such as NameResolution and Sockets require internal access to Primitive types. Binary copies of these types have been made within the System.Net.Internals namespace using #ifdef pragmas (source code is reused).
-
-An adaptation layer between .Internals and public types exists within the Extensions classes.
-
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Buffers.Binary;
using System.Diagnostics;
-using System.Globalization;
using System.Net.Sockets;
-using System.Text;
-#if SYSTEM_NET_PRIMITIVES_DLL
namespace System.Net
-#else
-namespace System.Net.Internals
-#endif
{
// This class is used when subclassing EndPoint, and provides indication
// on how to format the memory buffers that the platform uses for network addresses.
-#if SYSTEM_NET_PRIMITIVES_DLL
- public
-#else
- internal sealed
-#endif
- class SocketAddress : System.IEquatable<SocketAddress>
+ public class SocketAddress : IEquatable<SocketAddress>
{
#pragma warning disable CA1802 // these could be const on Windows but need to be static readonly for Unix
internal static readonly int IPv6AddressSize = SocketAddressPal.IPv6AddressSize;
set
{
ArgumentOutOfRangeException.ThrowIfGreaterThan(value, _buffer.Length);
- ArgumentOutOfRangeException.ThrowIfLessThan(value, MinSize);
+ ArgumentOutOfRangeException.ThrowIfLessThan(value, 0);
_size = value;
}
}
SocketAddressPal.SetPort(_buffer, unchecked((ushort)port));
}
- internal SocketAddress(AddressFamily addressFamily, ReadOnlySpan<byte> buffer)
- {
- _buffer = buffer.ToArray();
- _size = _buffer.Length;
- SocketAddressPal.SetAddressFamily(_buffer, addressFamily);
- }
-
/// <summary>This represents underlying memory that can be passed to native OS calls.</summary>
/// <remarks>
/// Content of the memory can be invalidated if <see cref="Size"/> is changed or if the SocketAddress is used in another receive call.
{
get
{
- return new Memory<byte>(_buffer, 0, _size);
- }
- }
-
- internal IPAddress GetIPAddress()
- {
- if (Family == AddressFamily.InterNetworkV6)
- {
- Debug.Assert(Size >= IPv6AddressSize);
-
- Span<byte> address = stackalloc byte[IPAddressParserStatics.IPv6AddressBytes];
- uint scope;
- SocketAddressPal.GetIPv6Address(_buffer, address, out scope);
-
- return new IPAddress(address, (long)scope);
- }
- else if (Family == AddressFamily.InterNetwork)
- {
- Debug.Assert(Size >= IPv4AddressSize);
- long address = (long)SocketAddressPal.GetIPv4Address(_buffer) & 0x0FFFFFFFF;
- return new IPAddress(address);
- }
- else
- {
-#if SYSTEM_NET_PRIMITIVES_DLL
- throw new SocketException(SocketError.AddressFamilyNotSupported);
-#else
- throw new SocketException((int)SocketError.AddressFamilyNotSupported);
-#endif
+ return new Memory<byte>(_buffer);
}
}
- internal int GetPort() => (int)SocketAddressPal.GetPort(_buffer);
-
- internal IPEndPoint GetIPEndPoint()
- {
- return new IPEndPoint(GetIPAddress(), GetPort());
- }
public override bool Equals(object? comparand) =>
comparand is SocketAddress other && Equals(other);
--- /dev/null
+// 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 partial class SocketAddressExtensions
+ {
+ public static IPAddress GetIPAddress(this SocketAddress socketAddress) => IPEndPointExtensions.GetIPAddress(socketAddress.Buffer.Span);
+ public static int GetPort(this SocketAddress socketAddress)
+ {
+ Debug.Assert(socketAddress.Family == AddressFamily.InterNetwork || socketAddress.Family == AddressFamily.InterNetworkV6);
+ return (int)SocketAddressPal.GetPort(socketAddress.Buffer.Span);
+ }
+
+ public static IPEndPoint GetIPEndPoint(this SocketAddress socketAddress)
+ {
+ return new IPEndPoint(socketAddress.GetIPAddress(), socketAddress.GetPort());
+ }
+
+ public static bool Equals(this SocketAddress socketAddress, EndPoint? endPoint)
+ {
+ if (socketAddress.Family == endPoint?.AddressFamily && endPoint is IPEndPoint ipe)
+ {
+ return ipe.Equals(socketAddress.Buffer.Span);
+ }
+
+ // We could serialize other EndPoints and compare socket addresses.
+ // But that would do two allocations and is probably as expensive as
+ // allocating new EndPoint.
+ // This may change if https://github.com/dotnet/runtime/issues/78993 is done
+ return false;
+ }
+ }
+}
{
internal static partial class SocketProtocolSupportPal
{
+ private const int DgramSocketType = 2;
+
private static unsafe bool IsSupported(AddressFamily af)
{
// Check for AF_UNIX on iOS/tvOS. The OS claims to support this, but returns EPERM on bind.
{
private static bool IsSupported(AddressFamily af)
{
+ const int StreamSocketType = 1;
Interop.Winsock.EnsureInitialized();
IntPtr INVALID_SOCKET = (IntPtr)(-1);
IntPtr socket = INVALID_SOCKET;
try
{
- socket = Interop.Winsock.WSASocketW(af, DgramSocketType, 0, IntPtr.Zero, 0, (int)Interop.Winsock.SocketConstructorFlags.WSA_FLAG_NO_HANDLE_INHERIT);
+ socket = Interop.Winsock.WSASocketW(af, StreamSocketType, 0, IntPtr.Zero, 0, (int)Interop.Winsock.SocketConstructorFlags.WSA_FLAG_NO_HANDLE_INHERIT);
return
socket != INVALID_SOCKET ||
(SocketError)Marshal.GetLastPInvokeError() != SocketError.AddressFamilyNotSupported;
public static bool OSSupportsIPv4 { get; } = IsSupported(AddressFamily.InterNetwork);
public static bool OSSupportsUnixDomainSockets { get; } = IsSupported(AddressFamily.Unix);
- private const int DgramSocketType = 2;
-
private static bool IsIPv6Disabled()
{
// First check for the AppContext switch, giving it priority over the environment variable.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-#if SYSTEM_NET_SOCKETS_DLL
namespace System.Net.Sockets
{
public
-#else
-namespace System.Net.Internals
-{
- internal
-#endif
// Specifies the protocols that the Socket class supports.
enum ProtocolType
{
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-#if SYSTEM_NET_SOCKETS_DLL
namespace System.Net.Sockets
{
public
-#else
-namespace System.Net.Internals
-{
- internal
-#endif
// Specifies the type of socket an instance of the System.Net.Sockets.Socket class represents.
enum SocketType
{
Link="Common\System\Net\CookieParser.cs" />
<Compile Include="$(CommonPath)System\Net\IPAddressParserStatics.cs"
Link="Common\System\Net\IPAddressParserStatics.cs" />
+ <Compile Include="$(CommonPath)System\Net\IPEndPointExtensions.cs"
+ Link="Common\System\Net\IPEndPointExtensions.cs" />
<Compile Include="$(CommonPath)System\Net\HttpKnownHeaderNames.cs"
Link="Common\System\Net\HttpKnownHeaderNames.cs" />
<Compile Include="$(CommonPath)System\Net\TcpValidationHelpers.cs"
Link="Common\System\Net\UriScheme.cs" />
<Compile Include="$(CommonPath)System\Net\SocketAddress.cs"
Link="Common\System\Net\SocketAddress.cs" />
+ <Compile Include="$(CommonPath)System\Net\SocketAddressExtensions.cs"
+ Link="Common\System\Net\SocketAddressExtensions.cs" />
<Compile Include="$(CommonPath)System\Net\NegotiationInfoClass.cs"
Link="Common\System\Net\NegotiationInfoClass.cs" />
<Compile Include="$(CommonPath)System\Net\NetworkInformation\HostInformation.cs"
{
SocketAddress sa = new SocketAddress(AddressFamily.InterNetwork);
Assert.Throws<ArgumentOutOfRangeException>(() => sa.Size = sa.Size + 1);
-
- sa.Size = 4;
- Assert.Equal(4, sa.Buffer.Length);
+ sa.Size = 0;
+ Assert.Throws<ArgumentOutOfRangeException>(() => sa.Size = - 1);
}
[Fact]
Link="Common\System\HexConverter.cs" />
<Compile Include="$(CommonPath)System\Obsoletions.cs"
Link="Common\System\Obsoletions.cs" />
+ <Compile Include="$(CommonPath)System\Net\IPEndPointExtensions.cs"
+ Link="Common\System\Net\IPEndPointExtensions.cs" />
+ <Compile Include="$(CommonPath)System\Net\SocketAddressExtensions.cs"
+ Link="Common\System\Net\SocketAddressExtensions.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="HostInformationPalTest.cs" />
Link="Common\System\HexConverter.cs" />
<Compile Include="$(CommonPath)System\Obsoletions.cs"
Link="Common\System\Obsoletions.cs" />
+ <Compile Include="$(CommonPath)System\Net\IPEndPointExtensions.cs"
+ Link="Common\System\Net\IPEndPointExtensions.cs" />
+ <Compile Include="$(CommonPath)System\Net\SocketAddressExtensions.cs"
+ Link="Common\System\Net\SocketAddressExtensions.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="CookieCollectionTest.cs" />
public int ReceiveFrom(byte[] buffer, System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP) { throw null; }
public int ReceiveFrom(System.Span<byte> buffer, ref System.Net.EndPoint remoteEP) { throw null; }
public int ReceiveFrom(System.Span<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP) { throw null; }
- public int ReceiveFrom(System.Span<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.SocketAddress receivedSocketAddress) { throw null; }
+ public int ReceiveFrom(System.Span<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.SocketAddress receivedAddress) { throw null; }
public System.Threading.Tasks.Task<System.Net.Sockets.SocketReceiveFromResult> ReceiveFromAsync(System.ArraySegment<byte> buffer, System.Net.EndPoint remoteEndPoint) { throw null; }
public System.Threading.Tasks.Task<System.Net.Sockets.SocketReceiveFromResult> ReceiveFromAsync(System.ArraySegment<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) { throw null; }
public System.Threading.Tasks.ValueTask<System.Net.Sockets.SocketReceiveFromResult> ReceiveFromAsync(System.Memory<byte> buffer, System.Net.EndPoint remoteEndPoint, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.ValueTask<System.Net.Sockets.SocketReceiveFromResult> ReceiveFromAsync(System.Memory<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
+ public System.Threading.Tasks.ValueTask<int> ReceiveFromAsync(System.Memory<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.SocketAddress receivedAddress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public bool ReceiveFromAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; }
public int ReceiveMessageFrom(byte[] buffer, int offset, int size, ref System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP, out System.Net.Sockets.IPPacketInformation ipPacketInformation) { throw null; }
public int ReceiveMessageFrom(System.Span<byte> buffer, ref System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP, out System.Net.Sockets.IPPacketInformation ipPacketInformation) { throw null; }
public bool SendToAsync(System.Net.Sockets.SocketAsyncEventArgs e) { throw null; }
public System.Threading.Tasks.ValueTask<int> SendToAsync(System.ReadOnlyMemory<byte> buffer, System.Net.EndPoint remoteEP, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.ValueTask<int> SendToAsync(System.ReadOnlyMemory<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
+ public System.Threading.Tasks.ValueTask<int> SendToAsync(System.ReadOnlyMemory<byte> buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.SocketAddress socketAddress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
[System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")]
public void SetIPProtectionLevel(System.Net.Sockets.IPProtectionLevel level) { }
public void SetRawSocketOption(int optionLevel, int optionName, System.ReadOnlySpan<byte> optionValue) { }
Link="Common\System\Net\ExceptionCheck.cs" />
<Compile Include="$(CommonPath)System\Net\RangeValidationHelpers.cs"
Link="Common\System\Net\RangeValidationHelpers.cs" />
- <Compile Include="$(CommonPath)System\Net\SocketAddress.cs"
- Link="Common\System\Net\SocketAddress.cs" />
<Compile Include="$(CommonPath)System\Net\TcpValidationHelpers.cs"
Link="Common\System\Net\TcpValidationHelpers.cs" />
+ <Compile Include="$(CommonPath)System\Net\SocketAddressExtensions.cs"
+ Link="Common\System\Net\SocketAddressExtensions.cs" />
<Compile Include="$(CommonPath)System\Net\SocketProtocolSupportPal.cs"
Link="Common\System\Net\SocketProtocolSupportPal.cs" />
- <!-- System.Net.Internals -->
- <Compile Include="$(CommonPath)System\Net\Internals\IPEndPointExtensions.cs"
- Link="Common\System\Net\Internals\IPEndPointExtensions.cs" />
- <Compile Include="$(CommonPath)System\Net\Internals\IPAddressExtensions.cs"
- Link="Common\System\Net\Internals\IPAddressExtensions.cs" />
<Compile Include="$(CommonPath)System\Net\Sockets\SocketExceptionFactory.cs"
Link="Common\System\Net\Sockets\SocketExceptionFactory.cs" />
<Compile Include="$(CommonPath)System\Net\Sockets\ProtocolFamily.cs"
saea.SetBuffer(buffer);
saea.SocketFlags = socketFlags;
saea.RemoteEndPoint = remoteEndPoint;
+ saea._socketAddress = new SocketAddress(AddressFamily);
+ if (remoteEndPoint!.AddressFamily != AddressFamily && AddressFamily == AddressFamily.InterNetworkV6 && IsDualMode)
+ {
+ saea.RemoteEndPoint = s_IPEndPointIPv6;
+ }
saea.WrapExceptionsForNetworkStream = false;
return saea.ReceiveFromAsync(this, cancellationToken);
}
/// <summary>
+ /// Receives data and returns the endpoint of the sending host.
+ /// </summary>
+ /// <param name="buffer">The buffer for the received data.</param>
+ /// <param name="socketFlags">A bitwise combination of SocketFlags values that will be used when receiving the data.</param>
+ /// <param name="receivedAddress">An <see cref="SocketAddress"/>, that will be updated with value of the remote peer.</param>
+ /// <param name="cancellationToken">A cancellation token that can be used to signal the asynchronous operation should be canceled.</param>
+ /// <returns>An asynchronous task that completes with a <see cref="SocketReceiveFromResult"/> containing the number of bytes received and the endpoint of the sending host.</returns>
+ public ValueTask<int> ReceiveFromAsync(Memory<byte> buffer, SocketFlags socketFlags, SocketAddress receivedAddress, CancellationToken cancellationToken = default)
+ {
+ ThrowIfDisposed();
+ ArgumentNullException.ThrowIfNull(receivedAddress, nameof(receivedAddress));
+
+ if (receivedAddress.Size < SocketAddress.GetMaximumAddressSize(AddressFamily))
+ {
+ throw new ArgumentOutOfRangeException(nameof(receivedAddress), SR.net_sockets_address_small);
+ }
+
+ if (cancellationToken.IsCancellationRequested)
+ {
+ return ValueTask.FromCanceled<int>(cancellationToken);
+ }
+
+ AwaitableSocketAsyncEventArgs saea =
+ Interlocked.Exchange(ref _singleBufferReceiveEventArgs, null) ??
+ new AwaitableSocketAsyncEventArgs(this, isReceiveForCaching: true);
+
+ Debug.Assert(saea.BufferList == null);
+ saea.SetBuffer(buffer);
+ saea.SocketFlags = socketFlags;
+ saea.RemoteEndPoint = null;
+ saea._socketAddress = receivedAddress;
+ saea.WrapExceptionsForNetworkStream = false;
+ return saea.ReceiveFromSocketAddressAsync(this, cancellationToken);
+ }
+
+ /// <summary>
/// Receives data and returns additional information about the sender of the message.
/// </summary>
/// <param name="buffer">The buffer for the received data.</param>
Debug.Assert(saea.BufferList == null);
saea.SetBuffer(MemoryMarshal.AsMemory(buffer));
saea.SocketFlags = socketFlags;
+ saea._socketAddress = null;
saea.RemoteEndPoint = remoteEP;
saea.WrapExceptionsForNetworkStream = false;
return saea.SendToAsync(this, cancellationToken);
}
/// <summary>
+ /// Sends data to the specified remote host.
+ /// </summary>
+ /// <param name="buffer">The buffer for the data to send.</param>
+ /// <param name="socketFlags">A bitwise combination of SocketFlags values that will be used when sending the data.</param>
+ /// <param name="socketAddress">The remote host to which to send the data.</param>
+ /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
+ /// <returns>An asynchronous task that completes with the number of bytes sent.</returns>
+ public ValueTask<int> SendToAsync(ReadOnlyMemory<byte> buffer, SocketFlags socketFlags, SocketAddress socketAddress, CancellationToken cancellationToken = default)
+ {
+ ThrowIfDisposed();
+ ArgumentNullException.ThrowIfNull(socketAddress);
+
+ if (cancellationToken.IsCancellationRequested)
+ {
+ return ValueTask.FromCanceled<int>(cancellationToken);
+ }
+
+ AwaitableSocketAsyncEventArgs saea =
+ Interlocked.Exchange(ref _singleBufferSendEventArgs, null) ??
+ new AwaitableSocketAsyncEventArgs(this, isReceiveForCaching: false);
+
+ Debug.Assert(saea.BufferList == null);
+ saea.SetBuffer(MemoryMarshal.AsMemory(buffer));
+ saea.SocketFlags = socketFlags;
+ saea._socketAddress = socketAddress;
+ saea.WrapExceptionsForNetworkStream = false;
+ return saea.SendToAsync(this, cancellationToken);
+ }
+
+ /// <summary>
/// Sends the file <paramref name="fileName"/> to a connected <see cref="Socket"/> object.
/// </summary>
/// <param name="fileName">A <see cref="string"/> that contains the path and name of the file to be sent. This parameter can be <see langword="null"/>.</param>
ValueTask.FromException<SocketReceiveFromResult>(CreateException(error));
}
+ internal ValueTask<int> ReceiveFromSocketAddressAsync(Socket socket, CancellationToken cancellationToken)
+ {
+ if (socket.ReceiveFromAsync(this, cancellationToken))
+ {
+ _cancellationToken = cancellationToken;
+ return new ValueTask<int>(this, _mrvtsc.Version);
+ }
+
+ int bytesTransferred = BytesTransferred;
+ SocketError error = SocketError;
+
+ ReleaseForSyncCompletion();
+
+ return error == SocketError.Success ?
+ new ValueTask<int>(bytesTransferred) :
+ ValueTask.FromException<int>(CreateException(error));
+ }
+
public ValueTask<SocketReceiveMessageFromResult> ReceiveMessageFromAsync(Socket socket, CancellationToken cancellationToken)
{
if (socket.ReceiveMessageFromAsync(this, cancellationToken))
private sealed class CachedSerializedEndPoint
{
public readonly IPEndPoint IPEndPoint;
- public readonly Internals.SocketAddress SocketAddress;
+ public readonly SocketAddress SocketAddress;
public CachedSerializedEndPoint(IPAddress address)
{
IPEndPoint = new IPEndPoint(address, 0);
- SocketAddress = IPEndPointExtensions.Serialize(IPEndPoint);
+ SocketAddress = IPEndPoint.Serialize();
}
}
IPAddress tempAddress = _addressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any;
IPEndPoint ep = new IPEndPoint(tempAddress, 0);
- Internals.SocketAddress socketAddress = IPEndPointExtensions.Serialize(ep);
+ SocketAddress socketAddress = ep.Serialize();
int size = socketAddress.Buffer.Length;
unsafe
{
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
-using System.Net.Internals;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
internal const int DefaultCloseTimeout = -1; // NOTE: changing this default is a breaking change.
private static readonly IPAddress s_IPAddressAnyMapToIPv6 = IPAddress.Any.MapToIPv6();
+ private static readonly IPEndPoint s_IPEndPointIPv6 = new IPEndPoint(s_IPAddressAnyMapToIPv6, 0);
private SafeSocketHandle _handle;
// Try to get the local end point. That will in turn enable the remote
// end point to be retrieved on-demand when the property is accessed.
- Internals.SocketAddress? socketAddress = null;
switch (_addressFamily)
{
case AddressFamily.InterNetwork:
break;
case AddressFamily.Unix:
- socketAddress = new Internals.SocketAddress(AddressFamily.Unix, buffer.Slice(0, bufferLength));
- _rightEndPoint = new UnixDomainSocketEndPoint(IPEndPointExtensions.GetNetSocketAddress(socketAddress));
+ _rightEndPoint = new UnixDomainSocketEndPoint(buffer.Slice(0, bufferLength));
break;
}
break;
case AddressFamily.Unix:
- socketAddress = new Internals.SocketAddress(AddressFamily.Unix, buffer.Slice(0, bufferLength));
- _remoteEndPoint = new UnixDomainSocketEndPoint(IPEndPointExtensions.GetNetSocketAddress(socketAddress));
+ _remoteEndPoint = new UnixDomainSocketEndPoint(buffer.Slice(0, bufferLength));
break;
}
if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"localEP:{localEP}");
- Internals.SocketAddress socketAddress = Serialize(ref localEP);
+ SocketAddress socketAddress = Serialize(ref localEP);
DoBind(localEP, socketAddress);
}
- private void DoBind(EndPoint endPointSnapshot, Internals.SocketAddress socketAddress)
+ private void DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
{
// Mitigation for Blue Screen of Death (Win7, maybe others).
IPEndPoint? ipEndPoint = endPointSnapshot as IPEndPoint;
SocketError errorCode = SocketPal.Bind(
_handle,
_protocolType,
- socketAddress.Buffer.Span);
+ socketAddress.Buffer.Span.Slice(0, socketAddress.Size));
// Throw an appropriate SocketException if the native call fails.
if (errorCode != SocketError.Success)
ValidateForMultiConnect(isMultiEndpoint: false);
- Internals.SocketAddress socketAddress = Serialize(ref remoteEP);
+ SocketAddress socketAddress = Serialize(ref remoteEP);
_pendingConnectRightEndPoint = remoteEP;
_nonBlockingConnectInProgress = !Blocking;
ValidateBlockingMode();
if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"SRC:{LocalEndPoint}");
- Internals.SocketAddress socketAddress =
- _addressFamily == AddressFamily.InterNetwork || _addressFamily == AddressFamily.InterNetworkV6 ?
- IPEndPointExtensions.Serialize(_rightEndPoint) :
- new Internals.SocketAddress(_addressFamily, SocketPal.MaximumAddressSize); // may be different size.
+ SocketAddress socketAddress = new SocketAddress(_addressFamily);
if (SocketsTelemetry.Log.IsEnabled()) SocketsTelemetry.Log.AcceptStart(socketAddress);
ValidateBlockingMode();
if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"SRC:{LocalEndPoint} size:{size} remoteEP:{remoteEP}");
- Internals.SocketAddress socketAddress = Serialize(ref remoteEP);
+ SocketAddress socketAddress = Serialize(ref remoteEP);
int bytesTransferred;
- SocketError errorCode = SocketPal.SendTo(_handle, buffer, offset, size, socketFlags, socketAddress.Buffer, out bytesTransferred);
+ SocketError errorCode = SocketPal.SendTo(_handle, buffer, offset, size, socketFlags, socketAddress.Buffer.Slice(0, socketAddress.Size), out bytesTransferred);
// Throw an appropriate SocketException if the native call fails.
if (errorCode != SocketError.Success)
ValidateBlockingMode();
- Internals.SocketAddress socketAddress = Serialize(ref remoteEP);
+ SocketAddress socketAddress = Serialize(ref remoteEP);
int bytesTransferred;
- SocketError errorCode = SocketPal.SendTo(_handle, buffer, socketFlags, socketAddress.Buffer, out bytesTransferred);
+ SocketError errorCode = SocketPal.SendTo(_handle, buffer, socketFlags, socketAddress.Buffer.Slice(0, socketAddress.Size), out bytesTransferred);
// Throw an appropriate SocketException if the native call fails.
if (errorCode != SocketError.Success)
ValidateBlockingMode();
int bytesTransferred;
- SocketError errorCode = SocketPal.SendTo(_handle, buffer, socketFlags, socketAddress.Buffer, out bytesTransferred);
+ SocketError errorCode = SocketPal.SendTo(_handle, buffer, socketFlags, socketAddress.Buffer.Slice(0, socketAddress.Size), out bytesTransferred);
// Throw an appropriate SocketException if the native call fails.
if (errorCode != SocketError.Success)
// WSARecvMsg; all that matters is that we generate a unique-to-this-call SocketAddress
// with the right address family.
EndPoint endPointSnapshot = remoteEP;
- Internals.SocketAddress socketAddress = Serialize(ref endPointSnapshot);
-
- // Save a copy of the original EndPoint.
- Internals.SocketAddress socketAddressOriginal = IPEndPointExtensions.Serialize(endPointSnapshot);
+ SocketAddress socketAddress = Serialize(ref endPointSnapshot);
SetReceivingPacketInformation();
- Internals.SocketAddress receiveAddress;
+ SocketAddress receiveAddress;
int bytesTransferred;
SocketError errorCode = SocketPal.ReceiveMessageFrom(this, _handle, buffer, offset, size, ref socketFlags, socketAddress, out receiveAddress, out ipPacketInformation, out bytesTransferred);
if (errorCode == SocketError.Success && SocketType == SocketType.Dgram) SocketsTelemetry.Log.DatagramReceived();
}
- if (!socketAddressOriginal.Equals(receiveAddress))
+ if (!SocketAddressExtensions.Equals(socketAddress, remoteEP))
{
try
{
// WSARecvMsg; all that matters is that we generate a unique-to-this-call SocketAddress
// with the right address family.
EndPoint endPointSnapshot = remoteEP;
- Internals.SocketAddress socketAddress = Serialize(ref endPointSnapshot);
-
- // Save a copy of the original EndPoint.
- Internals.SocketAddress socketAddressOriginal = IPEndPointExtensions.Serialize(endPointSnapshot);
+ SocketAddress socketAddress = Serialize(ref endPointSnapshot);
SetReceivingPacketInformation();
- Internals.SocketAddress receiveAddress;
+ SocketAddress receiveAddress;
int bytesTransferred;
SocketError errorCode = SocketPal.ReceiveMessageFrom(this, _handle, buffer, ref socketFlags, socketAddress, out receiveAddress, out ipPacketInformation, out bytesTransferred);
if (errorCode == SocketError.Success && SocketType == SocketType.Dgram) SocketsTelemetry.Log.DatagramReceived();
}
- if (!socketAddressOriginal.Equals(receiveAddress))
+ if (!SocketAddressExtensions.Equals(socketAddress, remoteEP))
{
try
{
// WSARecvFrom; all that matters is that we generate a unique-to-this-call SocketAddress
// with the right address family.
EndPoint endPointSnapshot = remoteEP;
- Internals.SocketAddress socketAddress = Serialize(ref endPointSnapshot);
- Internals.SocketAddress socketAddressOriginal = IPEndPointExtensions.Serialize(endPointSnapshot);
+ SocketAddress socketAddress = new SocketAddress(AddressFamily);
+ if (endPointSnapshot.AddressFamily == AddressFamily.InterNetwork && IsDualMode)
+ {
+ endPointSnapshot = s_IPEndPointIPv6;
+ }
int bytesTransferred;
SocketError errorCode = SocketPal.ReceiveFrom(_handle, buffer, offset, size, socketFlags, socketAddress.Buffer, out int socketAddressLength, out bytesTransferred);
socketAddress.Size = socketAddressLength;
- if (!socketAddressOriginal.Equals(socketAddress))
+ if (socketAddressLength > 0 && !socketAddress.Equals(remoteEP) || remoteEP.AddressFamily != socketAddress.Family)
{
try
{
if (endPointSnapshot.AddressFamily == socketAddress.Family)
{
- remoteEP = _remoteEndPoint != null ? _remoteEndPoint.Create(socketAddress) : socketAddress.GetIPEndPoint();
+ remoteEP = endPointSnapshot.Create(socketAddress);
}
- else if (endPointSnapshot.AddressFamily == AddressFamily.InterNetworkV6 && socketAddress.Family == AddressFamily.InterNetwork)
+ //else if (socketAddress.Family == AddressFamily.InterNetworkV6 && IsDualMode)
+ //{
+ // remoteEP = socketAddress.GetIPEndPoint();
+ //}
+ else if (AddressFamily == AddressFamily.InterNetworkV6 && socketAddress.Family == AddressFamily.InterNetwork)
{
// We expect IPv6 on DualMode sockets but we can also get plain old IPv4
remoteEP = new IPEndPoint(socketAddress.GetIPAddress().MapToIPv6(), socketAddress.GetPort());
// WSARecvFrom; all that matters is that we generate a unique-to-this-call SocketAddress
// with the right address family.
EndPoint endPointSnapshot = remoteEP;
- Internals.SocketAddress socketAddress = Serialize(ref endPointSnapshot);
- Internals.SocketAddress socketAddressOriginal = IPEndPointExtensions.Serialize(endPointSnapshot);
+ SocketAddress socketAddress = new SocketAddress(AddressFamily);
+ if (endPointSnapshot.AddressFamily == AddressFamily.InterNetwork && IsDualMode)
+ {
+ endPointSnapshot = s_IPEndPointIPv6;
+ }
int bytesTransferred;
SocketError errorCode = SocketPal.ReceiveFrom(_handle, buffer, socketFlags, socketAddress.Buffer, out int socketAddressLength, out bytesTransferred);
}
socketAddress.Size = socketAddressLength;
- if (!socketAddressOriginal.Equals(socketAddress))
+ if (socketAddressLength > 0 && !socketAddress.Equals(remoteEP) || remoteEP.AddressFamily != socketAddress.Family)
{
try
{
if (endPointSnapshot.AddressFamily == socketAddress.Family)
{
- remoteEP = _remoteEndPoint != null ? _remoteEndPoint.Create(socketAddress) : socketAddress.GetIPEndPoint();
+ remoteEP = endPointSnapshot.Create(socketAddress);
}
else if (endPointSnapshot.AddressFamily == AddressFamily.InterNetworkV6 && socketAddress.Family == AddressFamily.InterNetwork)
{
/// </summary>
/// <param name="buffer">A span of bytes that is the storage location for received data.</param>
/// <param name="socketFlags">A bitwise combination of the <see cref="SocketFlags"/> values.</param>
- /// <param name="receivedSocketAddress">An <see cref="SocketAddress"/>, that will be updated with value of the remote peer.</param>
+ /// <param name="receivedAddress">An <see cref="SocketAddress"/>, that will be updated with value of the remote peer.</param>
/// <returns>The number of bytes received.</returns>
/// <exception cref="ArgumentNullException"><c>remoteEP</c> is <see langword="null" />.</exception>
/// <exception cref="SocketException">An error occurred when attempting to access the socket.</exception>
/// <exception cref="ObjectDisposedException">The <see cref="Socket"/> has been closed.</exception>
- public int ReceiveFrom(Span<byte> buffer, SocketFlags socketFlags, SocketAddress receivedSocketAddress)
+ public int ReceiveFrom(Span<byte> buffer, SocketFlags socketFlags, SocketAddress receivedAddress)
{
ThrowIfDisposed();
+ ArgumentNullException.ThrowIfNull(receivedAddress, nameof(receivedAddress));
- if (receivedSocketAddress.Size < SocketAddress.GetMaximumAddressSize(AddressFamily))
+ if (receivedAddress.Size < SocketAddress.GetMaximumAddressSize(AddressFamily))
{
- throw new ArgumentOutOfRangeException(nameof(receivedSocketAddress), SR.net_sockets_address_small);
+ throw new ArgumentOutOfRangeException(nameof(receivedAddress), SR.net_sockets_address_small);
}
ValidateBlockingMode();
int bytesTransferred;
- SocketError errorCode = SocketPal.ReceiveFrom(_handle, buffer, socketFlags, receivedSocketAddress.Buffer, out int socketAddressSize, out bytesTransferred);
- if (socketAddressSize > 0)
- {
- receivedSocketAddress.Size = socketAddressSize;
- }
+ SocketError errorCode = SocketPal.ReceiveFrom(_handle, buffer, socketFlags, receivedAddress.Buffer, out int socketAddressSize, out bytesTransferred);
+ receivedAddress.Size = socketAddressSize;
+
UpdateReceiveSocketErrorForDisposed(ref errorCode, bytesTransferred);
// If the native call fails we'll throw a SocketException.
if (errorCode != SocketError.Success)
ThrowIfDisposed();
ArgumentNullException.ThrowIfNull(e);
- if (e.RemoteEndPoint == null)
- {
- throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "e.RemoteEndPoint"), nameof(e));
- }
- if (!CanTryAddressFamily(e.RemoteEndPoint.AddressFamily))
+ EndPoint? endPointSnapshot = e.RemoteEndPoint;
+ if (e._socketAddress == null)
{
- throw new ArgumentException(SR.Format(SR.net_InvalidEndPointAddressFamily, e.RemoteEndPoint.AddressFamily, _addressFamily), nameof(e));
- }
+ if (endPointSnapshot is DnsEndPoint)
+ {
+ throw new ArgumentException(SR.Format(SR.net_sockets_invalid_dnsendpoint, "e.RemoteEndPoint"), nameof(e));
+ }
- // We don't do a CAS demand here because the contents of remoteEP aren't used by
- // WSARecvFrom; all that matters is that we generate a unique-to-this-call SocketAddress
- // with the right address family.
- EndPoint endPointSnapshot = e.RemoteEndPoint;
- e._socketAddress = Serialize(ref endPointSnapshot);
+ if (endPointSnapshot == null)
+ {
+ throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "e.RemoteEndPoint"), nameof(e));
+ }
+ if (!CanTryAddressFamily(endPointSnapshot.AddressFamily))
+ {
+ throw new ArgumentException(SR.Format(SR.net_InvalidEndPointAddressFamily, endPointSnapshot.AddressFamily, _addressFamily), nameof(e));
+ }
+
+ // We don't do a CAS demand here because the contents of remoteEP aren't used by
+ // WSARecvFrom; all that matters is that we generate a unique-to-this-call SocketAddress
+ // with the right address family.
+
+ if (endPointSnapshot.AddressFamily == AddressFamily.InterNetwork && IsDualMode)
+ {
+ endPointSnapshot = s_IPEndPointIPv6;
+ }
+ e._socketAddress ??= new SocketAddress(AddressFamily);
+ }
// DualMode sockets may have updated the endPointSnapshot, and it has to have the same AddressFamily as
// e.m_SocketAddres for Create to work later.
ThrowIfDisposed();
ArgumentNullException.ThrowIfNull(e);
- if (e.RemoteEndPoint == null)
+
+ EndPoint? endPointSnapshot = e.RemoteEndPoint;
+ if (e._socketAddress == null)
{
- throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "e.RemoteEndPoint"), nameof(e));
- }
+ if (endPointSnapshot == null)
+ {
+ throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "e.RemoteEndPoint"), nameof(e));
+ }
- // Prepare SocketAddress
- EndPoint endPointSnapshot = e.RemoteEndPoint;
- e._socketAddress = Serialize(ref endPointSnapshot);
+ // Prepare SocketAddress
+ e._socketAddress = Serialize(ref endPointSnapshot);
+ }
// Prepare for and make the native call.
e.StartOperationCommon(this, SocketAsyncOperation.SendTo);
// Internal and private methods
//
- internal static void GetIPProtocolInformation(AddressFamily addressFamily, Internals.SocketAddress socketAddress, out bool isIPv4, out bool isIPv6)
+ internal static void GetIPProtocolInformation(AddressFamily addressFamily, SocketAddress socketAddress, out bool isIPv4, out bool isIPv6)
{
bool isIPv4MappedToIPv6 = socketAddress.Family == AddressFamily.InterNetworkV6 && socketAddress.GetIPAddress().IsIPv4MappedToIPv6;
isIPv4 = addressFamily == AddressFamily.InterNetwork || isIPv4MappedToIPv6; // DualMode
endPoint.Serialize().Size;
}
- private Internals.SocketAddress Serialize(ref EndPoint remoteEP)
+ private SocketAddress Serialize(ref EndPoint remoteEP)
{
if (remoteEP is IPEndPoint ip)
{
throw new ArgumentException(SR.Format(SR.net_sockets_invalid_dnsendpoint, nameof(remoteEP)), nameof(remoteEP));
}
- return IPEndPointExtensions.Serialize(remoteEP);
+ return remoteEP.Serialize();
}
- private void DoConnect(EndPoint endPointSnapshot, Internals.SocketAddress socketAddress)
+ private void DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
{
SocketsTelemetry.Log.ConnectStart(socketAddress);
SocketError errorCode;
try
{
- errorCode = SocketPal.Connect(_handle, socketAddress.Buffer);
+ errorCode = SocketPal.Connect(_handle, socketAddress.Buffer.Slice(0, socketAddress.Size));
}
catch (Exception ex)
{
private void ValidateReceiveFromEndpointAndState(EndPoint remoteEndPoint, string remoteEndPointArgumentName)
{
ArgumentNullException.ThrowIfNull(remoteEndPoint, remoteEndPointArgumentName);
+
+ if (remoteEndPoint is DnsEndPoint)
+ {
+ throw new ArgumentException(SR.Format(SR.net_sockets_invalid_dnsendpoint, remoteEndPointArgumentName), remoteEndPointArgumentName);
+ }
+
if (!CanTryAddressFamily(remoteEndPoint.AddressFamily))
{
throw new ArgumentException(SR.Format(SR.net_InvalidEndPointAddressFamily, remoteEndPoint.AddressFamily, _addressFamily), remoteEndPointArgumentName);
bool isIPv4, isIPv6;
Socket.GetIPProtocolInformation(socket.AddressFamily, _socketAddress!, out isIPv4, out isIPv6);
- int socketAddressSize = _socketAddress!.Size;
+ int socketAddressSize = _socketAddress!.Buffer.Length;
int bytesReceived;
SocketFlags receivedFlags;
IPPacketInformation ipPacketInformation;
}
}
- private SocketError FinishOperationAccept(Internals.SocketAddress remoteSocketAddress)
+ private SocketError FinishOperationAccept(SocketAddress remoteSocketAddress)
{
new ReadOnlySpan<byte>(_acceptBuffer, 0, _acceptAddressBufferCount).CopyTo(remoteSocketAddress.Buffer.Span);
remoteSocketAddress.Size = _acceptAddressBufferCount;
return SocketError.Success;
}
- private void UpdateReceivedSocketAddress(Internals.SocketAddress socketAddress)
+ private void UpdateReceivedSocketAddress(SocketAddress socketAddress)
{
if (_socketAddressSize > 0)
{
}
}
- private unsafe SocketError FinishOperationAccept(Internals.SocketAddress remoteSocketAddress)
+ private unsafe SocketError FinishOperationAccept(SocketAddress remoteSocketAddress)
{
SocketError socketError;
IntPtr localAddr;
}
}
- private unsafe void UpdateReceivedSocketAddress(Internals.SocketAddress socketAddress)
+ private unsafe void UpdateReceivedSocketAddress(SocketAddress socketAddress)
{
Debug.Assert(_socketAddressPtr != IntPtr.Zero);
int size = *((int*)_socketAddressPtr);
private int _acceptAddressBufferCount;
// Internal SocketAddress buffer.
- internal Internals.SocketAddress? _socketAddress;
+ internal SocketAddress? _socketAddress;
// Misc state variables.
private readonly bool _flowExecutionContext;
{
case SocketAsyncOperation.Accept:
// Get the endpoint.
- Internals.SocketAddress remoteSocketAddress = IPEndPointExtensions.Serialize(_currentSocket!._rightEndPoint!);
+ SocketAddress remoteSocketAddress = _currentSocket!._rightEndPoint!.Serialize();
socketError = FinishOperationAccept(remoteSocketAddress);
case SocketAsyncOperation.ReceiveFrom:
// Deal with incoming address.
UpdateReceivedSocketAddress(_socketAddress!);
- Internals.SocketAddress socketAddressOriginal = IPEndPointExtensions.Serialize(_remoteEndPoint!);
- if (!socketAddressOriginal.Equals(_socketAddress))
+ if (_remoteEndPoint != null && !SocketAddressExtensions.Equals(_socketAddress!, _remoteEndPoint))
{
try
{
case SocketAsyncOperation.ReceiveMessageFrom:
// Deal with incoming address.
UpdateReceivedSocketAddress(_socketAddress!);
- socketAddressOriginal = IPEndPointExtensions.Serialize(_remoteEndPoint!);
- if (!socketAddressOriginal.Equals(_socketAddress))
+ if (!SocketAddressExtensions.Equals(_socketAddress!, _remoteEndPoint))
{
try
{
{
bytesReceived = received;
errorCode = SocketError.Success;
- if (socketAddress.Length > 0 && receivedSocketAddressLength == 0)
- {
- // We can fail to get peer address on TCP
- receivedSocketAddressLength = socketAddress.Length;
- SocketAddressPal.Clear(socketAddress);
- }
return true;
}
return completed ? errorCode : SocketError.WouldBlock;
}
- public static SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, byte[] buffer, int offset, int count, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
+ public static SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, byte[] buffer, int offset, int count, ref SocketFlags socketFlags, SocketAddress socketAddress, out SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
{
int socketAddressLen;
}
- public static SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, Span<byte> buffer, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
+ public static SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, Span<byte> buffer, ref SocketFlags socketFlags, SocketAddress socketAddress, out SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
{
int socketAddressLen;
return new IPPacketInformation(address, (int)controlBuffer->index);
}
- public static unsafe SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, byte[] buffer, int offset, int size, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
+ public static unsafe SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, byte[] buffer, int offset, int size, ref SocketFlags socketFlags, SocketAddress socketAddress, out SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
{
return ReceiveMessageFrom(socket, handle, new Span<byte>(buffer, offset, size), ref socketFlags, socketAddress, out receiveAddress, out ipPacketInformation, out bytesTransferred);
}
- public static unsafe SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, Span<byte> buffer, ref SocketFlags socketFlags, Internals.SocketAddress socketAddress, out Internals.SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
+ public static unsafe SocketError ReceiveMessageFrom(Socket socket, SafeSocketHandle handle, Span<byte> buffer, ref SocketFlags socketFlags, SocketAddress socketAddress, out SocketAddress receiveAddress, out IPPacketInformation ipPacketInformation, out int bytesTransferred)
{
bool ipv4, ipv6;
Socket.GetIPProtocolInformation(socket.AddressFamily, socketAddress, out ipv4, out ipv6);
}
[NonEvent]
- public void ConnectStart(Internals.SocketAddress address)
+ public void ConnectStart(SocketAddress address)
{
Interlocked.Increment(ref _currentOutgoingConnectAttempts);
}
[NonEvent]
- public void AcceptStart(Internals.SocketAddress address)
+ public void AcceptStart(SocketAddress address)
{
if (IsEnabled(EventLevel.Informational, EventKeywords.All))
{
internal static int MaxAddressSize => s_nativeAddressSize;
- internal UnixDomainSocketEndPoint(SocketAddress socketAddress)
+ internal UnixDomainSocketEndPoint(ReadOnlySpan<byte> socketAddress)
{
- ArgumentNullException.ThrowIfNull(socketAddress);
+ Debug.Assert(AddressFamily.Unix == SocketAddressPal.GetAddressFamily(socketAddress));
- if (socketAddress.Family != EndPointAddressFamily ||
- socketAddress.Size > s_nativeAddressSize)
+ if (socketAddress.Length > s_nativePathOffset)
{
- throw new ArgumentOutOfRangeException(nameof(socketAddress));
- }
-
- if (socketAddress.Size > s_nativePathOffset)
- {
- _encodedPath = new byte[socketAddress.Size - s_nativePathOffset];
+ _encodedPath = new byte[socketAddress.Length - s_nativePathOffset];
for (int i = 0; i < _encodedPath.Length; i++)
{
_encodedPath[i] = socketAddress[s_nativePathOffset + i];
/// <summary>Creates an <see cref="EndPoint"/> instance from a <see cref="SocketAddress"/> instance.</summary>
/// <param name="socketAddress">The socket address that serves as the endpoint for a connection.</param>
/// <returns>A new <see cref="EndPoint"/> instance that is initialized from the specified <see cref="SocketAddress"/> instance.</returns>
- public override EndPoint Create(SocketAddress socketAddress) => new UnixDomainSocketEndPoint(socketAddress);
+ public override EndPoint Create(SocketAddress socketAddress) => new UnixDomainSocketEndPoint(socketAddress.Buffer.Span.Slice(0, socketAddress.Size));
/// <summary>Gets the address family to which the endpoint belongs.</summary>
/// <value>One of the <see cref="AddressFamily"/> values.</value>
int port = socket.BindToAnonymousPort(IPAddress.IPv6Loopback);
EndPoint receivedFrom = new DnsEndPoint("localhost", port, AddressFamily.InterNetworkV6);
- await AssertExtensions.ThrowsAsync<ArgumentException>("remoteEP", () => ReceiveFromAsync(socket, new byte[1], receivedFrom));
+ await Assert.ThrowsAsync<ArgumentException>(() => ReceiveFromAsync(socket, new byte[1], receivedFrom));
}
[Fact]
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Collections.Generic;
-using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
}
[Fact]
+ public async Task NullSocketAddress_Throws_ArgumentException()
+ {
+ using Socket socket = CreateSocket();
+ SocketAddress socketAddress = null;
+
+ Assert.Throws<ArgumentNullException>(() => socket.ReceiveFrom(new byte[1], SocketFlags.None, socketAddress));
+ await Assert.ThrowsAsync<ArgumentNullException>(() => socket.ReceiveFromAsync(new Memory<byte>(new byte[1]), SocketFlags.None, socketAddress).AsTask());
+ }
+
+ [Fact]
public async Task AddressFamilyDoesNotMatch_Throws_ArgumentException()
{
using var ipv4Socket = CreateSocket();
AssertExtensions.SequenceEqual(emptyBuffer, new ReadOnlySpan<byte>(receiveInternalBuffer, 0, Offset));
AssertExtensions.SequenceEqual(sendBuffer, new ReadOnlySpan<byte>(receiveInternalBuffer, Offset, DatagramSize));
Assert.Equal(sender.LocalEndPoint, result.RemoteEndPoint);
+ remoteEp = (IPEndPoint)result.RemoteEndPoint;
+ if (i > 0)
+ {
+ // reference should be same after first round
+ Assert.True(remoteEp == result.RemoteEndPoint);
+ }
}
}
Assert.Equal(sa, serverSA);
Assert.Equal(server.LocalEndPoint, server.LocalEndPoint.Create(sa));
Assert.True(new Span<byte>(receiveBuffer, 0, readBytes).SequenceEqual(sendBuffer));
+ }
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public async Task ReceiveSent_SocketAddressAsync_Success(bool ipv4)
+ {
+ const int DatagramSize = 256;
+ const int DatagramsToSend = 16;
+
+ IPAddress address = ipv4 ? IPAddress.Loopback : IPAddress.IPv6Loopback;
+ using Socket server = new Socket(address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
+ using Socket client = new Socket(address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
+
+ client.BindToAnonymousPort(address);
+ server.BindToAnonymousPort(address);
+
+ byte[] sendBuffer = new byte[DatagramSize];
+ byte[] receiveBuffer = new byte[DatagramSize];
+
+ SocketAddress serverSA = server.LocalEndPoint.Serialize();
+ SocketAddress clientSA = client.LocalEndPoint.Serialize();
+ SocketAddress sa = new SocketAddress(address.AddressFamily);
+
+ Random rnd = new Random(0);
+
+ for (int i = 0; i < DatagramsToSend; i++)
+ {
+ rnd.NextBytes(sendBuffer);
+ await client.SendToAsync(sendBuffer, SocketFlags.None, serverSA);
+
+ int readBytes = await server.ReceiveFromAsync(receiveBuffer, SocketFlags.None, sa);
+ Assert.Equal(sa, clientSA);
+ Assert.Equal(client.LocalEndPoint, client.LocalEndPoint.Create(sa));
+ Assert.True(new Span<byte>(receiveBuffer, 0, readBytes).SequenceEqual(sendBuffer));
+ // and send it back to make sure it works.
+ rnd.NextBytes(sendBuffer);
+ await server.SendToAsync(sendBuffer, SocketFlags.None, sa);
+ readBytes = await client.ReceiveFromAsync(receiveBuffer, SocketFlags.None, sa);
+ Assert.Equal(sa, serverSA);
+ Assert.Equal(server.LocalEndPoint, server.LocalEndPoint.Create(sa));
+ Assert.True(new Span<byte>(receiveBuffer, 0, readBytes).SequenceEqual(sendBuffer));
}
}
}
[Fact]
+ public async Task NullSocketAddress_Throws_ArgumentException()
+ {
+ using Socket socket = CreateSocket();
+ SocketAddress socketAddress = null;
+
+ Assert.Throws<ArgumentNullException>(() => socket.SendTo(new byte[1], SocketFlags.None, socketAddress));
+ await AssertThrowsSynchronously<ArgumentNullException>(() => socket.SendToAsync(new byte[1], SocketFlags.None, socketAddress).AsTask());
+ }
+
+ [Fact]
public async Task Datagram_UDP_ShouldImplicitlyBindLocalEndpoint()
{
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.DotNet.RemoteExecutor;
}
// An abstract socket address starts with a zero byte.
serverAddress = '\0' + Guid.NewGuid().ToString();
- clientAddress = '\0' + Guid.NewGuid().ToString();
+ clientAddress = '\0' + Guid.NewGuid().ToString() + "ABC";
expectedClientAddress = '@' + clientAddress.Substring(1);
}
else
{
serverAddress = GetRandomNonExistingFilePath();
- clientAddress = GetRandomNonExistingFilePath();
+ clientAddress = GetRandomNonExistingFilePath() + "ABC";
expectedClientAddress = clientAddress;
}
Assert.NotEqual(endPoint2, endPoint3);
}
+ [ConditionalTheory(typeof(Socket), nameof(Socket.OSSupportsUnixDomainSockets))]
+ [ActiveIssue("https://github.com/dotnet/runtime/issues/26189", TestPlatforms.Windows)]
+ [SkipOnPlatform(TestPlatforms.LinuxBionic, "SElinux blocks UNIX sockets in our CI environment")]
+ [InlineData(true)]
+ [InlineData(false)]
+ public async Task ReceiveFrom_EndPoints_Correct(bool useAsync)
+ {
+ string serverAddress = GetRandomNonExistingFilePath();
+ string clientAddress = GetRandomNonExistingFilePath() + "ABCD";
+
+ using (Socket server = new Socket(AddressFamily.Unix, SocketType.Dgram, ProtocolType.Unspecified))
+ {
+ server.Bind(new UnixDomainSocketEndPoint(serverAddress));
+ using (Socket client = new Socket(AddressFamily.Unix, SocketType.Dgram, ProtocolType.Unspecified))
+ {
+ byte[] data = Encoding.ASCII.GetBytes(nameof(ReceiveFrom_EndPoints_Correct));
+ // Bind the client.
+ client.Bind(new UnixDomainSocketEndPoint(clientAddress));
+
+ var sender = new UnixDomainSocketEndPoint(GetRandomNonExistingFilePath());
+ EndPoint senderRemote = (EndPoint)sender;
+ int transferredBytes;
+ if (useAsync)
+ {
+ transferredBytes = await client.SendToAsync(data, server.LocalEndPoint);
+ }
+ else
+ {
+ transferredBytes = client.SendTo(data, server.LocalEndPoint);
+ }
+ Assert.Equal(data.Length, transferredBytes);
+
+ byte[] buffer = new byte[data.Length * 2];
+ if (useAsync)
+ {
+ SocketReceiveFromResult result = await server.ReceiveFromAsync(buffer, senderRemote);
+ Assert.Equal(clientAddress, result.RemoteEndPoint.ToString());
+ Assert.Equal(data.Length, result.ReceivedBytes);
+ }
+ else
+ {
+ transferredBytes = server.ReceiveFrom(buffer, ref senderRemote);
+ Assert.Equal(data.Length, transferredBytes);
+ Assert.Equal(clientAddress, senderRemote.ToString());
+ }
+ }
+ }
+ }
+
private static string GetRandomNonExistingFilePath()
{
string result;