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
21 changes: 20 additions & 1 deletion Tests/IPAddressTests/IPAddressTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace NFUnitTestIPAddress
public class IPAddressTests
{
[Setup]
public void SetupConnectToEthernetTests()
public void Setup()
{
// Comment next line to run the tests on a real hardware
Assert.SkipTest("Skipping tests using nanoCLR Win32 in a pipeline");
Expand Down Expand Up @@ -301,5 +301,24 @@ public void NetTest6_SocketAddressBasic()
+ " as " + socketAddress2.ToString() + " " + socketAddress2.GetHashCode());
}
}

[TestMethod]
public void Equality_Tests()
{
var privateAddress = IPAddress.Parse("192.168.0.1");
var publicAddress = IPAddress.Parse("1.1.1.1");

// Equal
Assert.AreEqual(privateAddress, IPAddress.Parse("192.168.0.1"));
Assert.AreEqual(publicAddress, IPAddress.Parse("1.1.1.1"));
Assert.IsTrue(privateAddress == new IPAddress(new byte[] { 192, 168, 0, 1 }), "192.168.0.1 == 192.168.0.1");
Assert.IsTrue(publicAddress == new IPAddress(new byte[] { 1, 1, 1, 1 }), "1.1.1.1 == 1.1.1.1");

// Not Equal
Assert.AreNotEqual(privateAddress, IPAddress.Parse("1.1.1.1"));
Assert.AreNotEqual(publicAddress, IPAddress.Parse("192.168.0.1"));
Assert.IsTrue(privateAddress != new IPAddress(new byte[] { 192, 168, 0, 2 }), "192.168.0.1 == 192.168.0.2");
Assert.IsTrue(publicAddress != new IPAddress(new byte[] { 1, 1, 1, 2 }), "1.1.1.1 == 1.1.1.2");
}
}
}
3 changes: 3 additions & 0 deletions Tests/IPAddressTests/IPAddressTests.nfproj
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
<ItemGroup>
<ProjectReference Include="..\..\nanoFramework.System.Net\System.Net.nfproj" />
</ItemGroup>
<ItemGroup>
<Content Include="packages.lock.json" />
</ItemGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
<!-- MANUAL UPDATE HERE -->
<ProjectExtensions>
Expand Down
8 changes: 5 additions & 3 deletions Tests/IPAddressTests/nano.runsettings
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
<RunSettings>
<!-- Configurations that affect the Test Framework -->
<RunConfiguration>
<MaxCpuCount>1</MaxCpuCount>
<ResultsDirectory>.\TestResults</ResultsDirectory><!-- Path relative to solution directory -->
<TestSessionTimeout>120000</TestSessionTimeout><!-- Milliseconds -->
<TargetFrameworkVersion>net48</TargetFrameworkVersion>
<TargetPlatform>x64</TargetPlatform>
</RunConfiguration>
<nanoFrameworkAdapter>
<Logging>None</Logging>
<IsRealHardware>False</IsRealHardware>
<Logging>None</Logging> <!--Set to the desired level of logging for Unit Test execution. Possible values are: None, Detailed, Verbose, Error. -->
<IsRealHardware>False</IsRealHardware><!--Set to true to run tests on real hardware. -->
<RealHardwarePort>COM3</RealHardwarePort><!--Specify the COM port to use to connect to a nanoDevice. If none is specified, a device detection is performed and the 1st available one will be used. -->
<CLRVersion></CLRVersion><!--Specify the nanoCLR version to use. If not specified, the latest available will be used. -->
<PathToLocalCLRInstance></PathToLocalCLRInstance><!--Specify the path to a local nanoCLR instance. If not specified, the default one installed with nanoclr CLR witll be used. -->
</nanoFrameworkAdapter>
</RunSettings>
104 changes: 79 additions & 25 deletions nanoFramework.System.Net/IPAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,38 @@ 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.
/// </summary>
public static readonly IPAddress Any = new(0x0000000000000000);
/// <remarks>
/// The <see cref="Socket.Bind"/> method uses the <see cref="Any"/> field to indicate that a <see cref="Socket"/> instance must listen for client activity on all network interfaces.
///
/// The <see cref="Any"/> field is equivalent to 0.0.0.0 in dotted-quad notation.
/// </remarks>
public static readonly IPAddress Any = new(new byte[] { 0, 0, 0, 0 });

/// <summary>
/// Provides the IP loopback address. This field is read-only.
/// </summary>
public static readonly IPAddress Loopback = new(0x000000000100007F);
/// <remarks>
/// The <see cref="Loopback"/> field is equivalent to 127.0.0.1 in dotted-quad notation.
/// </remarks>
public static readonly IPAddress Loopback = new(new byte[] { 127, 0, 0, 1 });

/// <summary>
/// Provides the IP broadcast address. This field is read-only.
/// </summary>
/// <remarks>
/// The <see cref="Broadcast"/> field is equivalent to 255.255.255.255 in dotted-quad notation.
/// </remarks>
public static readonly IPAddress Broadcast = new(new byte[] { 255, 255, 255, 255 });

/// <summary>
/// Provides an IP address that indicates that no network interface should be used. This field is read-only.
/// </summary>
/// <remarks>
/// The <see cref="Socket.Bind"/> uses the <see cref="None"/> field to indicate that a <see cref="Socket"/> must not listen for client activity.
///
/// The <see cref="None"/> field is equivalent to 255.255.255.255 in dotted-quad notation.
/// </remarks>
public static readonly IPAddress None = Broadcast;

internal readonly long Address;

Expand Down Expand Up @@ -136,6 +162,22 @@ public IPAddress(byte[] address)
}
}

/// <summary>
/// Indicates whether two <see cref="IPAddress"/> objects are equal.
/// </summary>
/// <param name="a">The <see cref="IPAddress"/> to compare with <paramref name="b"/>.</param>
/// <param name="b">The <see cref="IPAddress"/> to compare with <paramref name="a"/>.</param>
/// <returns><see langword="true"/> if <paramref name="b"/> is equal to <paramref name="a"/>; otherwise, <see langword="false"/>.</returns>
public static bool operator ==(IPAddress a, IPAddress b) => a is not null && a.Equals(b);

/// <summary>
/// Indicates whether two <see cref="IPAddress"/> objects are not equal.
/// </summary>
/// <param name="a">The <see cref="IPAddress"/> to compare with <paramref name="b"/>.</param>
/// <param name="b">The <see cref="IPAddress"/> to compare with <paramref name="a"/>.</param>
/// <returns><see langword="true"/> if <paramref name="b"/> is not equal to <paramref name="a"/>; otherwise, <see langword="false"/>.</returns>
public static bool operator !=(IPAddress a, IPAddress b) => !(a == b);

/// <summary>
/// Initializes a new instance of a IPV6 <see cref="IPAddress"/> class with the address specified as a Byte array.
/// </summary>
Expand Down Expand Up @@ -173,45 +215,59 @@ private IPAddress(ushort[] address, uint scopeid)
/// <summary>
/// Compares two IP addresses.
/// </summary>
/// <param name="obj">An <see cref="IPAddress"/> instance to compare to the current instance.</param>
/// <returns></returns>
public override bool Equals(object obj)
/// <param name="other">An <see cref="IPAddress"/> instance to compare to the current instance.</param>
/// <returns><see langword="true"/> if the two addresses are equal; otherwise, <see langword="false"/>.</returns>
public override bool Equals(object other)
{
IPAddress addr = obj as IPAddress;
return other is IPAddress ipAddress && Equals(ipAddress);
}

if (obj == null) return false;
/// <summary>
/// Compares two IP addresses.
/// </summary>
/// <param name="other">An <see cref="IPAddress"/> instance to compare to the current instance.</param>
/// <returns><see langword="true"/> if the two addresses are equal; otherwise, <see langword="false"/>.</returns>
public bool Equals(IPAddress other)
{
if (other is null)
{
return false;
}

// Compare families before address representations
if (AddressFamily != other.AddressFamily)
{
return false;
}

// Compare family before address
if (_family != addr.AddressFamily)
if (_family != other.AddressFamily)
{
return false;
}

if (_family == AddressFamily.InterNetworkV6)
{
// For IPv6 addresses, compare the full 128bit address
for (int i = 0; i < NumberOfLabels; i++)
for (var i = 0; i < NumberOfLabels; i++)
{
if (addr._numbers[i] != this._numbers[i])
if (other._numbers[i] != _numbers[i])
return false;
}

// Also scope must match
if (addr._scopeid == this._scopeid)
return true;

return false;
return other._scopeid == _scopeid;
}
else
{
return this.Address == addr.Address;
return Address == other.Address;
}
}

/// <summary>
/// Provides a copy of the <see cref="IPAddress"/> as an array of bytes.
/// Provides a copy of the <see cref="IPAddress"/> as an array of bytes in network order.
/// </summary>
/// <returns>A Byte array.</returns>
/// <returns>A <see langword="byte"/> array.</returns>
public byte[] GetAddressBytes()
{
byte[] bytes;
Expand All @@ -223,8 +279,8 @@ public byte[] GetAddressBytes()
int j = 0;
for (int i = 0; i < NumberOfLabels; i++)
{
bytes[j++] = (byte)((this._numbers[i] >> 8) & 0xFF);
bytes[j++] = (byte)((this._numbers[i]) & 0xFF);
bytes[j++] = (byte)((_numbers[i] >> 8) & 0xFF);
bytes[j++] = (byte)((_numbers[i]) & 0xFF);
}
return bytes;
}
Expand Down Expand Up @@ -341,11 +397,9 @@ public override int GetHashCode()
{
return ToString().GetHashCode();
}
else
{
// For IPv4 addresses, we can simply use the integer representation.
return unchecked((int)Address);
}

// 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.
Expand Down Expand Up @@ -410,7 +464,7 @@ public IPAddress MapToIPv6()
return this;
}

ushort[] labels = new ushort[IPAddress.NumberOfLabels];
ushort[] labels = new ushort[NumberOfLabels];
labels[5] = 0xFFFF;
labels[6] = (ushort)(((Address & 0x0000FF00) >> 8) | ((Address & 0x000000FF) << 8));
labels[7] = (ushort)(((Address & 0xFF000000) >> 24) | ((Address & 0x00FF0000) >> 8));
Expand Down
2 changes: 1 addition & 1 deletion nanoFramework.System.Net/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

////////////////////////////////////////////////////////////////
// update this whenever the native assembly signature changes //
[assembly: AssemblyNativeVersion("100.2.0.0")]
[assembly: AssemblyNativeVersion("100.2.0.1")]
////////////////////////////////////////////////////////////////

// Setting ComVisible to false makes the types in this assembly not visible
Expand Down