Skip to content

Commit

Permalink
Merge branch 'master' into dotnet8
Browse files Browse the repository at this point in the history
  • Loading branch information
zarlo authored Dec 7, 2023
2 parents 36bfae1 + b66602e commit 2586128
Show file tree
Hide file tree
Showing 22 changed files with 1,045 additions and 492 deletions.
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

0 comments on commit 2586128

Please sign in to comment.