Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plug System.Net #2812

Merged
merged 30 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
22e0880
✨ Implement plug for TcpClient, TcpListener and NetworkStream
valentinbreiz Nov 7, 2023
89ac855
✨ Implement plugs for TcpListener
valentinbreiz Nov 7, 2023
87a11ec
✨ Implement Stream plugs
valentinbreiz Nov 7, 2023
3a35ed9
🐛 Stream read plug does not work
valentinbreiz Nov 7, 2023
f33a693
🔥 Remove useless Stream plug + implement shutdown plug
valentinbreiz Nov 8, 2023
e4f3e64
✨ Implement Socket plugs + needed stuff
valentinbreiz Nov 8, 2023
0022a59
✨ Start work on Socket + TcpListener implementation
valentinbreiz Nov 8, 2023
313543f
✨ IPAdress plug base implemented
valentinbreiz Nov 9, 2023
382e348
✨ Implement TcpListener.AcceptTcpClient
valentinbreiz Nov 9, 2023
62117a4
✨ Implement TCP Socket Bind Listen Accept Close
valentinbreiz Nov 9, 2023
6f45939
🥅 Throw Socket errors if not TCP stream
valentinbreiz Nov 9, 2023
be9427e
✨ Implement Socket.Receive
valentinbreiz Nov 10, 2023
bce8f13
🐛 Fix NetworkStream dispose
valentinbreiz Nov 10, 2023
6179d92
✨ Implement Socket.Send
valentinbreiz Nov 10, 2023
9647bc9
Merge branch 'master' into feature/plugNet2
valentinbreiz Dec 3, 2023
48d8a98
🐛 Fix closing connections
valentinbreiz Dec 3, 2023
ff3ebd4
✨ Implement Socket.Send ack check
valentinbreiz Dec 4, 2023
ad9bd56
🐛 Fix build (multiple set_Client)
valentinbreiz Dec 4, 2023
fde10fb
Merge branch 'master' into feature/plugNet2
MishaProductions Dec 4, 2023
4fe4515
🐛 Fix stack corruption (wrong plug return type)
valentinbreiz Dec 4, 2023
6fc41c4
🔥 Remove useless debug logs
valentinbreiz Dec 4, 2023
069069f
✨ Begin TCPClient connect impl
valentinbreiz Dec 4, 2023
c6bb978
✨ TCPClient connect local port generation + fixes
valentinbreiz Dec 5, 2023
4465eb6
✨ TCPClient works!
valentinbreiz Dec 5, 2023
6e776ad
📝 Update TCP documentation
valentinbreiz Dec 5, 2023
d758ae7
Merge branch 'master' into feature/plugNet2
valentinbreiz Dec 5, 2023
f3fca0a
📝 Update Network.md
valentinbreiz Dec 5, 2023
c7b70e1
🔥 Clean up code
valentinbreiz Dec 5, 2023
51bb237
✅ Remove TCP test for now
valentinbreiz Dec 5, 2023
4b4e809
✅ Update TCP tests + Fix NetworkStream Write
valentinbreiz Dec 5, 2023
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
141 changes: 98 additions & 43 deletions Docs/articles/Kernel/Network.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ All protocols here don't necessary support every feature described by their RFC

Each protocol has a Client class which can be used to receive and send data. If a Receive() method is blocking, the method will timeout after 5 seconds or use the value optionally set by parameter. Please note that all finished connections should be closed using Close().

Cosmos Network Stack won't use Classes and Functions that are under .NET Core. Everything described here will be under:
The Cosmos Network Stack mainly not uses classes and functions that are under .NET Core (except TCP). Everything described here will be under:
```csharp
using Cosmos.System.Network;
```
Expand All @@ -28,30 +28,15 @@ using(var xClient = new DHCPClient())
}
```

## TCP
Like UDP, TCP has to create a client and call Connect() to specify the remote machine address before sending or receiving data.

Server :
### Get local IP address
```csharp
using(var xServer = new TcpListener(4242))
{
/** Start server **/
xServer.Start();

/** Accept incoming TCP connection **/
var client = xServer.AcceptTcpClient(); //blocking

/** Stop server **/
xServer.Stop();

/** Send data **/
client.Send(Encoding.ASCII.GetBytes(message));
}
Console.WriteLine(NetworkConfiguration.CurrentAddress.ToString());
```

Client :
## UDP
Before playing with packets, we have to create a client and call Connect() to specify the remote machine address. After that the client will be able to send or listen for data.
```csharp
using(var xClient = new TcpClient(4242))
using(var xClient = new UdpClient(4242))
{
xClient.Connect(new Address(192, 168, 1, 70), 4242);

Expand All @@ -65,6 +50,98 @@ using(var xClient = new TcpClient(4242))
}
```

## TCP
Unlike UDP, TCP is plugged with the dotnet framework. You won't have to use Cosmos.System.Network but System.Net.Sockets and System.Net. You can setup TCP network streams using TcpListener, TcpClient and NetworkStream, don't use the Stream class unless you know what you do.

Server:
```csharp
using System.Text;
using System.Net.Sockets;
using System.Net;

class TcpServer
{
private TcpListener tcpListener;
private int port;

public TcpServer(int port)
{
this.port = port;
var address = IPAddress.Any;
this.tcpListener = new TcpListener(address, port);
}

public void Start()
{
this.tcpListener.Start();

while (true)
{
/** Wait for new connections **/
TcpClient client = this.tcpListener.AcceptTcpClient();
HandleClientComm(client);
client.Close();
}
}

private void HandleClientComm(TcpClient client)
{
NetworkStream stream = client.GetStream();

byte[] buffer = new byte[client.ReceiveBufferSize];
int bytesRead;

while (true)
{
bytesRead = 0;

/** Receive data **/
bytesRead = stream.Read(buffer, 0, buffer.Length); // Blocks until a client sends a message

if (bytesRead == 0) // The client has disconnected from the server
{
break;
}

string received = Encoding.ASCII.GetString(buffer, 0, bytesRead);

/** Send data **/
byte[] response = Encoding.ASCII.GetBytes("ok");
stream.Write(response, 0, response.Length);

// stream.Flush(); useless for now
}
stream.Close();
}
}
```

Client :
```csharp
string serverIp = "192.168.1.63";
int serverPort = 1312;

using(TcpClient client = new TcpClient())
{
/**Connect to server **/
client.Connect(serverIp, serverPort);
NetworkStream stream = client.GetStream();

/** Send data **/
string messageToSend = "Hello from CosmosOS!";
byte[] dataToSend = Encoding.ASCII.GetBytes(messageToSend);
stream.Write(dataToSend, 0, dataToSend.Length);

/** Receive data **/
byte[] receivedData = new byte[client.ReceiveBufferSize];
int bytesRead = stream.Read(receivedData, 0, receivedData.Length);
string receivedMessage = Encoding.ASCII.GetString(receivedData, 0, bytesRead);

/** Close data stream **/
stream.Close();
}
```

## FTP
Only server side is implemented in Cosmos. We recommand to use FileZilla as your FTP client.

Expand Down Expand Up @@ -96,23 +173,6 @@ using(var xServer = new FtpServer(fs, "0:\\"))
}
```

## UDP
Before playing with packets, we have to create a client and call Connect() to specify the remote machine address. After that the client will be able to send or listen for data.
```csharp
using(var xClient = new UdpClient(4242))
{
xClient.Connect(new Address(192, 168, 1, 70), 4242);

/** Send data **/
xClient.Send(Encoding.ASCII.GetBytes(message));

/** Receive data **/
var endpoint = new EndPoint(Address.Zero, 0);
var data = xClient.Receive(ref endpoint); //set endpoint to remote machine IP:port
var data2 = xClient.NonBlockingReceive(ref endpoint); //retrieve receive buffer without waiting
}
```

## ICMP
For ICMP, we will only be able to send an ICMP echo to a distant machine and wait for its response. If another machine sends us an ICMP echo, Cosmos will automatically handle the request and reply.
```csharp
Expand Down Expand Up @@ -141,9 +201,4 @@ using(var xClient = new DnsClient())
/** Receive DNS Response **/
Address destination = xClient.Receive(); //can set a timeout value
}

```
## Get local IP address
```csharp
Console.WriteLine(NetworkConfiguration.CurrentAddress.ToString());
```
66 changes: 41 additions & 25 deletions Tests/Kernels/NetworkTest/Kernel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Sys = Cosmos.System;

Expand Down Expand Up @@ -156,39 +158,53 @@ private void TestTcpConnection()

using (var xClient = new TcpClient())
{
Assert.IsTrue(xClient.IsClosed(), "TCP connexion created.");

xClient.Connect(new Address(127, 0, 0, 1), 12345);
Assert.IsTrue(xClient.IsConnected(), "TCP connexion established.");

var endpoint = new EndPoint(Address.Zero, 0);
var data = xClient.Receive(ref endpoint);
Assert.AreEqual(Encoding.ASCII.GetString(data), "Hello from the testrunner!", "TCP receive works");

xClient.Send(Encoding.ASCII.GetBytes(NetworkConfiguration.CurrentAddress.ToString()));

xClient.Send(Encoding.ASCII.GetBytes("cosmos is the best operating system uwu"));
var data2 = xClient.Receive(ref endpoint);
Assert.AreEqual(Encoding.ASCII.GetString(data2), "COSMOS IS THE BEST OPERATING SYSTEM UWU", "TCP send works");
Global.debugger.Send("Creating IPAddress...");
var address = new IPAddress(new byte[] { 127, 0, 0, 1 });
Global.debugger.Send("Connecting to TCP server...");
xClient.Connect(address, 12345);
Global.debugger.Send("TcpClient connected.");
NetworkStream stream = xClient.GetStream();
Assert.IsTrue(xClient.Connected, "TCP connexion established.");

byte[] receivedData = new byte[xClient.ReceiveBufferSize];
int bytesRead = stream.Read(receivedData, 0, receivedData.Length);
string receivedMessage = Encoding.ASCII.GetString(receivedData, 0, bytesRead);
Assert.AreEqual(receivedMessage, "Hello from the testrunner!", "TCP receive works");

Global.debugger.Send("TcpClient sending IP " + NetworkConfiguration.CurrentAddress.ToString());
stream.Write(Encoding.ASCII.GetBytes(NetworkConfiguration.CurrentAddress.ToString()));
Global.debugger.Send("TcpClient IP sent");

// Envoyer un message au serveur
string messageToSend = "cosmos is the best operating system uwu";
byte[] dataToSend = Encoding.ASCII.GetBytes(messageToSend);
Global.debugger.Send("Sending: " + messageToSend);
stream.Write(dataToSend, 0, dataToSend.Length);

byte[] receivedData2 = new byte[xClient.ReceiveBufferSize];
int bytesRead2 = stream.Read(receivedData2, 0, receivedData2.Length);
string receivedMessage2 = Encoding.ASCII.GetString(receivedData2, 0, bytesRead2);
Assert.AreEqual(receivedMessage2, "COSMOS IS THE BEST OPERATING SYSTEM UWU", "TCP send works");

string baseMessage = "This is a long TCP message for sequencing test...";
string paddedMessage = baseMessage.PadRight(6000, '.');
xClient.Send(Encoding.ASCII.GetBytes(paddedMessage));
stream.Write(Encoding.ASCII.GetBytes(paddedMessage));
Global.debugger.Send("Sent long data packet.");

var data3 = xClient.Receive(ref endpoint);
Assert.AreEqual(data3.Length, 6000, "TCP paquet sequencing works.");
byte[] receivedData3 = new byte[xClient.ReceiveBufferSize];
int bytesRead3 = stream.Read(receivedData3, 0, receivedData3.Length);
Assert.AreEqual(bytesRead3, 6000, "TCP paquet sequencing works.");

stream.Close();
}

Global.debugger.Send("Creating TCP server...");

using (var xServer = new TcpListener(4343))
{
xServer.Start();
Assert.IsTrue(xServer.IsListening(), "TCP server is listening.");
var xServer = new TcpListener(IPAddress.Any, 4343);
xServer.Start();

var client = xServer.AcceptTcpClient(); //blocking
Assert.IsTrue(xServer.IsConnected(), "Received new client! TCP connexion established.");
}
var client = xServer.AcceptTcpClient(); //blocking
Assert.IsTrue(client.Connected, "Received new client! TCP connexion established.");
}

private void TestDnsConnection()
Expand Down Expand Up @@ -222,7 +238,7 @@ private void TestIcmpConnection()

xClient.SendEcho();

var endpoint = new EndPoint(Address.Zero, 0);
var endpoint = new Sys.Network.IPv4.EndPoint(Address.Zero, 0);
int time = xClient.Receive(ref endpoint);

Assert.IsFalse(time == -1, "ICMP echo works");
Expand Down
6 changes: 6 additions & 0 deletions source/Cosmos.Core_Plugs/Interop/Advapi32Impl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,11 @@ public static int RegEnumKeyEx(object aSafeRegistryHandle, int aInt, char[] aCha
{
throw new NotImplementedException();
}

[PlugMethod(Signature = "System_Int32__Interop_Advapi32_EventSetInformation_System_Int64__Interop_Advapi32_EVENT_INFO_CLASS__System_Void___System_UInt32_")]
public static unsafe int EventSetInformation(long registrationHandle, object informationClass, void* eventInformation, uint informationLength)
{
throw new NotImplementedException();
}
}
}
12 changes: 12 additions & 0 deletions source/Cosmos.Core_Plugs/Interop/Kernel32Impl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,17 @@ public static unsafe int WriteFile(global::System.Runtime.InteropServices.SafeHa
{
throw new NotImplementedException();
}

[PlugMethod(Signature = "System_Int32__Interop_Kernel32_ReadFile_System_Runtime_InteropServices_SafeHandle__System_Byte___System_Int32___System_Int32__System_Threading_NativeOverlapped__")]
public static unsafe int ReadFile(global::System.Runtime.InteropServices.SafeHandle aSafeHandle, byte* aBytePtr, int aInt, ref int aRefInt, global::System.Threading.NativeOverlapped* aNativeOverlappedPtr)
{
throw new NotImplementedException();
}

[PlugMethod(Signature = "System_Void__Interop_Kernel32_GetSystemInfo__Interop_Kernel32_SYSTEM_INFO_")]
public static unsafe void GetSystemInfo(object lpSystemInfo)
{
throw new NotImplementedException();
}
}
}
30 changes: 30 additions & 0 deletions source/Cosmos.Core_Plugs/Interop/WinsockImpl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using IL2CPU.API.Attribs;
using System;
using System.Net.Sockets;

namespace Cosmos.Core_Plugs.Interop
{
[Plug("Interop+Winsock, System.Net.Sockets", IsOptional = true)]
public static unsafe class WinsockImpl
{
public static SocketError shutdown(SafeSocketHandle socketHandle, int how)
{
throw new NotImplementedException();
}

public static int recv(SafeSocketHandle socketHandle, byte* pinnedBuffer, int len, SocketFlags socketFlags)
{
throw new NotImplementedException();
}

public static int send(SafeSocketHandle socketHandle, byte* pinnedBuffer, int len, SocketFlags socketFlags)
{
throw new NotImplementedException();
}

public static int bind(SafeSocketHandle socketHandle, byte[] socketAddress, int socketAddressSize)
{
throw new NotImplementedException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IL2CPU.API.Attribs;

namespace Cosmos.Core_Plugs.Microsoft
{
[Plug("Microsoft.Win32.SafeHandles.SafeFileHandle+OverlappedValueTaskSource, System.Private.CoreLib", IsOptional = true)]
public static class OverlappedValueTaskSourceImpl
{
[PlugMethod(Signature = "System_Void__Microsoft_Win32_SafeHandles_SafeFileHandle_OverlappedValueTaskSource__cctor__")]
public static void Cctor()
{
throw new NotImplementedException();
}
}
}
20 changes: 20 additions & 0 deletions source/Cosmos.Core_Plugs/System/Threading/OverlappedImpl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using IL2CPU.API.Attribs;

namespace Cosmos.Core_Plugs.System.Threading
{
[Plug(TargetName = "System.Threading.Overlapped, System.Private.CoreLib")]
class OverlappedImpl
{
[PlugMethod(Signature = "System_Void__System_Threading_Overlapped_Free_System_Threading_NativeOverlapped__")]
public unsafe static void Free(NativeOverlapped* a)
{
throw new NotImplementedException();
}
}
}
Loading