Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
- template: azure-pipelines-templates/class-lib-build.yml@templates
parameters:
sonarCloudProject: 'nanoframework_lib-nanoFramework.System.Net'
runUnitTests: true
runUnitTests: false
unitTestRunsettings: '$(System.DefaultWorkingDirectory)\Tests\SocketTests\nano.runsettings'

##############################
Expand Down
28 changes: 18 additions & 10 deletions nanoFramework.System.Net/DNS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,28 @@ public static class Dns
/// </remarks>
public static IPHostEntry GetHostEntry(string hostNameOrAddress)
{
NativeSocket.getaddrinfo(hostNameOrAddress, out string canonicalName, out byte[][] addresses);

//Do we need to try to pase this as an Address????
string canonicalName;
byte[][] addresses;
int addressesCount = addresses.Length;
IPAddress[] ipAddresses = new IPAddress[addressesCount];
IPHostEntry ipHostEntry = new();

NativeSocket.getaddrinfo(hostNameOrAddress, out canonicalName, out addresses);
for (int i = 0; i < addressesCount; i++)
{
byte[] address = addresses[i];

int cAddresses = addresses.Length;
IPAddress[] ipAddresses = new IPAddress[cAddresses];
IPHostEntry ipHostEntry = new IPHostEntry();
AddressFamily family = (AddressFamily)((address[1] << 8) | address[0]);

for (int i = 0; i < cAddresses; i++)
{
ipAddresses[i] = new IPAddress(addresses[i]);
if (family == AddressFamily.InterNetwork)
{
uint ipAddr = (uint)((address[7] << 24) | (address[6] << 16) | (address[5] << 8) | (address[4]));

ipAddresses[i] = new IPAddress(ipAddr);
}
else
{
throw new NotImplementedException();
}
}

ipHostEntry.hostName = canonicalName;
Expand Down
83 changes: 62 additions & 21 deletions nanoFramework.System.Net/IPAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,28 @@
namespace System.Net
{
/// <summary>
/// Provides an internet protocol (IP) address.
/// Initializes a new instance of the <see cref="IPAddress"/> class.
/// </summary>
[Serializable]
public class IPAddress
{
/// <summary>
/// Provides an IP address that indicates that the server must listen for client activity on all network interfaces.
/// This field is read-only.
/// Provides an IP address that indicates that the server must listen for client activity on all network interfaces. This field is read-only.
/// </summary>
public static readonly IPAddress Any = new IPAddress(0x0000000000000000);
public static readonly IPAddress Any = new(0x0000000000000000);

/// <summary>
/// Provides the IP loopback address. This field is read-only.
/// </summary>
public static readonly IPAddress Loopback = new IPAddress(0x000000000100007F);
public static readonly IPAddress Loopback = new(0x000000000100007F);

internal long Address;
internal readonly long Address;

[Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)]
private AddressFamily _family = AddressFamily.InterNetwork;
private readonly AddressFamily _family = AddressFamily.InterNetwork;

[Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)]
private ushort[] _numbers = new ushort[NumberOfLabels];
private readonly ushort[] _numbers = new ushort[NumberOfLabels];

internal const int IPv4AddressBytes = 4;
internal const int IPv6AddressBytes = 16;
Expand All @@ -55,12 +54,22 @@ public AddressFamily AddressFamily
/// <summary>
/// Initializes a new instance of the <see cref="IPAddress"/> class with the address specified as an Int64.
/// </summary>
/// <param name="newAddress"></param>
/// <param name="newAddress">The long value of the IP address. For example, the value 0x2414188f in big-endian format would be the IP address "143.24.20.36".</param>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="newAddress"/> &lt; 0 or
/// <paramref name="newAddress"/> &gt; 0x00000000FFFFFFFF
/// </exception>
/// <remarks>
/// The IPAddress instance is created with the <see cref="Address"/> property set to <paramref name="newAddress"/>.
/// The <see cref="Int64"/> value is assumed to be in network byte order.
/// </remarks>
public IPAddress(long newAddress)
{
if (newAddress < 0 || newAddress > 0x00000000FFFFFFFF)
{
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
throw new ArgumentOutOfRangeException();
#pragma warning restore S3928 // OK to throw this here
}

Address = newAddress;
Expand All @@ -73,15 +82,29 @@ public IPAddress(long newAddress)
/// Initializes a new instance of the <see cref="IPAddress"/> class with the address specified as a Byte array.
/// </summary>
/// <param name="address"></param>
/// <exception cref="ArgumentNullException"><paramref name="address"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="address"/> contains a bad IP address.</exception>
/// <remarks>
/// The IPAddress is created with the <see cref="Address"/> property set to <paramref name="address"/>.
/// If the length of <paramref name="address"/> is 4, <see cref="IPAddress"/>(Byte[]) constructs an IPv4 address; otherwise, an IPv6 address with a scope of 0 is constructed.
/// The <see cref="Byte"/> array is assumed to be in network byte order with the most significant byte first in index position 0.
/// </remarks>
public IPAddress(byte[] address)
{
if (address[0] == (byte)AddressFamily.InterNetwork)
if (address == null)
{
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
throw new ArgumentNullException();
#pragma warning restore S3928 // OK to throw this here
}

if (address.Length == IPv4AddressBytes)
{
_family = AddressFamily.InterNetwork;
// need to offset address by 4 (1st are family, 2nd are port
Address = ((address[3 + 4] << 24 | address[2 + 4] << 16 | address[1 + 4] << 8 | address[0 + 4]) & 0x0FFFFFFFF);

Address = (address[3] << 24 | address[2] << 16 | address[1] << 8 | address[0]) & 0x0FFFFFFFF;
}
else if (address[0] == (byte)AddressFamily.InterNetworkV6)
else if (address.Length == IPv6AddressBytes)
{
_family = AddressFamily.InterNetworkV6;

Expand All @@ -93,7 +116,9 @@ public IPAddress(byte[] address)
else
{
// unsupported address family
throw new NotSupportedException();
#pragma warning disable S3928 // Parameter names used into ArgumentException constructors should match an existing one
throw new ArgumentException();
#pragma warning restore S3928 // OK to throw this here
}
}

Expand Down Expand Up @@ -140,12 +165,10 @@ public static IPAddress Parse(string ipString)
/// <summary>
/// Converts an Internet address to its standard notation.
/// </summary>
/// <returns>A string that contains the IP address in either IPv4 dotted-quad or
/// in IPv6 colon-hexadecimal notation.
/// <returns>A string that contains the IP address in either IPv4 dotted-quad or in IPv6 colon-hexadecimal notation.
/// </returns>
/// <remarks>
/// The ToString method converts the IP address that is stored in the Address property to either IPv4 dotted-quad or
/// IPv6 colon-hexadecimal notation.
/// The <see cref="ToString"/> method converts the IP address that is stored in the <see cref="Address"/> property to either IPv4 dotted-quad or IPv6 colon-hexadecimal notation.
/// </remarks>
public override string ToString()
{
Expand All @@ -161,6 +184,7 @@ public static IPAddress GetDefaultLocalAddress()
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();

int cnt = interfaces.Length;

for (int i = 0; i < cnt; i++)
{
NetworkInterface ni = interfaces[i];
Expand All @@ -180,6 +204,23 @@ public static IPAddress GetDefaultLocalAddress()
return Any;
}

/// <inheritdoc/>
public override int GetHashCode()
{
// For IPv6 addresses, we cannot simply return the integer
// representation as the hashcode. Instead, we calculate
// the hashcode from the string representation of the address.
if (_family == AddressFamily.InterNetworkV6)
{
return ToString().GetHashCode();
}
else
{
// For IPv4 addresses, we can simply use the integer representation.
return unchecked((int)Address);
}
}

// For security, we need to be able to take an IPAddress and make a copy that's immutable and not derived.
internal IPAddress Snapshot()
{
Expand All @@ -188,8 +229,8 @@ internal IPAddress Snapshot()
case AddressFamily.InterNetwork:
return new IPAddress(Address);

//case AddressFamily.InterNetworkV6:
// return new IPAddress(m_Numbers, (uint)m_ScopeId);
//case AddressFamily.InterNetworkV6:
// return new IPAddress(m_Numbers, (uint)m_ScopeId);
}

throw new NotSupportedException();
Expand Down
27 changes: 17 additions & 10 deletions nanoFramework.System.Net/IPEndPoint.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// namespace System.Net
//
// Copyright (c) .NET Foundation and Contributors
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
Expand All @@ -19,17 +18,17 @@ public class IPEndPoint : EndPoint
/// Specifies the minimum value that can be assigned to the Port property. This field is read-only.
/// </summary>
public const int MinPort = 0x00000000;

/// <summary>
/// Specifies the maximum value that can be assigned to the Port property. The MaxPort value is set to 0x0000FFFF. This field is read-only.
/// </summary>
public const int MaxPort = 0x0000FFFF;

[Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)]
private IPAddress _address;
private readonly IPAddress _address;

[Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)]
private int _port;
private readonly int _port;

/// <summary>
/// Initializes a new instance of the <see cref="IPEndPoint"/> class with the specified address and port number.
Expand Down Expand Up @@ -96,9 +95,12 @@ public int Port
public override SocketAddress Serialize()
{
// create a new SocketAddress
//
SocketAddress socketAddress = new SocketAddress(AddressFamily.InterNetwork, SocketAddress.IPv4AddressSize);
SocketAddress socketAddress = new(
AddressFamily.InterNetwork,
SocketAddress.IPv4AddressSize);

byte[] buffer = socketAddress.m_Buffer;

//
// populate it
//
Expand Down Expand Up @@ -127,10 +129,10 @@ public override EndPoint Create(SocketAddress socketAddress)

// Debug.Assert(socketAddress.Family == AddressFamily.InterNetwork);

int port = (int)(
int port =
(buf[2] << 8 & 0xFF00) |
(buf[3])
);
;

long address = (long)(
(buf[4] & 0x000000FF) |
Expand Down Expand Up @@ -158,15 +160,20 @@ public override string ToString()
/// <returns>true if the objects are equal.</returns>
public override bool Equals(object obj)
{
IPEndPoint ep = obj as IPEndPoint;
if (ep == null)
if (obj is not IPEndPoint ep)
{
return false;
}

return ep._address.Equals(_address) && ep._port == _port;
}

/// <inheritdoc/>
public override int GetHashCode()
{
return _address.GetHashCode() ^ _port;
}

// For security, we need to be able to take an IPEndPoint and make a copy that's immutable and not derived.
internal IPEndPoint Snapshot()
{
Expand Down
64 changes: 58 additions & 6 deletions nanoFramework.System.Net/SocketAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class SocketAddress
internal const int IPv4AddressSize = 16;

[Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)]
internal byte[] m_Buffer;
internal readonly byte[] m_Buffer;

[Diagnostics.DebuggerBrowsable(Diagnostics.DebuggerBrowsableState.Never)]
internal long _address;
Expand All @@ -40,7 +40,7 @@ internal SocketAddress(byte[] address)
}

internal SocketAddress(IPAddress ipAddress)
:this(ipAddress.AddressFamily,
: this(ipAddress.AddressFamily,
(ipAddress.AddressFamily == AddressFamily.InterNetwork) ? IPv4AddressSize : IPv6AddressSize)

{
Expand Down Expand Up @@ -90,11 +90,11 @@ internal SocketAddress(IPAddress ipAddress)
/// </remarks>
public SocketAddress(AddressFamily family, int size)
{
// Debug.Assert(size > 2);
// Debug.Assert(size > 2);

m_Buffer = new byte[size]; //(size / IntPtr.Size + 2) * IntPtr.Size];//sizeof DWORD

m_Buffer[0] = unchecked((byte)((int)family ));
m_Buffer[0] = unchecked((byte)((int)family));
m_Buffer[1] = unchecked((byte)((int)family >> 8));
}

Expand Down Expand Up @@ -129,10 +129,62 @@ public byte this[int offset]
internal IPEndPoint GetIPEndPoint()
{
IPAddress address = GetIPAddress();
int port = (int)((m_Buffer[2] << 8 & 0xFF00) | (m_Buffer[3]));
int port = ((m_Buffer[2] << 8) & 0xFF00) | (m_Buffer[3]);
return new IPEndPoint(address, port);
}

/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj is not SocketAddress castedComparand || Size != castedComparand.Size)
{
return false;
}

for (int i = 0; i < Size; i++)
{
if (this[i] != castedComparand[i])
{
return false;
}
}

return true;
}

/// <inheritdoc/>
public override int GetHashCode()
{
int i;
int hash = 0;
int size = Size & ~3;

for (i = 0; i < size; i += 4)
{
hash ^= m_Buffer[i]
| (m_Buffer[i + 1] << 8)
| (m_Buffer[i + 2] << 16)
| (m_Buffer[i + 3] << 24);
}

if ((Size & 3) != 0)
{

int remnant = 0;
int shift = 0;

for (; i < Size; ++i)
{
remnant |= m_Buffer[i] << shift;
shift += 8;
}

hash ^= remnant;
}

return hash;
}

internal IPAddress GetIPAddress()
{
//if (Family == AddressFamily.InterNetworkV6)
Expand All @@ -153,7 +205,7 @@ internal IPAddress GetIPAddress()
//}
//else if (Family == AddressFamily.InterNetwork)
{
long address = (long)(
long address = (
(m_Buffer[4] & 0x000000FF) |
(m_Buffer[5] << 8 & 0x0000FF00) |
(m_Buffer[6] << 16 & 0x00FF0000) |
Expand Down