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
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,57 @@
|:-|---|---|
| System.Net | [![Build Status](https://dev.azure.com/nanoframework/System.Net/_apis/build/status/System.Net?repoName=nanoframework%2FSystem.Net&branchName=main)](https://dev.azure.com/nanoframework/System.Net/_build/latest?definitionId=20&repoName=nanoframework%2FSystem.Net&branchName=main) | [![NuGet](https://img.shields.io/nuget/v/nanoFramework.System.Net.svg?label=NuGet&style=flat&logo=nuget)](https://www.nuget.org/packages/nanoFramework.System.Net/) |

## NetworkHelper usage

`NetworkHelper` provides two patterns for establishing a network connection: a blocking token-based approach for simple use-cases, and an event-based approach for background connection management.

### Token-based (retryable)

Call `SetupAndConnectNetwork` with a `CancellationToken` timeout. This method can be called repeatedly — if the first attempt times out, call it again:

```csharp
bool connected = false;
while (!connected)
{
CancellationTokenSource cs = new(30000);
connected = NetworkHelper.SetupAndConnectNetwork(requiresDateTime: true, token: cs.Token);
if (!connected)
{
Debug.WriteLine($"Network not ready, status: {NetworkHelper.Status}");
// wait before retrying
Thread.Sleep(5000);
}
}
```

### Event-based

Call `SetupNetworkHelper` once at startup. The helper connects in the background. Wait on `NetworkReady`:

```csharp
NetworkHelper.SetupNetworkHelper(requiresDateTime: true);

if (!NetworkHelper.NetworkReady.WaitOne(30000, true))
{
Debug.WriteLine($"Failed to connect: {NetworkHelper.Status}");
}
```

> **Note:** `NetworkReady` is reset when the connection is lost and re-signaled when it is restored, accurately reflecting live network state. Code that previously assumed `NetworkReady` would remain set after first connect should be updated to handle transient disconnects.

### Reset and reconfigure

Call `Reset()` to fully reset the helper so it can be called again with different settings, or to restart after an error:

```csharp
NetworkHelper.Reset();

// Now call SetupNetworkHelper or SetupAndConnectNetwork again
NetworkHelper.SetupNetworkHelper(requiresDateTime: true);
```

`SetupNetworkHelper` throws `InvalidOperationException` if called a second time without a prior `Reset()`. Token-based methods (`SetupAndConnectNetwork`) do not have this restriction and are always retryable.

## Feedback and documentation

For documentation, providing feedback, issues and finding out how to contribute please refer to the [Home repo](https://github.com/nanoframework/Home).
Expand Down
102 changes: 51 additions & 51 deletions Tests/IPAddressTests/IPAddressTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ public void NetTest1_DNS()
{
IPHostEntry ipHostEntry = Dns.GetHostEntry("192.168.1.1");

Assert.Equal(ipHostEntry.AddressList.Length, 1, "GetHostEntry returned wrong number of addresses");
Assert.AreEqual(1, ipHostEntry.AddressList.Length, "GetHostEntry returned wrong number of addresses");
IPAddress address = ipHostEntry.AddressList[0];

Assert.NotNull(address, "Address is null");
Assert.Equal(address.ToString(), "192.168.1.1", "Address is incorrect");
Assert.IsNotNull(address, "Address is null");
Assert.AreEqual("192.168.1.1", address.ToString(), "Address is incorrect");
}

[TestMethod]
Expand All @@ -54,25 +54,25 @@ public void NetTest2_IPAddressBasic()
+ IPInts[1] * 256
+ IPInts[2] * 256 * 256
+ IPInts[3] * 256 * 256 * 256);
Assert.NotNull(address, "Address is null");
Assert.IsNotNull(address, "Address is null");

Type typeOfAddress = address.GetType();
Assert.IsType(typeOfAddress, Type.GetType("System.Net.IPAddress"), "Type is incorrect");
Assert.IsInstanceOfType(address, Type.GetType("System.Net.IPAddress"), "Type is incorrect");

byte[] targetBytes = { (byte)IPInts[0], (byte)IPInts[1], (byte)IPInts[2], (byte)IPInts[3] };
byte[] addressBytes = address.GetAddressBytes();
Assert.Equal(addressBytes.Length, 4, "GetAddressBytes returns wrong size");
Assert.AreEqual(4, addressBytes.Length, "GetAddressBytes returns wrong size");

for (int j = 0; j < 4; j++)
{
Assert.Equal(addressBytes[j], targetBytes[j], "GetAddressBytes returns wrong bytes");
Assert.AreEqual(targetBytes[j], addressBytes[j], "GetAddressBytes returns wrong bytes");
}

IPAddress addressFromByteArray = new(targetBytes);
addressBytes = addressFromByteArray.GetAddressBytes();
for (int j = 0; j < 4; j++)
{
Assert.Equal(addressBytes[j], targetBytes[j], "Address from byte array returns wrong bytes");
Assert.AreEqual(targetBytes[j], addressBytes[j], "Address from byte array returns wrong bytes");
}

IPAddress address2 = new(
Expand All @@ -81,17 +81,17 @@ public void NetTest2_IPAddressBasic()
+ IPInts[2] * 256 * 256
+ IPInts[3] * 256 * 256 * 256);

Assert.Equal(address.ToString(), address2.ToString(), "ToString returns differently for same data");
Assert.AreEqual(address.ToString(), address2.ToString(), "ToString returns differently for same data");

Assert.Equal(address.GetHashCode(), address2.GetHashCode(), "GetHasCode returns differently for same data");
Assert.AreEqual(address.GetHashCode(), address2.GetHashCode(), "GetHasCode returns differently for same data");

address2 = new IPAddress(
(IPInts[0] % 2 + 1)
+ (IPInts[1] % 2 + 1) * 256
+ (IPInts[2] % 2 + 1) * 256 * 256
+ (IPInts[3] % 2 + 1) * 256 * 256 * 256);

Assert.NotEqual(address.GetHashCode(), address2.GetHashCode(), "GetHasCode returns same for " + address.ToString()
Assert.AreNotEqual(address.GetHashCode(), address2.GetHashCode(), "GetHasCode returns same for " + address.ToString()
+ " as " + address2.ToString());
}
}
Expand All @@ -100,20 +100,20 @@ public void NetTest2_IPAddressBasic()
public void NetTest3_IPAddressLoopback()
{
IPAddress address = IPAddress.Loopback;
Assert.NotNull(address, "Address is null");
Assert.IsNotNull(address, "Address is null");

Assert.Equal(address.ToString(), "127.0.0.1", "Address is incorrect");
Assert.AreEqual("127.0.0.1", address.ToString(), "Address is incorrect");

Type typeOfAddress = address.GetType();
Assert.IsType(typeOfAddress, Type.GetType("System.Net.IPAddress"), "Type is incorrect");
Assert.IsInstanceOfType(address, Type.GetType("System.Net.IPAddress"), "Type is incorrect");

byte[] localhostBytes = { 127, 0, 0, 1 };
byte[] addressBytes = address.GetAddressBytes();
Assert.Equal(addressBytes.Length, 4, "GetAddressBytes returns wrong size");
Assert.AreEqual(4, addressBytes.Length, "GetAddressBytes returns wrong size");

for (int i = 0; i < 4; i++)
{
Assert.Equal(addressBytes[i], localhostBytes[i], "GetAddressBytes returns wrong bytes");
Assert.AreEqual(localhostBytes[i], addressBytes[i], "GetAddressBytes returns wrong bytes");
}
}

Expand All @@ -123,20 +123,20 @@ public void NetTest4_IPAddressAny()
{
IPAddress address = IPAddress.Any;

Assert.NotNull(address, "Address is null");
Assert.IsNotNull(address, "Address is null");

Assert.Equal(address.ToString(), "0.0.0.0", "Address is incorrect");
Assert.AreEqual("0.0.0.0", address.ToString(), "Address is incorrect");

Type typeOfAddress = address.GetType();
Assert.IsType(typeOfAddress, Type.GetType("System.Net.IPAddress"), "Type is incorrect");
Assert.IsInstanceOfType(address, Type.GetType("System.Net.IPAddress"), "Type is incorrect");

byte[] localhostBytes = { 0, 0, 0, 0 };
byte[] addressBytes = address.GetAddressBytes();
Assert.Equal(addressBytes.Length, 4, "GetAddressBytes returns wrong size");
Assert.AreEqual(4, addressBytes.Length, "GetAddressBytes returns wrong size");

for (int i = 0; i < 4; i++)
{
Assert.Equal(addressBytes[i], localhostBytes[i], "GetAddressBytes returns wrong bytes");
Assert.AreEqual(localhostBytes[i], addressBytes[i], "GetAddressBytes returns wrong bytes");
}
}

Expand Down Expand Up @@ -171,47 +171,47 @@ public void NetTest5_IPEndPointBasic()
Debug.WriteLine("EndPoint2 created with long and int");
IPEndPoint endPoint2 = new(addressLong, portInt);

Assert.NotNull(endPoint1, "EndPoint1 is null");
Assert.NotNull(endPoint2, "EndPoint2 is null");
Assert.IsNotNull(endPoint1, "EndPoint1 is null");
Assert.IsNotNull(endPoint2, "EndPoint2 is null");

Type typeOfEndPoint = endPoint1.GetType();
Assert.IsType(typeOfEndPoint, Type.GetType("System.Net.IPEndPoint"), "EndPoint1 Type is incorrect");
Assert.IsInstanceOfType(endPoint1, Type.GetType("System.Net.IPEndPoint"), "EndPoint1 Type is incorrect");

typeOfEndPoint = endPoint2.GetType();
Assert.IsType(typeOfEndPoint, Type.GetType("System.Net.IPEndPoint"), "EndPoint2 Type is incorrect");
Assert.IsInstanceOfType(endPoint2, Type.GetType("System.Net.IPEndPoint"), "EndPoint2 Type is incorrect");

Assert.Equal(endPoint1.ToString(), endPoint2.ToString(), "ToString returns differently for same data");
Assert.AreEqual(endPoint1.ToString(), endPoint2.ToString(), "ToString returns differently for same data");

Assert.True(endPoint1.Equals(endPoint2), "Equals returns false for same data");
Assert.IsTrue(endPoint1.Equals(endPoint2), "Equals returns false for same data");

int hashCode1 = endPoint1.GetHashCode();
int hashCode2 = endPoint2.GetHashCode();

Assert.Equal(hashCode1, hashCode2, "GetHasCode returns differently for same data");
Assert.AreEqual(hashCode1, hashCode2, "GetHasCode returns differently for same data");

Assert.False(endPoint1.Address.ToString() != endPoint2.Address.ToString()
Assert.IsFalse(endPoint1.Address.ToString() != endPoint2.Address.ToString()
|| endPoint1.Address.ToString() != address.ToString()
|| endPoint2.Address.ToString() != address.ToString(), "Address returns wrong data");

Assert.False(endPoint1.Port != endPoint2.Port
Assert.IsFalse(endPoint1.Port != endPoint2.Port
|| endPoint1.Port != portInt
|| endPoint2.Port != portInt, "Port returns wrong data");

Debug.WriteLine("Cloning Enpoint1 into EndPoint2");
endPoint2 = (IPEndPoint)endPoint2.Create(endPoint1.Serialize());

typeOfEndPoint = endPoint2.GetType();
Assert.IsType(typeOfEndPoint, Type.GetType("System.Net.IPEndPoint"), "EndPoint2 Type is incorrect after clone");
Assert.IsInstanceOfType(endPoint2, Type.GetType("System.Net.IPEndPoint"), "EndPoint2 Type is incorrect after clone");

Assert.Equal(endPoint1.ToString(), endPoint2.ToString(), "ToString returns differently for cloned data");
Assert.AreEqual(endPoint1.ToString(), endPoint2.ToString(), "ToString returns differently for cloned data");

Assert.Equal(endPoint1.GetHashCode(), endPoint2.GetHashCode(), "GetHashCode returns differently for cloned data");
Assert.AreEqual(endPoint1.GetHashCode(), endPoint2.GetHashCode(), "GetHashCode returns differently for cloned data");

Assert.False(endPoint1.Address.ToString() != endPoint2.Address.ToString()
Assert.IsFalse(endPoint1.Address.ToString() != endPoint2.Address.ToString()
|| endPoint1.Address.ToString() != address.ToString()
|| endPoint2.Address.ToString() != address.ToString(), "Address returns wrong data after clone");

Assert.False(endPoint1.Port != endPoint2.Port
Assert.IsFalse(endPoint1.Port != endPoint2.Port
|| endPoint1.Port != portInt
|| endPoint2.Port != portInt, "Port returns wrong data after clone");

Expand All @@ -225,14 +225,14 @@ public void NetTest5_IPEndPointBasic()
+ (IPInts[3] % 2 + 1) * 256 * 256 * 256;
endPoint2 = new IPEndPoint(addressLong2, portInt2);

Assert.NotEqual(endPoint1.GetHashCode(), endPoint2.GetHashCode(), "GetHashCode returns same for "
Assert.AreNotEqual(endPoint1.GetHashCode(), endPoint2.GetHashCode(), "GetHashCode returns same for "
+ endPoint1.ToString()
+ " as " + endPoint2.ToString());

Assert.False(endPoint1.Address == endPoint2.Address
Assert.IsFalse(endPoint1.Address == endPoint2.Address
|| endPoint2.Address == address, "Address returns wrong data after change");

Assert.False(endPoint1.Port == endPoint2.Port
Assert.IsFalse(endPoint1.Port == endPoint2.Port
|| endPoint2.Port == portInt, "Port returns wrong data after change");
}
}
Expand All @@ -241,13 +241,13 @@ public void NetTest5_IPEndPointBasic()
public void NetTest5_IPHostEntryBasic()
{
IPHostEntry ipHostEntry = Dns.GetHostEntry("192.168.1.1");
Assert.NotNull(ipHostEntry, "IPHostEntry is null");
Assert.IsNotNull(ipHostEntry, "IPHostEntry is null");

Type typeOfIPHostEntry = ipHostEntry.GetType();
Assert.IsType(typeOfIPHostEntry, Type.GetType("System.Net.IPHostEntry"), "IPHostEntry Type is incorrect");
Assert.IsInstanceOfType(ipHostEntry, Type.GetType("System.Net.IPHostEntry"), "IPHostEntry Type is incorrect");

Assert.Equal(ipHostEntry.AddressList[0].ToString(), "192.168.1.1", "AddressList[0] is incorrect");
Assert.Throws(typeof(IndexOutOfRangeException), () => { ipHostEntry.AddressList[1].ToString(); });
Assert.AreEqual("192.168.1.1", ipHostEntry.AddressList[0].ToString(), "AddressList[0] is incorrect");
Assert.ThrowsException(typeof(IndexOutOfRangeException), () => { ipHostEntry.AddressList[1].ToString(); });
}

[TestMethod]
Expand Down Expand Up @@ -278,25 +278,25 @@ public void NetTest6_SocketAddressBasic()
SocketAddress socketAddress1 = ipEndpoint1.Serialize();
SocketAddress socketAddress2 = ipEndpoint1.Serialize();

Assert.NotNull(socketAddress1, "socketAddress1 is null");
Assert.NotNull(socketAddress2, "socketAddress2 is null");
Assert.IsNotNull(socketAddress1, "socketAddress1 is null");
Assert.IsNotNull(socketAddress2, "socketAddress2 is null");

Type typeOfSocketAddress = socketAddress1.GetType();
Assert.IsType(typeOfSocketAddress, Type.GetType("System.Net.SocketAddress"), "socketAddress1 Type is incorrect");
Assert.IsInstanceOfType(socketAddress1, Type.GetType("System.Net.SocketAddress"), "socketAddress1 Type is incorrect");

typeOfSocketAddress = socketAddress2.GetType();
Assert.IsType(typeOfSocketAddress, Type.GetType("System.Net.SocketAddress"), "socketAddress2 Type is incorrect");
Assert.IsInstanceOfType(socketAddress2, Type.GetType("System.Net.SocketAddress"), "socketAddress2 Type is incorrect");

Assert.Equal(socketAddress1.ToString(), socketAddress2.ToString(), "ToString returns differently for same data");
Assert.AreEqual(socketAddress1.ToString(), socketAddress2.ToString(), "ToString returns differently for same data");

Assert.Equal(socketAddress1.GetHashCode(), socketAddress2.GetHashCode(), $"GetHashCode returns differently for same data");
Assert.True(socketAddress1.Family == AddressFamily.InterNetwork, "socketAddress1 Family is incorrect");
Assert.True(socketAddress2.Family == AddressFamily.InterNetwork, "socketAddress2 Family is incorrect");
Assert.AreEqual(socketAddress1.GetHashCode(), socketAddress2.GetHashCode(), $"GetHashCode returns differently for same data");
Assert.IsTrue(socketAddress1.Family == AddressFamily.InterNetwork, "socketAddress1 Family is incorrect");
Assert.IsTrue(socketAddress2.Family == AddressFamily.InterNetwork, "socketAddress2 Family is incorrect");

// Recreate a different Socket
socketAddress2 = new SocketAddress(AddressFamily.Chaos, 8);

Assert.NotEqual(socketAddress1.GetHashCode(), socketAddress2.GetHashCode(), "GetHashCode returns same for "
Assert.AreNotEqual(socketAddress1.GetHashCode(), socketAddress2.GetHashCode(), "GetHashCode returns same for "
+ socketAddress1.ToString() + " " + socketAddress1.GetHashCode()
+ " as " + socketAddress2.ToString() + " " + socketAddress2.GetHashCode());
}
Expand Down
Loading