From 21561e4c65765a6a6b5a05c4c20d37da8c000c3f Mon Sep 17 00:00:00 2001 From: Quajak Date: Mon, 11 May 2020 00:02:34 +0200 Subject: [PATCH 001/314] Added test for ldind_ref --- .../Cosmos.Compiler.Tests.Bcl.System/System/ArrayTests.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Tests/Kernels/Cosmos.Compiler.Tests.Bcl.System/System/ArrayTests.cs b/Tests/Kernels/Cosmos.Compiler.Tests.Bcl.System/System/ArrayTests.cs index e78691211c..667353fb12 100644 --- a/Tests/Kernels/Cosmos.Compiler.Tests.Bcl.System/System/ArrayTests.cs +++ b/Tests/Kernels/Cosmos.Compiler.Tests.Bcl.System/System/ArrayTests.cs @@ -79,7 +79,10 @@ public static void Execute() error = true; } Assert.IsTrue(error && y == 2, "Index out of range exception works correctly for too small positions."); - + + string[] stringArray = new string[10]; + stringArray[0] += "asd"; + Assert.AreEqual(stringArray[0], "asd", "Adding directly to array works"); } } } From 18d57dac54da899568ba99ae18dc009d958da5e2 Mon Sep 17 00:00:00 2001 From: Quajak Date: Wed, 4 Nov 2020 18:56:19 +0100 Subject: [PATCH 002/314] Added test for loading and storing three byte structs --- .../Kernel.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Tests/Kernels/Cosmos.Compiler.Tests.TypeSystem/Kernel.cs b/Tests/Kernels/Cosmos.Compiler.Tests.TypeSystem/Kernel.cs index 9a984165fc..6dbc4bb10b 100644 --- a/Tests/Kernels/Cosmos.Compiler.Tests.TypeSystem/Kernel.cs +++ b/Tests/Kernels/Cosmos.Compiler.Tests.TypeSystem/Kernel.cs @@ -38,6 +38,13 @@ protected override void Run() Assert.IsTrue(xEnumerable is IEnumerable, "isinst isn't working for interfaces on generic reference types!"); Assert.IsTrue(xEnumerable is IList, "isinst isn't working for generic interfaces on generic reference types!"); + ThreeBytes[] array = new ThreeBytes[1]; + array[0] = new ThreeBytes(17, 254, 77); + Assert.AreEqual(array[0].A, 17, "Three byte struct in array first value read correctly"); + Assert.AreEqual(array[0].B, 254, "Three byte struct in array second value read correctly"); + var local = array[0]; + Assert.AreEqual(local.C, 77, "Three byte struct third value read correctly"); + TestController.Completed(); } catch (Exception e) @@ -52,4 +59,18 @@ protected override void Run() } } } + + public struct ThreeBytes + { + public byte A; + public byte B; + public byte C; + + public ThreeBytes(byte a, byte b, byte c) + { + A = a; + B = b; + C = c; + } + } } From e8de30821a0e5e816f87ec4c2909859950711ff0 Mon Sep 17 00:00:00 2001 From: Quajak Date: Wed, 4 Nov 2020 21:23:47 +0100 Subject: [PATCH 003/314] Moved test --- .../Kernel.cs | 21 --------------- .../SimpleStructsAndArraysTest/Kernel.cs | 26 ++++++++++++++++++- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/Tests/Kernels/Cosmos.Compiler.Tests.TypeSystem/Kernel.cs b/Tests/Kernels/Cosmos.Compiler.Tests.TypeSystem/Kernel.cs index 6dbc4bb10b..9a984165fc 100644 --- a/Tests/Kernels/Cosmos.Compiler.Tests.TypeSystem/Kernel.cs +++ b/Tests/Kernels/Cosmos.Compiler.Tests.TypeSystem/Kernel.cs @@ -38,13 +38,6 @@ protected override void Run() Assert.IsTrue(xEnumerable is IEnumerable, "isinst isn't working for interfaces on generic reference types!"); Assert.IsTrue(xEnumerable is IList, "isinst isn't working for generic interfaces on generic reference types!"); - ThreeBytes[] array = new ThreeBytes[1]; - array[0] = new ThreeBytes(17, 254, 77); - Assert.AreEqual(array[0].A, 17, "Three byte struct in array first value read correctly"); - Assert.AreEqual(array[0].B, 254, "Three byte struct in array second value read correctly"); - var local = array[0]; - Assert.AreEqual(local.C, 77, "Three byte struct third value read correctly"); - TestController.Completed(); } catch (Exception e) @@ -59,18 +52,4 @@ protected override void Run() } } } - - public struct ThreeBytes - { - public byte A; - public byte B; - public byte C; - - public ThreeBytes(byte a, byte b, byte c) - { - A = a; - B = b; - C = c; - } - } } diff --git a/Tests/Kernels/SimpleStructsAndArraysTest/Kernel.cs b/Tests/Kernels/SimpleStructsAndArraysTest/Kernel.cs index b6bb505e62..77c6a8bde1 100644 --- a/Tests/Kernels/SimpleStructsAndArraysTest/Kernel.cs +++ b/Tests/Kernels/SimpleStructsAndArraysTest/Kernel.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; - using Cosmos.TestRunner; using Sys = Cosmos.System; @@ -82,6 +81,20 @@ private static void TestStep1() Assert.IsTrue(xItem2.E == 5, "xItem2.E == 5"); } + public struct ThreeBytes + { + public byte A; + public byte B; + public byte C; + + public ThreeBytes(byte a, byte b, byte c) + { + A = a; + B = b; + C = c; + } + } + private class KVPClass { public int Key; @@ -254,6 +267,16 @@ protected static void TestStandardList() // Assert.IsTrue(xTestMultidimensionalArray[1, 1] == 4, "Index [1, 1] == 4"); //} + private void TestRemainder3Structs() + { + ThreeBytes[] array = new ThreeBytes[1]; + array[0] = new ThreeBytes(17, 254, 77); + Assert.AreEqual(array[0].A, 17, "Three byte struct in array first value read correctly"); + Assert.AreEqual(array[0].B, 254, "Three byte struct in array second value read correctly"); + var local = array[0]; + Assert.AreEqual(local.C, 77, "Three byte struct third value read correctly"); + } + protected override void Run() { TestStep1(); @@ -265,6 +288,7 @@ protected override void Run() //Assert.IsTrue(true, "After TestMultidimensionalArray"); ConstrainedTest.MutateStructTest(); Assert.IsTrue(true, "After MutateTestStruct"); + TestRemainder3Structs(); TestController.Completed(); } From e1e504f8e06b55a16af81d5311adf06ad59779d2 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Sun, 20 Dec 2020 19:02:50 +0100 Subject: [PATCH 004/314] Trigger Build From 2f2cd626e33053b5259e0829d261be5883f1a009 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 24 Dec 2020 03:21:02 +0100 Subject: [PATCH 005/314] Implement non linear framebuffer detection for VBE multiboot Real hardware doesn't often use a linear framebuffer. It can causes graphics issues. --- source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs b/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs index b7174ef8a7..0839b17a97 100644 --- a/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs +++ b/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs @@ -81,8 +81,21 @@ public VBEDriver(ushort xres, ushort yres, ushort bpp) if (VBE.IsAvailable()) //VBE VESA Enabled Mulitboot Parsing { Global.mDebugger.SendInternal($"Creating VBE VESA driver with Mode {xres}*{yres}@{bpp}"); - IO.LinearFrameBuffer = new MemoryBlock(VBE.getLfbOffset(), (uint)xres * yres * (uint)(bpp / 8)); - lastbuffer = new ManagedMemoryBlock((uint)xres * yres * (uint)(bpp / 8)); + + var ModeInfo = VBE.getModeInfo(); + + if ((ModeInfo.pitch / 4) == ModeInfo.width) //linear framebuffer detection + { + IO.LinearFrameBuffer = new MemoryBlock(VBE.getLfbOffset(), (uint)xres * yres * (uint)(bpp / 8)); + lastbuffer = new ManagedMemoryBlock((uint)xres * yres * (uint)(bpp / 8)); + } + else + { + uint OffScreenSize = (ModeInfo.pitch / (uint)(bpp / 8)) - ModeInfo.width; + + IO.LinearFrameBuffer = new MemoryBlock(VBE.getLfbOffset(), (uint)(xres * yres * (uint)(bpp / 8)) + (OffScreenSize * yres * (uint)(bpp / 8))); + lastbuffer = new ManagedMemoryBlock((uint)(xres * yres * (uint)(bpp / 8)) + (OffScreenSize * yres * (uint)(bpp / 8))); + } } else if (ISAModeAvailable()) //Bochs Graphics Adaptor ISA Mode { From 32ee02c6d4fb7ecc167218044f614c0f146eb64b Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 24 Dec 2020 03:22:25 +0100 Subject: [PATCH 006/314] bpp is not always 4! --- source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs b/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs index 0839b17a97..f50d52a2fe 100644 --- a/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs +++ b/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs @@ -84,7 +84,7 @@ public VBEDriver(ushort xres, ushort yres, ushort bpp) var ModeInfo = VBE.getModeInfo(); - if ((ModeInfo.pitch / 4) == ModeInfo.width) //linear framebuffer detection + if ((ModeInfo.pitch / (bpp / 8)) == ModeInfo.width) //linear framebuffer detection { IO.LinearFrameBuffer = new MemoryBlock(VBE.getLfbOffset(), (uint)xres * yres * (uint)(bpp / 8)); lastbuffer = new ManagedMemoryBlock((uint)xres * yres * (uint)(bpp / 8)); From 3f3d6ab5ef68fc606f5c007d5c3de06d23ae051b Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Sun, 3 Jan 2021 12:07:41 -0500 Subject: [PATCH 007/314] Disable auto-install of workloads Disable auto-install of workloads --- .../Dependencies/InnoSetupDependency.cs | 1 + .../Dependencies/ReposDependency.cs | 1 + .../Dependencies/VisualStudioDependency.cs | 3 ++- .../VisualStudioWorkloadsDependency.cs | 2 +- source/Cosmos.Build.Builder/IDependency.cs | 1 + .../ViewModels/MainWindowViewModel.cs | 22 ++++++++++++++----- 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs b/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs index 806b605df7..c9d70e21c3 100644 --- a/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs @@ -14,6 +14,7 @@ internal class InnoSetupDependency : IDependency private const string InnoSetupInstallerUrl = "http://www.jrsoftware.org/download.php/is.exe"; public string Name => "Inno Setup"; + public bool ShouldInstallByDefault => true; private readonly IInnoSetupService _innoSetupService; diff --git a/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs b/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs index 44bfa95736..f80aabdd3b 100644 --- a/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs @@ -13,6 +13,7 @@ namespace Cosmos.Build.Builder.Dependencies internal class ReposDependency : IDependency { public string Name => "Repos: IL2CPU, XSharp and Common"; + public bool ShouldInstallByDefault => true; private readonly string _cosmosDir; private readonly IEnumerable _repos; diff --git a/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs b/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs index abdfa7968a..7e6df6d116 100644 --- a/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs @@ -9,11 +9,12 @@ namespace Cosmos.Build.Builder.Dependencies internal class VisualStudioDependency : IDependency { private static readonly Version MinimumVsVersion = new Version(15, 9); - + public bool ShouldInstallByDefault => true; public string Name => $"Visual Studio {MinimumVsVersion.Major}.{MinimumVsVersion.Minor}+"; private readonly ISetupInstance2 _visualStudioInstance; + public VisualStudioDependency(ISetupInstance2 visualStudioInstance) { _visualStudioInstance = visualStudioInstance; diff --git a/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs b/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs index 42a5806748..dd9423d86b 100644 --- a/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs @@ -17,7 +17,7 @@ internal class VisualStudioWorkloadsDependency : IDependency NetCoreToolsWorkload, VisualStudioExtensionsWorkload }; - + public bool ShouldInstallByDefault => false; public string Name => "Visual Studio Workloads"; private readonly ISetupInstance2 _visualStudioInstance; diff --git a/source/Cosmos.Build.Builder/IDependency.cs b/source/Cosmos.Build.Builder/IDependency.cs index e881c1a462..f53867fb1b 100644 --- a/source/Cosmos.Build.Builder/IDependency.cs +++ b/source/Cosmos.Build.Builder/IDependency.cs @@ -6,6 +6,7 @@ namespace Cosmos.Build.Builder internal interface IDependency { string Name { get; } + bool ShouldInstallByDefault { get; } Task IsInstalledAsync(CancellationToken cancellationToken); Task InstallAsync(CancellationToken cancellationToken); diff --git a/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs b/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs index 05836967df..a1458532b0 100644 --- a/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs +++ b/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs @@ -109,15 +109,27 @@ private async Task BuildAsync() { _logger.LogMessage($"{dependency.Name} not found."); - using (var viewModel = new DependencyInstallationDialogViewModel(dependency)) + if (dependency.ShouldInstallByDefault) { - _dependencyInstallationDialogService.ShowDialog(viewModel); - - if (!viewModel.InstallationSucceeded) + using (var viewModel = new DependencyInstallationDialogViewModel(dependency)) { - throw new Exception($"Dependency installation failed! Dependency name: {dependency.Name}"); + _dependencyInstallationDialogService.ShowDialog(viewModel); + + if (!viewModel.InstallationSucceeded) + { + throw new Exception($"Dependency installation failed! Dependency name: {dependency.Name}"); + } } } + else + { + MessageBox.Show($"{dependency.Name} is not installed. Please install {dependency.Name}"); + _logger.SetError(); + _logger.NewSection("Error"); + _logger.LogMessage($"{dependency.Name} not found."); + _logger.SetError(); + return; + } } } From 07aae9c192108fa0a122fb6e5ef63641dad152da Mon Sep 17 00:00:00 2001 From: F4lc0131 Date: Mon, 4 Jan 2021 12:48:21 +0100 Subject: [PATCH 008/314] Italian readme.md Added translation to italian --- readme-IT.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 readme-IT.md diff --git a/readme-IT.md b/readme-IT.md new file mode 100644 index 0000000000..eec341039e --- /dev/null +++ b/readme-IT.md @@ -0,0 +1,9 @@ +# Cosmos + +[![Build status](https://ci.appveyor.com/api/projects/status/kust7g5dlnykhkaf/branch/master?svg=true)](https://ci.appveyor.com/project/CosmosOS/cosmos/branch/master) + +Cosmos è un "kit di costruzione" per SO. Fai il tuo sistema operativo con linguaggi gestiti come C#, VB.NET, e altri! + +Per avere informazioni su come usare Cosmos, visita il [sito web di Cosmos](http://www.gocosmos.org). + +Per documentazione e informazioni tecniche, visita la [documentazione di Cosmos](https://cosmosos.github.io). From 8353d993770a9808afc6bf7fdd3ef33513875fa4 Mon Sep 17 00:00:00 2001 From: F4lc0131 Date: Tue, 5 Jan 2021 00:31:36 +0100 Subject: [PATCH 009/314] Add files via upload --- .../System/ConsoleImpl.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs b/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs index 3c6af9d5ce..03d319108b 100644 --- a/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs +++ b/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs @@ -431,8 +431,23 @@ public static ConsoleKeyInfo ReadKey(bool intercept) return new ConsoleKeyInfo(key.KeyChar, key.Key.ToConsoleKey(), xShift, xAlt, xControl); } + /// + /// This will contain the context that locked the Console for the ReadLine() + /// + private static Core.Processing.ProcessContext.Context LockContext = null; + /// + /// This will contain the queue where threads have to wait before accessing the ReadLine method + /// + private static List queue = new List(); + private static List old = null; public static String ReadLine() { + if (LockContext is null) LockContext = Core.Processing.ProcessContext.m_CurrentContext; //if nobody locked the Console, just lock it + else if (LockContext != Core.Processing.ProcessContext.m_CurrentContext) + { + queue.Add(Core.Processing.ProcessContext.m_CurrentContext); + while (LockContext != Core.Processing.ProcessContext.m_CurrentContext) ; + } var xConsole = GetConsole(); if (xConsole == null) { @@ -529,6 +544,19 @@ public static String ReadLine() WriteLine(); char[] final = chars.ToArray(); + //if there's some process queued, we just set the first as the main and queue the otherones + if (queue.Count > 0) + { + Cosmos.HAL.Global.mDebugger.Send($"Dequeuing {queue[0].name} and locking console to it"); + LockContext = queue[0]; + old = queue; + queue = new List(); + foreach (Core.Processing.ProcessContext.Context context in old) + { + if (context != LockContext) + queue.Add(context); + } + } return new string(final); } From 261120443767865b9767e2b73d5fc455d40bdb41 Mon Sep 17 00:00:00 2001 From: F4lc0131 Date: Tue, 5 Jan 2021 01:06:55 +0100 Subject: [PATCH 010/314] Removed some useless stuff --- .../System/ConsoleImpl.cs | 1438 ++++++++--------- 1 file changed, 716 insertions(+), 722 deletions(-) diff --git a/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs b/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs index 03d319108b..8f9cf2ee93 100644 --- a/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs +++ b/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs @@ -1,553 +1,547 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Cosmos.System; -using IL2CPU.API; -using IL2CPU.API.Attribs; - -namespace Cosmos.System_Plugs.System -{ - [Plug(Target = typeof (global::System.Console))] - public static class ConsoleImpl - { - private static ConsoleColor mForeground = ConsoleColor.White; - private static ConsoleColor mBackground = ConsoleColor.Black; - private static Encoding ConsoleInputEncoding = Encoding.ASCII; - private static Encoding ConsoleOutputEncoding = Encoding.ASCII; - - private static readonly Cosmos.System.Console mFallbackConsole = new Cosmos.System.Console(null); - - private static Cosmos.System.Console GetConsole() - { - return mFallbackConsole; - } - - public static ConsoleColor get_BackgroundColor() - { - return mBackground; - } - - public static void set_BackgroundColor(ConsoleColor value) - { - mBackground = value; - //Cosmos.HAL.Global.TextScreen.SetColors(mForeground, mBackground); - if (GetConsole() != null) GetConsole().Background = value; - } - - public static int get_BufferHeight() - { - WriteLine("Not implemented: get_BufferHeight"); - return -1; - } - - public static void set_BufferHeight(int aHeight) - { - WriteLine("Not implemented: set_BufferHeight"); - } - - public static int get_BufferWidth() - { - WriteLine("Not implemented: get_BufferWidth"); - return -1; - } - - public static void set_BufferWidth(int aWidth) - { - WriteLine("Not implemented: set_BufferWidth"); - } - - public static bool get_CapsLock() - { - return Global.CapsLock; - } - - public static int get_CursorLeft() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return 0; - } - return GetConsole().X; - } - - public static void set_CursorLeft(int x) - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; - } - - if (x < get_WindowWidth()) - { - xConsole.X = x; - } - else - { - WriteLine("x must be lower than the console width!"); - } - } - - public static int get_CursorSize() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return 0; - } - return xConsole.CursorSize; - } - - public static void set_CursorSize(int aSize) - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; - } - xConsole.CursorSize = aSize; - } - - public static int get_CursorTop() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return 0; - } - return GetConsole().Y; - } - - public static void set_CursorTop(int y) - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; - } - - if (y < get_WindowHeight()) - { - xConsole.Y = y; - } - else - { - WriteLine("y must be lower than the console height!"); - } - } - - public static bool get_CursorVisible() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - return false; - } - return GetConsole().CursorVisible; - } - - public static void set_CursorVisible(bool value) - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; - } - xConsole.CursorVisible = value; - } - - - //public static TextWriter get_Error() { - // WriteLine("Not implemented: get_Error"); - // return null; - //} - - public static ConsoleColor get_ForegroundColor() - { - return mForeground; - } - - public static void set_ForegroundColor(ConsoleColor value) - { - mForeground = value; - //Cosmos.HAL.Global.TextScreen.SetColors(mForeground, mBackground); - if (GetConsole() != null) GetConsole().Foreground = value; - } - - //public static TextReader get_In() - //{ - // WriteLine("Not implemented: get_In"); - // return null; - //} - - public static Encoding get_InputEncoding() - { - return ConsoleInputEncoding; - } - - public static void set_InputEncoding(Encoding value) - { - ConsoleInputEncoding = value; - } - - public static Encoding get_OutputEncoding() - { - return ConsoleOutputEncoding; - } - - - public static void set_OutputEncoding(Encoding value) - { - ConsoleOutputEncoding = value; - } - - public static bool get_KeyAvailable() - { - return KeyboardManager.KeyAvailable; - } - - public static int get_LargestWindowHeight() - { - WriteLine("Not implemented: get_LargestWindowHeight"); - return -1; - } - - public static int get_LargestWindowWidth() - { - WriteLine("Not implemented: get_LargestWindowWidth"); - return -1; - } - - public static bool get_NumberLock() - { - return Global.NumLock; - } - - //public static TextWriter get_Out() { - // WriteLine("Not implemented: get_Out"); - // return null; - //} - - public static string get_Title() - { - WriteLine("Not implemented: get_Title"); - return string.Empty; - } - - public static void set_Title(string value) - { - WriteLine("Not implemented: set_Title"); - } - - public static bool get_TreatControlCAsInput() - { - WriteLine("Not implemented: get_TreatControlCAsInput"); - return false; - } - - public static void set_TreatControlCAsInput(bool value) - { - WriteLine("Not implemented: set_TreatControlCAsInput"); - } - - public static int get_WindowHeight() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return 25; - } - return GetConsole().Rows; - } - - public static void set_WindowHeight(int value) - { - WriteLine("Not implemented: set_WindowHeight"); - } - - public static int get_WindowLeft() - { - WriteLine("Not implemented: get_WindowLeft"); - return -1; - } - - public static void set_WindowLeft(int value) - { - WriteLine("Not implemented: set_WindowLeft"); - } - - public static int get_WindowTop() - { - WriteLine("Not implemented: get_WindowTop"); - return -1; - } - - public static void set_WindowTop(int value) - { - WriteLine("Not implemented: set_WindowTop"); - } - - public static int get_WindowWidth() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return 85; - } - return GetConsole().Cols; - } - - public static void set_WindowWidth(int value) - { - WriteLine("Not implemented: set_WindowWidth"); - } - - /// - /// The ArgumentOutOfRangeException check is now done at driver level in PCSpeaker - is it still needed here? - /// - /// - /// - public static void Beep(int aFrequency, int aDuration) - { - if (aFrequency < 37 || aFrequency > 32767) - { - throw new ArgumentOutOfRangeException("Frequency must be between 37 and 32767Hz"); - } - - if (aDuration <= 0) - { - throw new ArgumentOutOfRangeException("Duration must be more than 0"); - } - - PCSpeaker.Beep((uint) aFrequency, (uint) aDuration); - } - - /// - /// Beep() is pure CIL - /// Default implementation beeps for 200 milliseconds at 800 hertz - /// In Cosmos, these are Cosmos.System.Duration.Default and Cosmos.System.Notes.Default respectively, - /// and are used when there are no params - /// https://docs.microsoft.com/en-us/dotnet/api/system.console.beep?view=netcore-2.0 - /// - public static void Beep() - { - PCSpeaker.Beep(); - } - - //TODO: Console uses TextWriter - intercept and plug it instead - public static void Clear() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; - } - GetConsole().Clear(); - } - - // MoveBufferArea(int, int, int, int, int, int) is pure CIL - - public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, - int targetLeft, int targetTop, Char sourceChar, ConsoleColor sourceForeColor, ConsoleColor sourceBackColor) - { - WriteLine("Not implemented: MoveBufferArea"); - } - - //public static Stream OpenStandardError() { - // WriteLine("Not implemented: OpenStandardError"); - //} - - //public static Stream OpenStandardError(int bufferSize) { - // WriteLine("Not implemented: OpenStandardError"); - //} - - //public static Stream OpenStandardInput(int bufferSize) { - // WriteLine("Not implemented: OpenStandardInput"); - //} - - //public static Stream OpenStandardInput() { - // WriteLine("Not implemented: OpenStandardInput"); - //} - - //public static Stream OpenStandardOutput(int bufferSize) { - // WriteLine("Not implemented: OpenStandardOutput"); - //} - - //public static Stream OpenStandardOutput() { - // WriteLine("Not implemented: OpenStandardOutput"); - //} - - public static int Read() - { - // TODO special cases, if needed, that returns -1 - KeyEvent xResult; - - if (KeyboardManager.TryReadKey(out xResult)) - { - return xResult.KeyChar; - } - else - { - return -1; - } - } - - public static ConsoleKeyInfo ReadKey() - { - return ReadKey(false); - } - - // ReadKey() pure CIL - - public static ConsoleKeyInfo ReadKey(bool intercept) - { - var key = KeyboardManager.ReadKey(); - if (intercept == false && key.KeyChar != '\0') - { - Write(key.KeyChar); - } - - //TODO: Plug HasFlag and use the next 3 lines instead of the 3 following lines - - //bool xShift = key.Modifiers.HasFlag(ConsoleModifiers.Shift); - //bool xAlt = key.Modifiers.HasFlag(ConsoleModifiers.Alt); - //bool xControl = key.Modifiers.HasFlag(ConsoleModifiers.Control); - - bool xShift = (key.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift; - bool xAlt = (key.Modifiers & ConsoleModifiers.Alt) == ConsoleModifiers.Alt; - bool xControl = (key.Modifiers & ConsoleModifiers.Control) == ConsoleModifiers.Control; - - return new ConsoleKeyInfo(key.KeyChar, key.Key.ToConsoleKey(), xShift, xAlt, xControl); - } - +using System; +using System.Collections.Generic; +using System.Text; +using Cosmos.System; +using IL2CPU.API; +using IL2CPU.API.Attribs; + +namespace Cosmos.System_Plugs.System +{ + [Plug(Target = typeof (global::System.Console))] + public static class ConsoleImpl + { + private static ConsoleColor mForeground = ConsoleColor.White; + private static ConsoleColor mBackground = ConsoleColor.Black; + private static Encoding ConsoleInputEncoding = Encoding.ASCII; + private static Encoding ConsoleOutputEncoding = Encoding.ASCII; + + private static readonly Cosmos.System.Console mFallbackConsole = new Cosmos.System.Console(null); + + private static Cosmos.System.Console GetConsole() + { + return mFallbackConsole; + } + + public static ConsoleColor get_BackgroundColor() + { + return mBackground; + } + + public static void set_BackgroundColor(ConsoleColor value) + { + mBackground = value; + //Cosmos.HAL.Global.TextScreen.SetColors(mForeground, mBackground); + if (GetConsole() != null) GetConsole().Background = value; + } + + public static int get_BufferHeight() + { + WriteLine("Not implemented: get_BufferHeight"); + return -1; + } + + public static void set_BufferHeight(int aHeight) + { + WriteLine("Not implemented: set_BufferHeight"); + } + + public static int get_BufferWidth() + { + WriteLine("Not implemented: get_BufferWidth"); + return -1; + } + + public static void set_BufferWidth(int aWidth) + { + WriteLine("Not implemented: set_BufferWidth"); + } + + public static bool get_CapsLock() + { + return Global.CapsLock; + } + + public static int get_CursorLeft() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return 0; + } + return GetConsole().X; + } + + public static void set_CursorLeft(int x) + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + + if (x < get_WindowWidth()) + { + xConsole.X = x; + } + else + { + WriteLine("x must be lower than the console width!"); + } + } + + public static int get_CursorSize() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return 0; + } + return xConsole.CursorSize; + } + + public static void set_CursorSize(int aSize) + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + xConsole.CursorSize = aSize; + } + + public static int get_CursorTop() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return 0; + } + return GetConsole().Y; + } + + public static void set_CursorTop(int y) + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + + if (y < get_WindowHeight()) + { + xConsole.Y = y; + } + else + { + WriteLine("y must be lower than the console height!"); + } + } + + public static bool get_CursorVisible() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + return false; + } + return GetConsole().CursorVisible; + } + + public static void set_CursorVisible(bool value) + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + xConsole.CursorVisible = value; + } + + + //public static TextWriter get_Error() { + // WriteLine("Not implemented: get_Error"); + // return null; + //} + + public static ConsoleColor get_ForegroundColor() + { + return mForeground; + } + + public static void set_ForegroundColor(ConsoleColor value) + { + mForeground = value; + //Cosmos.HAL.Global.TextScreen.SetColors(mForeground, mBackground); + if (GetConsole() != null) GetConsole().Foreground = value; + } + + //public static TextReader get_In() + //{ + // WriteLine("Not implemented: get_In"); + // return null; + //} + + public static Encoding get_InputEncoding() + { + return ConsoleInputEncoding; + } + + public static void set_InputEncoding(Encoding value) + { + ConsoleInputEncoding = value; + } + + public static Encoding get_OutputEncoding() + { + return ConsoleOutputEncoding; + } + + + public static void set_OutputEncoding(Encoding value) + { + ConsoleOutputEncoding = value; + } + + public static bool get_KeyAvailable() + { + return KeyboardManager.KeyAvailable; + } + + public static int get_LargestWindowHeight() + { + WriteLine("Not implemented: get_LargestWindowHeight"); + return -1; + } + + public static int get_LargestWindowWidth() + { + WriteLine("Not implemented: get_LargestWindowWidth"); + return -1; + } + + public static bool get_NumberLock() + { + return Global.NumLock; + } + + //public static TextWriter get_Out() { + // WriteLine("Not implemented: get_Out"); + // return null; + //} + + public static string get_Title() + { + WriteLine("Not implemented: get_Title"); + return string.Empty; + } + + public static void set_Title(string value) + { + WriteLine("Not implemented: set_Title"); + } + + public static bool get_TreatControlCAsInput() + { + WriteLine("Not implemented: get_TreatControlCAsInput"); + return false; + } + + public static void set_TreatControlCAsInput(bool value) + { + WriteLine("Not implemented: set_TreatControlCAsInput"); + } + + public static int get_WindowHeight() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return 25; + } + return GetConsole().Rows; + } + + public static void set_WindowHeight(int value) + { + WriteLine("Not implemented: set_WindowHeight"); + } + + public static int get_WindowLeft() + { + WriteLine("Not implemented: get_WindowLeft"); + return -1; + } + + public static void set_WindowLeft(int value) + { + WriteLine("Not implemented: set_WindowLeft"); + } + + public static int get_WindowTop() + { + WriteLine("Not implemented: get_WindowTop"); + return -1; + } + + public static void set_WindowTop(int value) + { + WriteLine("Not implemented: set_WindowTop"); + } + + public static int get_WindowWidth() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return 85; + } + return GetConsole().Cols; + } + + public static void set_WindowWidth(int value) + { + WriteLine("Not implemented: set_WindowWidth"); + } + /// - /// This will contain the context that locked the Console for the ReadLine() - /// - private static Core.Processing.ProcessContext.Context LockContext = null; + /// The ArgumentOutOfRangeException check is now done at driver level in PCSpeaker - is it still needed here? + /// + /// + /// + public static void Beep(int aFrequency, int aDuration) + { + if (aFrequency < 37 || aFrequency > 32767) + { + throw new ArgumentOutOfRangeException("Frequency must be between 37 and 32767Hz"); + } + + if (aDuration <= 0) + { + throw new ArgumentOutOfRangeException("Duration must be more than 0"); + } + + PCSpeaker.Beep((uint) aFrequency, (uint) aDuration); + } + /// - /// This will contain the queue where threads have to wait before accessing the ReadLine method - /// - private static List queue = new List(); + /// Beep() is pure CIL + /// Default implementation beeps for 200 milliseconds at 800 hertz + /// In Cosmos, these are Cosmos.System.Duration.Default and Cosmos.System.Notes.Default respectively, + /// and are used when there are no params + /// https://docs.microsoft.com/en-us/dotnet/api/system.console.beep?view=netcore-2.0 + /// + public static void Beep() + { + PCSpeaker.Beep(); + } + + //TODO: Console uses TextWriter - intercept and plug it instead + public static void Clear() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + GetConsole().Clear(); + } + + // MoveBufferArea(int, int, int, int, int, int) is pure CIL + + public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, + int targetLeft, int targetTop, Char sourceChar, ConsoleColor sourceForeColor, ConsoleColor sourceBackColor) + { + WriteLine("Not implemented: MoveBufferArea"); + } + + //public static Stream OpenStandardError() { + // WriteLine("Not implemented: OpenStandardError"); + //} + + //public static Stream OpenStandardError(int bufferSize) { + // WriteLine("Not implemented: OpenStandardError"); + //} + + //public static Stream OpenStandardInput(int bufferSize) { + // WriteLine("Not implemented: OpenStandardInput"); + //} + + //public static Stream OpenStandardInput() { + // WriteLine("Not implemented: OpenStandardInput"); + //} + + //public static Stream OpenStandardOutput(int bufferSize) { + // WriteLine("Not implemented: OpenStandardOutput"); + //} + + //public static Stream OpenStandardOutput() { + // WriteLine("Not implemented: OpenStandardOutput"); + //} + + public static int Read() + { + // TODO special cases, if needed, that returns -1 + KeyEvent xResult; + + if (KeyboardManager.TryReadKey(out xResult)) + { + return xResult.KeyChar; + } + else + { + return -1; + } + } + + public static ConsoleKeyInfo ReadKey() + { + return ReadKey(false); + } + + // ReadKey() pure CIL + + public static ConsoleKeyInfo ReadKey(bool intercept) + { + var key = KeyboardManager.ReadKey(); + if (intercept == false && key.KeyChar != '\0') + { + Write(key.KeyChar); + } + + //TODO: Plug HasFlag and use the next 3 lines instead of the 3 following lines + + //bool xShift = key.Modifiers.HasFlag(ConsoleModifiers.Shift); + //bool xAlt = key.Modifiers.HasFlag(ConsoleModifiers.Alt); + //bool xControl = key.Modifiers.HasFlag(ConsoleModifiers.Control); + + bool xShift = (key.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift; + bool xAlt = (key.Modifiers & ConsoleModifiers.Alt) == ConsoleModifiers.Alt; + bool xControl = (key.Modifiers & ConsoleModifiers.Control) == ConsoleModifiers.Control; + + return new ConsoleKeyInfo(key.KeyChar, key.Key.ToConsoleKey(), xShift, xAlt, xControl); + } + + private static Core.Processing.ProcessContext.Context LockContext = null; + private static List queue = new List(); private static List old = null; - public static String ReadLine() - { - if (LockContext is null) LockContext = Core.Processing.ProcessContext.m_CurrentContext; //if nobody locked the Console, just lock it + public static String ReadLine() + { + if (LockContext == null) LockContext = Core.Processing.ProcessContext.m_CurrentContext; //if nobody locked the Console, just lock it else if (LockContext != Core.Processing.ProcessContext.m_CurrentContext) { queue.Add(Core.Processing.ProcessContext.m_CurrentContext); while (LockContext != Core.Processing.ProcessContext.m_CurrentContext) ; - } - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return null; - } - List chars = new List(32); - KeyEvent current; - int currentCount = 0; - - while ((current = KeyboardManager.ReadKey()).Key != ConsoleKeyEx.Enter) - { - if (current.Key == ConsoleKeyEx.NumEnter) break; - //Check for "special" keys - if (current.Key == ConsoleKeyEx.Backspace) // Backspace - { - if (currentCount > 0) - { - int curCharTemp = GetConsole().X; - chars.RemoveAt(currentCount - 1); - GetConsole().X = GetConsole().X - 1; - - //Move characters to the left - for (int x = currentCount - 1; x < chars.Count; x++) - { - Write(chars[x]); - } - - Write(' '); - - GetConsole().X = curCharTemp - 1; - - currentCount--; - } - continue; - } - else if (current.Key == ConsoleKeyEx.LeftArrow) - { - if (currentCount > 0) - { - GetConsole().X = GetConsole().X - 1; - currentCount--; - } - continue; - } - else if (current.Key == ConsoleKeyEx.RightArrow) - { - if (currentCount < chars.Count) - { - GetConsole().X = GetConsole().X + 1; - currentCount++; - } - continue; - } - - if (current.KeyChar == '\0') continue; - - //Write the character to the screen - if (currentCount == chars.Count) - { - chars.Add(current.KeyChar); - Write(current.KeyChar); - currentCount++; - } - else - { - //Insert the new character in the correct location - //For some reason, List.Insert() doesn't work properly - //so the character has to be inserted manually - List temp = new List(); - - for (int x = 0; x < chars.Count; x++) - { - if (x == currentCount) - { - temp.Add(current.KeyChar); - } - - temp.Add(chars[x]); - } - - chars = temp; - - //Shift the characters to the right - for (int x = currentCount; x < chars.Count; x++) - { - Write(chars[x]); - } - - GetConsole().X -= (chars.Count - currentCount) - 1; - currentCount++; - } - } - WriteLine(); - - char[] final = chars.ToArray(); - //if there's some process queued, we just set the first as the main and queue the otherones + } + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return null; + } + List chars = new List(32); + KeyEvent current; + int currentCount = 0; + + while ((current = KeyboardManager.ReadKey()).Key != ConsoleKeyEx.Enter) + { + if (current.Key == ConsoleKeyEx.NumEnter) break; + //Check for "special" keys + if (current.Key == ConsoleKeyEx.Backspace) // Backspace + { + if (currentCount > 0) + { + int curCharTemp = GetConsole().X; + chars.RemoveAt(currentCount - 1); + GetConsole().X = GetConsole().X - 1; + + //Move characters to the left + for (int x = currentCount - 1; x < chars.Count; x++) + { + Write(chars[x]); + } + + Write(' '); + + GetConsole().X = curCharTemp - 1; + + currentCount--; + } + continue; + } + else if (current.Key == ConsoleKeyEx.LeftArrow) + { + if (currentCount > 0) + { + GetConsole().X = GetConsole().X - 1; + currentCount--; + } + continue; + } + else if (current.Key == ConsoleKeyEx.RightArrow) + { + if (currentCount < chars.Count) + { + GetConsole().X = GetConsole().X + 1; + currentCount++; + } + continue; + } + + if (current.KeyChar == '\0') continue; + + //Write the character to the screen + if (currentCount == chars.Count) + { + chars.Add(current.KeyChar); + Write(current.KeyChar); + currentCount++; + } + else + { + //Insert the new character in the correct location + //For some reason, List.Insert() doesn't work properly + //so the character has to be inserted manually + List temp = new List(); + + for (int x = 0; x < chars.Count; x++) + { + if (x == currentCount) + { + temp.Add(current.KeyChar); + } + + temp.Add(chars[x]); + } + + chars = temp; + + //Shift the characters to the right + for (int x = currentCount; x < chars.Count; x++) + { + Write(chars[x]); + } + + GetConsole().X -= (chars.Count - currentCount) - 1; + currentCount++; + } + } + WriteLine(); + + char[] final = chars.ToArray(); + //if there's some process queued, we just set the first as the main and queue the otherones if (queue.Count > 0) { - Cosmos.HAL.Global.mDebugger.Send($"Dequeuing {queue[0].name} and locking console to it"); + Cosmos.HAL.Global.mDebugger.Send($"Removing {queue[0].name} from Queue and locking console to it"); LockContext = queue[0]; old = queue; queue = new List(); @@ -556,184 +550,184 @@ public static String ReadLine() if (context != LockContext) queue.Add(context); } - } - return new string(final); - } - - public static void ResetColor() - { - set_BackgroundColor(ConsoleColor.Black); - set_ForegroundColor(ConsoleColor.White); - } - - public static void SetBufferSize(int width, int height) - { - WriteLine("Not implemented: SetBufferSize"); - } - - public static void SetCursorPosition(int left, int top) - { - set_CursorLeft(left); - set_CursorTop(top); - } - - //public static void SetError(TextWriter newError) { - // WriteLine("Not implemented: SetError"); - //} - - //public static void SetIn(TextReader newIn) { - // WriteLine("Not implemented: SetIn"); - //} - - //public static void SetOut(TextWriter newOut) { - // WriteLine("Not implemented: SetOut"); - //} - - public static void SetWindowPosition(int left, int top) - { - WriteLine("Not implemented: SetWindowPosition"); - } - - public static void SetWindowSize(int width, int height) - { - WriteLine("Not implemented: SetWindowSize"); - } - - #region Write - - public static void Write(bool aBool) - { - Write(aBool.ToString()); - } - - /* - * A .Net character can be effectevily more can one byte so calling the low level Console.Write() will be wrong as - * it accepts only bytes, we need to convert it using the specified OutputEncoding but to do this we have to convert - * it ToString first - */ - public static void Write(char aChar) => Write(aChar.ToString()); - - public static void Write(char[] aBuffer) => Write(aBuffer, 0, aBuffer.Length); - - /* Decimal type is not working yet... */ - //public static void Write(decimal aDecimal) => Write(aDecimal.ToString()); - - public static void Write(double aDouble) => Write(aDouble.ToString()); - - public static void Write(float aFloat) => Write(aFloat.ToString()); - - public static void Write(int aInt) => Write(aInt.ToString()); - - public static void Write(long aLong) => Write(aLong.ToString()); - - /* Correct behaviour printing null should not throw NRE or do nothing but should print an empty string */ - public static void Write(object value) => Write((value ?? String.Empty)); - - public static void Write(string aText) - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; - } - - byte[] aTextEncoded = ConsoleOutputEncoding.GetBytes(aText); - GetConsole().Write(aTextEncoded); - } - - public static void Write(uint aInt) => Write(aInt.ToString()); - - public static void Write(ulong aLong) => Write(aLong.ToString()); - - public static void Write(string format, object arg0) => Write(String.Format(format, arg0)); - - public static void Write(string format, object arg0, object arg1) => Write(String.Format(format, arg0, arg1)); - - public static void Write(string format, object arg0, object arg1, object arg2) => Write(String.Format(format, arg0, arg1, arg2)); - - public static void Write(string format, object arg0, object arg1, object arg2, object arg3) => Write(String.Format(format, arg0, arg1, arg2, arg3)); - - public static void Write(string format, params object[] arg) => Write(String.Format(format, arg)); - - public static void Write(char[] aBuffer, int aIndex, int aCount) - { - if (aBuffer == null) - { - throw new ArgumentNullException("aBuffer"); - } - if (aIndex < 0) - { - throw new ArgumentOutOfRangeException("aIndex"); - } - if (aCount < 0) - { - throw new ArgumentOutOfRangeException("aCount"); - } - if ((aBuffer.Length - aIndex) < aCount) - { - throw new ArgumentException(); - } - for (int i = 0; i < aCount; i++) - { - Write(aBuffer[aIndex + i]); - } - } - - //You'd expect this to be on System.Console wouldn't you? Well, it ain't so we just rely on Write(object value) - //public static void Write(byte aByte) { - // Write(aByte.ToString()); - //} - -#endregion - -#region WriteLine - - public static void WriteLine() => Write(Environment.NewLine); - - public static void WriteLine(bool aBool) => WriteLine(aBool.ToString()); - - public static void WriteLine(char aChar) => WriteLine(aChar.ToString()); - - public static void WriteLine(char[] aBuffer) => WriteLine(new String(aBuffer)); - - /* Decimal type is not working yet... */ - //public static void WriteLine(decimal aDecimal) => WriteLine(aDecimal.ToString()); - - public static void WriteLine(double aDouble) => WriteLine(aDouble.ToString()); - - public static void WriteLine(float aFloat) => WriteLine(aFloat.ToString()); - - public static void WriteLine(int aInt) => WriteLine(aInt.ToString()); - - public static void WriteLine(long aLong) => WriteLine(aLong.ToString()); - - /* Correct behaviour printing null should not throw NRE or do nothing but should print an empty line */ - public static void WriteLine(object value) => Write((value ?? String.Empty) + Environment.NewLine); - - public static void WriteLine(string aText) => Write(aText + Environment.NewLine); - - public static void WriteLine(uint aInt) => WriteLine(aInt.ToString()); - - public static void WriteLine(ulong aLong) => WriteLine(aLong.ToString()); - - public static void WriteLine(string format, object arg0) => WriteLine(String.Format(format, arg0)); - - public static void WriteLine(string format, object arg0, object arg1) => WriteLine(String.Format(format, arg0, arg1)); - - public static void WriteLine(string format, object arg0, object arg1, object arg2) => WriteLine(String.Format(format, arg0, arg1, arg2)); - - public static void WriteLine(string format, object arg0, object arg1, object arg2, object arg3) => WriteLine(String.Format(format, arg0, arg1, arg2, arg3)); - - public static void WriteLine(string format, params object[] arg) => WriteLine(String.Format(format, arg)); - - public static void WriteLine(char[] aBuffer, int aIndex, int aCount) - { - Write(aBuffer, aIndex, aCount); - WriteLine(); - } - -#endregion - - } -} + } + return new string(final); + } + + public static void ResetColor() + { + set_BackgroundColor(ConsoleColor.Black); + set_ForegroundColor(ConsoleColor.White); + } + + public static void SetBufferSize(int width, int height) + { + WriteLine("Not implemented: SetBufferSize"); + } + + public static void SetCursorPosition(int left, int top) + { + set_CursorLeft(left); + set_CursorTop(top); + } + + //public static void SetError(TextWriter newError) { + // WriteLine("Not implemented: SetError"); + //} + + //public static void SetIn(TextReader newIn) { + // WriteLine("Not implemented: SetIn"); + //} + + //public static void SetOut(TextWriter newOut) { + // WriteLine("Not implemented: SetOut"); + //} + + public static void SetWindowPosition(int left, int top) + { + WriteLine("Not implemented: SetWindowPosition"); + } + + public static void SetWindowSize(int width, int height) + { + WriteLine("Not implemented: SetWindowSize"); + } + + #region Write + + public static void Write(bool aBool) + { + Write(aBool.ToString()); + } + + /* + * A .Net character can be effectevily more can one byte so calling the low level Console.Write() will be wrong as + * it accepts only bytes, we need to convert it using the specified OutputEncoding but to do this we have to convert + * it ToString first + */ + public static void Write(char aChar) => Write(aChar.ToString()); + + public static void Write(char[] aBuffer) => Write(aBuffer, 0, aBuffer.Length); + + /* Decimal type is not working yet... */ + //public static void Write(decimal aDecimal) => Write(aDecimal.ToString()); + + public static void Write(double aDouble) => Write(aDouble.ToString()); + + public static void Write(float aFloat) => Write(aFloat.ToString()); + + public static void Write(int aInt) => Write(aInt.ToString()); + + public static void Write(long aLong) => Write(aLong.ToString()); + + /* Correct behaviour printing null should not throw NRE or do nothing but should print an empty string */ + public static void Write(object value) => Write((value ?? String.Empty)); + + public static void Write(string aText) + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + + byte[] aTextEncoded = ConsoleOutputEncoding.GetBytes(aText); + GetConsole().Write(aTextEncoded); + } + + public static void Write(uint aInt) => Write(aInt.ToString()); + + public static void Write(ulong aLong) => Write(aLong.ToString()); + + public static void Write(string format, object arg0) => Write(String.Format(format, arg0)); + + public static void Write(string format, object arg0, object arg1) => Write(String.Format(format, arg0, arg1)); + + public static void Write(string format, object arg0, object arg1, object arg2) => Write(String.Format(format, arg0, arg1, arg2)); + + public static void Write(string format, object arg0, object arg1, object arg2, object arg3) => Write(String.Format(format, arg0, arg1, arg2, arg3)); + + public static void Write(string format, params object[] arg) => Write(String.Format(format, arg)); + + public static void Write(char[] aBuffer, int aIndex, int aCount) + { + if (aBuffer == null) + { + throw new ArgumentNullException("aBuffer"); + } + if (aIndex < 0) + { + throw new ArgumentOutOfRangeException("aIndex"); + } + if (aCount < 0) + { + throw new ArgumentOutOfRangeException("aCount"); + } + if ((aBuffer.Length - aIndex) < aCount) + { + throw new ArgumentException(); + } + for (int i = 0; i < aCount; i++) + { + Write(aBuffer[aIndex + i]); + } + } + + //You'd expect this to be on System.Console wouldn't you? Well, it ain't so we just rely on Write(object value) + //public static void Write(byte aByte) { + // Write(aByte.ToString()); + //} + +#endregion + +#region WriteLine + + public static void WriteLine() => Write(Environment.NewLine); + + public static void WriteLine(bool aBool) => WriteLine(aBool.ToString()); + + public static void WriteLine(char aChar) => WriteLine(aChar.ToString()); + + public static void WriteLine(char[] aBuffer) => WriteLine(new String(aBuffer)); + + /* Decimal type is not working yet... */ + //public static void WriteLine(decimal aDecimal) => WriteLine(aDecimal.ToString()); + + public static void WriteLine(double aDouble) => WriteLine(aDouble.ToString()); + + public static void WriteLine(float aFloat) => WriteLine(aFloat.ToString()); + + public static void WriteLine(int aInt) => WriteLine(aInt.ToString()); + + public static void WriteLine(long aLong) => WriteLine(aLong.ToString()); + + /* Correct behaviour printing null should not throw NRE or do nothing but should print an empty line */ + public static void WriteLine(object value) => Write((value ?? String.Empty) + Environment.NewLine); + + public static void WriteLine(string aText) => Write(aText + Environment.NewLine); + + public static void WriteLine(uint aInt) => WriteLine(aInt.ToString()); + + public static void WriteLine(ulong aLong) => WriteLine(aLong.ToString()); + + public static void WriteLine(string format, object arg0) => WriteLine(String.Format(format, arg0)); + + public static void WriteLine(string format, object arg0, object arg1) => WriteLine(String.Format(format, arg0, arg1)); + + public static void WriteLine(string format, object arg0, object arg1, object arg2) => WriteLine(String.Format(format, arg0, arg1, arg2)); + + public static void WriteLine(string format, object arg0, object arg1, object arg2, object arg3) => WriteLine(String.Format(format, arg0, arg1, arg2, arg3)); + + public static void WriteLine(string format, params object[] arg) => WriteLine(String.Format(format, arg)); + + public static void WriteLine(char[] aBuffer, int aIndex, int aCount) + { + Write(aBuffer, aIndex, aCount); + WriteLine(); + } + +#endregion + + } +} From 64b2d3bd41b7ee2975b3f61262d53966558fa60e Mon Sep 17 00:00:00 2001 From: F4lc0131 Date: Tue, 5 Jan 2021 13:53:44 +0100 Subject: [PATCH 011/314] Add files via upload --- source/Cosmos.System2/LockSystem.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 source/Cosmos.System2/LockSystem.cs diff --git a/source/Cosmos.System2/LockSystem.cs b/source/Cosmos.System2/LockSystem.cs new file mode 100644 index 0000000000..b035991f8d --- /dev/null +++ b/source/Cosmos.System2/LockSystem.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Cosmos.System +{ + public class LockSystem + { + public static Dictionary definedLocks = new Dictionary(); + public class Lock + { + internal Lock() { } + public Core.Processing.ProcessContext.Context LockContext = null; + public List queue = new List(); + } + public static Lock DefineLock(string LockName) + { + definedLocks.Add(LockName, new Lock()); + return definedLocks[LockName]; + } + } +} From 978eb419b240b0250a444e99223b27ad4927573d Mon Sep 17 00:00:00 2001 From: F4lc0131 Date: Tue, 5 Jan 2021 13:54:14 +0100 Subject: [PATCH 012/314] Add files via upload --- .../System/ConsoleImpl.cs | 1470 +++++++++-------- 1 file changed, 749 insertions(+), 721 deletions(-) diff --git a/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs b/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs index 8f9cf2ee93..a13cdb68dc 100644 --- a/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs +++ b/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs @@ -1,733 +1,761 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Cosmos.System; -using IL2CPU.API; -using IL2CPU.API.Attribs; - -namespace Cosmos.System_Plugs.System -{ - [Plug(Target = typeof (global::System.Console))] - public static class ConsoleImpl - { - private static ConsoleColor mForeground = ConsoleColor.White; - private static ConsoleColor mBackground = ConsoleColor.Black; - private static Encoding ConsoleInputEncoding = Encoding.ASCII; - private static Encoding ConsoleOutputEncoding = Encoding.ASCII; - - private static readonly Cosmos.System.Console mFallbackConsole = new Cosmos.System.Console(null); - - private static Cosmos.System.Console GetConsole() - { - return mFallbackConsole; - } - - public static ConsoleColor get_BackgroundColor() - { - return mBackground; - } - - public static void set_BackgroundColor(ConsoleColor value) - { - mBackground = value; - //Cosmos.HAL.Global.TextScreen.SetColors(mForeground, mBackground); - if (GetConsole() != null) GetConsole().Background = value; - } - - public static int get_BufferHeight() - { - WriteLine("Not implemented: get_BufferHeight"); - return -1; - } - - public static void set_BufferHeight(int aHeight) - { - WriteLine("Not implemented: set_BufferHeight"); - } - - public static int get_BufferWidth() - { - WriteLine("Not implemented: get_BufferWidth"); - return -1; - } - - public static void set_BufferWidth(int aWidth) - { - WriteLine("Not implemented: set_BufferWidth"); - } - - public static bool get_CapsLock() - { - return Global.CapsLock; - } - - public static int get_CursorLeft() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return 0; - } - return GetConsole().X; - } - - public static void set_CursorLeft(int x) - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; - } - - if (x < get_WindowWidth()) - { - xConsole.X = x; - } - else - { - WriteLine("x must be lower than the console width!"); - } - } - - public static int get_CursorSize() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return 0; - } - return xConsole.CursorSize; - } - - public static void set_CursorSize(int aSize) - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; - } - xConsole.CursorSize = aSize; - } - - public static int get_CursorTop() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return 0; - } - return GetConsole().Y; - } - - public static void set_CursorTop(int y) - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; - } - - if (y < get_WindowHeight()) - { - xConsole.Y = y; - } - else - { - WriteLine("y must be lower than the console height!"); - } - } - - public static bool get_CursorVisible() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - return false; - } - return GetConsole().CursorVisible; - } - - public static void set_CursorVisible(bool value) - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; - } - xConsole.CursorVisible = value; - } - - - //public static TextWriter get_Error() { - // WriteLine("Not implemented: get_Error"); - // return null; - //} - - public static ConsoleColor get_ForegroundColor() - { - return mForeground; - } - - public static void set_ForegroundColor(ConsoleColor value) - { - mForeground = value; - //Cosmos.HAL.Global.TextScreen.SetColors(mForeground, mBackground); - if (GetConsole() != null) GetConsole().Foreground = value; - } - - //public static TextReader get_In() - //{ - // WriteLine("Not implemented: get_In"); - // return null; - //} - - public static Encoding get_InputEncoding() - { - return ConsoleInputEncoding; - } - - public static void set_InputEncoding(Encoding value) - { - ConsoleInputEncoding = value; - } - - public static Encoding get_OutputEncoding() - { - return ConsoleOutputEncoding; - } - - - public static void set_OutputEncoding(Encoding value) - { - ConsoleOutputEncoding = value; - } - - public static bool get_KeyAvailable() - { - return KeyboardManager.KeyAvailable; - } - - public static int get_LargestWindowHeight() - { - WriteLine("Not implemented: get_LargestWindowHeight"); - return -1; - } - - public static int get_LargestWindowWidth() - { - WriteLine("Not implemented: get_LargestWindowWidth"); - return -1; - } - - public static bool get_NumberLock() - { - return Global.NumLock; - } - - //public static TextWriter get_Out() { - // WriteLine("Not implemented: get_Out"); - // return null; - //} - - public static string get_Title() - { - WriteLine("Not implemented: get_Title"); - return string.Empty; - } - - public static void set_Title(string value) - { - WriteLine("Not implemented: set_Title"); - } - - public static bool get_TreatControlCAsInput() - { - WriteLine("Not implemented: get_TreatControlCAsInput"); - return false; - } - - public static void set_TreatControlCAsInput(bool value) - { - WriteLine("Not implemented: set_TreatControlCAsInput"); - } - - public static int get_WindowHeight() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return 25; - } - return GetConsole().Rows; - } - - public static void set_WindowHeight(int value) - { - WriteLine("Not implemented: set_WindowHeight"); - } - - public static int get_WindowLeft() - { - WriteLine("Not implemented: get_WindowLeft"); - return -1; - } - - public static void set_WindowLeft(int value) - { - WriteLine("Not implemented: set_WindowLeft"); - } - - public static int get_WindowTop() - { - WriteLine("Not implemented: get_WindowTop"); - return -1; - } - - public static void set_WindowTop(int value) - { - WriteLine("Not implemented: set_WindowTop"); - } - - public static int get_WindowWidth() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return 85; - } - return GetConsole().Cols; - } - - public static void set_WindowWidth(int value) - { - WriteLine("Not implemented: set_WindowWidth"); - } - - /// - /// The ArgumentOutOfRangeException check is now done at driver level in PCSpeaker - is it still needed here? - /// - /// - /// - public static void Beep(int aFrequency, int aDuration) - { - if (aFrequency < 37 || aFrequency > 32767) - { - throw new ArgumentOutOfRangeException("Frequency must be between 37 and 32767Hz"); - } - - if (aDuration <= 0) - { - throw new ArgumentOutOfRangeException("Duration must be more than 0"); - } - - PCSpeaker.Beep((uint) aFrequency, (uint) aDuration); - } - - /// - /// Beep() is pure CIL - /// Default implementation beeps for 200 milliseconds at 800 hertz - /// In Cosmos, these are Cosmos.System.Duration.Default and Cosmos.System.Notes.Default respectively, - /// and are used when there are no params - /// https://docs.microsoft.com/en-us/dotnet/api/system.console.beep?view=netcore-2.0 - /// - public static void Beep() - { - PCSpeaker.Beep(); - } - - //TODO: Console uses TextWriter - intercept and plug it instead - public static void Clear() - { - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; - } - GetConsole().Clear(); - } - - // MoveBufferArea(int, int, int, int, int, int) is pure CIL - - public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, - int targetLeft, int targetTop, Char sourceChar, ConsoleColor sourceForeColor, ConsoleColor sourceBackColor) - { - WriteLine("Not implemented: MoveBufferArea"); - } - - //public static Stream OpenStandardError() { - // WriteLine("Not implemented: OpenStandardError"); - //} - - //public static Stream OpenStandardError(int bufferSize) { - // WriteLine("Not implemented: OpenStandardError"); - //} - - //public static Stream OpenStandardInput(int bufferSize) { - // WriteLine("Not implemented: OpenStandardInput"); - //} - - //public static Stream OpenStandardInput() { - // WriteLine("Not implemented: OpenStandardInput"); - //} - - //public static Stream OpenStandardOutput(int bufferSize) { - // WriteLine("Not implemented: OpenStandardOutput"); - //} - - //public static Stream OpenStandardOutput() { - // WriteLine("Not implemented: OpenStandardOutput"); - //} - - public static int Read() - { - // TODO special cases, if needed, that returns -1 - KeyEvent xResult; - - if (KeyboardManager.TryReadKey(out xResult)) - { - return xResult.KeyChar; - } - else - { - return -1; - } - } - - public static ConsoleKeyInfo ReadKey() - { - return ReadKey(false); - } - - // ReadKey() pure CIL - - public static ConsoleKeyInfo ReadKey(bool intercept) - { - var key = KeyboardManager.ReadKey(); - if (intercept == false && key.KeyChar != '\0') - { - Write(key.KeyChar); - } - - //TODO: Plug HasFlag and use the next 3 lines instead of the 3 following lines - - //bool xShift = key.Modifiers.HasFlag(ConsoleModifiers.Shift); - //bool xAlt = key.Modifiers.HasFlag(ConsoleModifiers.Alt); - //bool xControl = key.Modifiers.HasFlag(ConsoleModifiers.Control); - - bool xShift = (key.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift; - bool xAlt = (key.Modifiers & ConsoleModifiers.Alt) == ConsoleModifiers.Alt; - bool xControl = (key.Modifiers & ConsoleModifiers.Control) == ConsoleModifiers.Control; - - return new ConsoleKeyInfo(key.KeyChar, key.Key.ToConsoleKey(), xShift, xAlt, xControl); - } - - private static Core.Processing.ProcessContext.Context LockContext = null; - private static List queue = new List(); +using System; +using System.Collections.Generic; +using System.Text; +using Cosmos.System; +using IL2CPU.API; +using IL2CPU.API.Attribs; + +namespace Cosmos.System_Plugs.System +{ + [Plug(Target = typeof (global::System.Console))] + public static class ConsoleImpl + { + private static ConsoleColor mForeground = ConsoleColor.White; + private static ConsoleColor mBackground = ConsoleColor.Black; + private static Encoding ConsoleInputEncoding = Encoding.ASCII; + private static Encoding ConsoleOutputEncoding = Encoding.ASCII; + + private static readonly Cosmos.System.Console mFallbackConsole = new Cosmos.System.Console(null); + + private static Cosmos.System.Console GetConsole() + { + return mFallbackConsole; + } + + public static ConsoleColor get_BackgroundColor() + { + return mBackground; + } + + public static void set_BackgroundColor(ConsoleColor value) + { + mBackground = value; + //Cosmos.HAL.Global.TextScreen.SetColors(mForeground, mBackground); + if (GetConsole() != null) GetConsole().Background = value; + } + + public static int get_BufferHeight() + { + WriteLine("Not implemented: get_BufferHeight"); + return -1; + } + + public static void set_BufferHeight(int aHeight) + { + WriteLine("Not implemented: set_BufferHeight"); + } + + public static int get_BufferWidth() + { + WriteLine("Not implemented: get_BufferWidth"); + return -1; + } + + public static void set_BufferWidth(int aWidth) + { + WriteLine("Not implemented: set_BufferWidth"); + } + + public static bool get_CapsLock() + { + return Global.CapsLock; + } + + public static int get_CursorLeft() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return 0; + } + return GetConsole().X; + } + + public static void set_CursorLeft(int x) + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + + if (x < get_WindowWidth()) + { + xConsole.X = x; + } + else + { + WriteLine("x must be lower than the console width!"); + } + } + + public static int get_CursorSize() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return 0; + } + return xConsole.CursorSize; + } + + public static void set_CursorSize(int aSize) + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + xConsole.CursorSize = aSize; + } + + public static int get_CursorTop() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return 0; + } + return GetConsole().Y; + } + + public static void set_CursorTop(int y) + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + + if (y < get_WindowHeight()) + { + xConsole.Y = y; + } + else + { + WriteLine("y must be lower than the console height!"); + } + } + + public static bool get_CursorVisible() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + return false; + } + return GetConsole().CursorVisible; + } + + public static void set_CursorVisible(bool value) + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + xConsole.CursorVisible = value; + } + + + //public static TextWriter get_Error() { + // WriteLine("Not implemented: get_Error"); + // return null; + //} + + public static ConsoleColor get_ForegroundColor() + { + return mForeground; + } + + public static void set_ForegroundColor(ConsoleColor value) + { + mForeground = value; + //Cosmos.HAL.Global.TextScreen.SetColors(mForeground, mBackground); + if (GetConsole() != null) GetConsole().Foreground = value; + } + + //public static TextReader get_In() + //{ + // WriteLine("Not implemented: get_In"); + // return null; + //} + + public static Encoding get_InputEncoding() + { + return ConsoleInputEncoding; + } + + public static void set_InputEncoding(Encoding value) + { + ConsoleInputEncoding = value; + } + + public static Encoding get_OutputEncoding() + { + return ConsoleOutputEncoding; + } + + + public static void set_OutputEncoding(Encoding value) + { + ConsoleOutputEncoding = value; + } + + public static bool get_KeyAvailable() + { + return KeyboardManager.KeyAvailable; + } + + public static int get_LargestWindowHeight() + { + WriteLine("Not implemented: get_LargestWindowHeight"); + return -1; + } + + public static int get_LargestWindowWidth() + { + WriteLine("Not implemented: get_LargestWindowWidth"); + return -1; + } + + public static bool get_NumberLock() + { + return Global.NumLock; + } + + //public static TextWriter get_Out() { + // WriteLine("Not implemented: get_Out"); + // return null; + //} + + public static string get_Title() + { + WriteLine("Not implemented: get_Title"); + return string.Empty; + } + + public static void set_Title(string value) + { + WriteLine("Not implemented: set_Title"); + } + + public static bool get_TreatControlCAsInput() + { + WriteLine("Not implemented: get_TreatControlCAsInput"); + return false; + } + + public static void set_TreatControlCAsInput(bool value) + { + WriteLine("Not implemented: set_TreatControlCAsInput"); + } + + public static int get_WindowHeight() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return 25; + } + return GetConsole().Rows; + } + + public static void set_WindowHeight(int value) + { + WriteLine("Not implemented: set_WindowHeight"); + } + + public static int get_WindowLeft() + { + WriteLine("Not implemented: get_WindowLeft"); + return -1; + } + + public static void set_WindowLeft(int value) + { + WriteLine("Not implemented: set_WindowLeft"); + } + + public static int get_WindowTop() + { + WriteLine("Not implemented: get_WindowTop"); + return -1; + } + + public static void set_WindowTop(int value) + { + WriteLine("Not implemented: set_WindowTop"); + } + + public static int get_WindowWidth() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return 85; + } + return GetConsole().Cols; + } + + public static void set_WindowWidth(int value) + { + WriteLine("Not implemented: set_WindowWidth"); + } + + /// + /// The ArgumentOutOfRangeException check is now done at driver level in PCSpeaker - is it still needed here? + /// + /// + /// + public static void Beep(int aFrequency, int aDuration) + { + if (aFrequency < 37 || aFrequency > 32767) + { + throw new ArgumentOutOfRangeException("Frequency must be between 37 and 32767Hz"); + } + + if (aDuration <= 0) + { + throw new ArgumentOutOfRangeException("Duration must be more than 0"); + } + + PCSpeaker.Beep((uint) aFrequency, (uint) aDuration); + } + + /// + /// Beep() is pure CIL + /// Default implementation beeps for 200 milliseconds at 800 hertz + /// In Cosmos, these are Cosmos.System.Duration.Default and Cosmos.System.Notes.Default respectively, + /// and are used when there are no params + /// https://docs.microsoft.com/en-us/dotnet/api/system.console.beep?view=netcore-2.0 + /// + public static void Beep() + { + PCSpeaker.Beep(); + } + + //TODO: Console uses TextWriter - intercept and plug it instead + public static void Clear() + { + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + GetConsole().Clear(); + } + + // MoveBufferArea(int, int, int, int, int, int) is pure CIL + + public static void MoveBufferArea(int sourceLeft, int sourceTop, int sourceWidth, int sourceHeight, + int targetLeft, int targetTop, Char sourceChar, ConsoleColor sourceForeColor, ConsoleColor sourceBackColor) + { + WriteLine("Not implemented: MoveBufferArea"); + } + + //public static Stream OpenStandardError() { + // WriteLine("Not implemented: OpenStandardError"); + //} + + //public static Stream OpenStandardError(int bufferSize) { + // WriteLine("Not implemented: OpenStandardError"); + //} + + //public static Stream OpenStandardInput(int bufferSize) { + // WriteLine("Not implemented: OpenStandardInput"); + //} + + //public static Stream OpenStandardInput() { + // WriteLine("Not implemented: OpenStandardInput"); + //} + + //public static Stream OpenStandardOutput(int bufferSize) { + // WriteLine("Not implemented: OpenStandardOutput"); + //} + + //public static Stream OpenStandardOutput() { + // WriteLine("Not implemented: OpenStandardOutput"); + //} + + public static int Read() + { + // TODO special cases, if needed, that returns -1 + KeyEvent xResult; + + if (KeyboardManager.TryReadKey(out xResult)) + { + return xResult.KeyChar; + } + else + { + return -1; + } + } + + public static ConsoleKeyInfo ReadKey() + { + return ReadKey(false); + } + + // ReadKey() pure CIL + + public static ConsoleKeyInfo ReadKey(bool intercept) + { + var key = KeyboardManager.ReadKey(); + if (intercept == false && key.KeyChar != '\0') + { + Write(key.KeyChar); + } + + //TODO: Plug HasFlag and use the next 3 lines instead of the 3 following lines + + //bool xShift = key.Modifiers.HasFlag(ConsoleModifiers.Shift); + //bool xAlt = key.Modifiers.HasFlag(ConsoleModifiers.Alt); + //bool xControl = key.Modifiers.HasFlag(ConsoleModifiers.Control); + + bool xShift = (key.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift; + bool xAlt = (key.Modifiers & ConsoleModifiers.Alt) == ConsoleModifiers.Alt; + bool xControl = (key.Modifiers & ConsoleModifiers.Control) == ConsoleModifiers.Control; + + return new ConsoleKeyInfo(key.KeyChar, key.Key.ToConsoleKey(), xShift, xAlt, xControl); + } + + private static LockSystem.Lock _lock = LockSystem.DefineLock("Console"); + private static List chars = new List(32); + private static List old = null; - public static String ReadLine() - { - if (LockContext == null) LockContext = Core.Processing.ProcessContext.m_CurrentContext; //if nobody locked the Console, just lock it - else if (LockContext != Core.Processing.ProcessContext.m_CurrentContext) - { - queue.Add(Core.Processing.ProcessContext.m_CurrentContext); - while (LockContext != Core.Processing.ProcessContext.m_CurrentContext) ; - } - var xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return null; - } - List chars = new List(32); - KeyEvent current; - int currentCount = 0; - - while ((current = KeyboardManager.ReadKey()).Key != ConsoleKeyEx.Enter) + public static String ReadLine() + { + if (_lock.LockContext == null) _lock.LockContext = Core.Processing.ProcessContext.m_CurrentContext; //if nobody locked the Console, just lock it + else if (_lock.LockContext != Core.Processing.ProcessContext.m_CurrentContext) { - if (current.Key == ConsoleKeyEx.NumEnter) break; - //Check for "special" keys - if (current.Key == ConsoleKeyEx.Backspace) // Backspace - { - if (currentCount > 0) - { - int curCharTemp = GetConsole().X; - chars.RemoveAt(currentCount - 1); - GetConsole().X = GetConsole().X - 1; - - //Move characters to the left - for (int x = currentCount - 1; x < chars.Count; x++) - { - Write(chars[x]); - } - - Write(' '); - - GetConsole().X = curCharTemp - 1; - - currentCount--; - } - continue; - } - else if (current.Key == ConsoleKeyEx.LeftArrow) - { - if (currentCount > 0) - { - GetConsole().X = GetConsole().X - 1; - currentCount--; - } - continue; - } - else if (current.Key == ConsoleKeyEx.RightArrow) - { - if (currentCount < chars.Count) - { - GetConsole().X = GetConsole().X + 1; - currentCount++; - } - continue; - } - - if (current.KeyChar == '\0') continue; - - //Write the character to the screen - if (currentCount == chars.Count) - { - chars.Add(current.KeyChar); - Write(current.KeyChar); - currentCount++; - } - else - { - //Insert the new character in the correct location - //For some reason, List.Insert() doesn't work properly - //so the character has to be inserted manually - List temp = new List(); - - for (int x = 0; x < chars.Count; x++) - { - if (x == currentCount) - { - temp.Add(current.KeyChar); - } - - temp.Add(chars[x]); - } - - chars = temp; - - //Shift the characters to the right - for (int x = currentCount; x < chars.Count; x++) - { - Write(chars[x]); - } - - GetConsole().X -= (chars.Count - currentCount) - 1; - currentCount++; - } + _lock.queue.Add(Core.Processing.ProcessContext.m_CurrentContext); + while (_lock.LockContext != Core.Processing.ProcessContext.m_CurrentContext) ; } + LockSystem.definedLocks["Console"] = _lock; + chars = new List(32); + var xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return null; + } + KeyEvent current; + int currentCount = 0; + + while ((current = KeyboardManager.ReadKey()).Key != ConsoleKeyEx.Enter) + { + if (current.Key == ConsoleKeyEx.NumEnter) break; + //Check for "special" keys + if (current.Key == ConsoleKeyEx.Backspace) // Backspace + { + if (currentCount > 0) + { + int curCharTemp = GetConsole().X; + chars.RemoveAt(currentCount - 1); + GetConsole().X = GetConsole().X - 1; + + //Move characters to the left + for (int x = currentCount - 1; x < chars.Count; x++) + { + Write(chars[x]); + } + + Write(' '); + + GetConsole().X = curCharTemp - 1; + + currentCount--; + } + continue; + } + else if (current.Key == ConsoleKeyEx.LeftArrow) + { + if (currentCount > 0) + { + GetConsole().X = GetConsole().X - 1; + currentCount--; + } + continue; + } + else if (current.Key == ConsoleKeyEx.RightArrow) + { + if (currentCount < chars.Count) + { + GetConsole().X = GetConsole().X + 1; + currentCount++; + } + continue; + } + + if (current.KeyChar == '\0') continue; + + //Write the character to the screen + if (currentCount == chars.Count) + { + chars.Add(current.KeyChar); + Write(current.KeyChar); + currentCount++; + } + else + { + //Insert the new character in the correct location + //For some reason, List.Insert() doesn't work properly + //so the character has to be inserted manually + List temp = new List(); + + for (int x = 0; x < chars.Count; x++) + { + if (x == currentCount) + { + temp.Add(current.KeyChar); + } + + temp.Add(chars[x]); + } + + chars = temp; + + //Shift the characters to the right + for (int x = currentCount; x < chars.Count; x++) + { + Write(chars[x]); + } + + GetConsole().X -= (chars.Count - currentCount) - 1; + currentCount++; + } + } WriteLine(); - char[] final = chars.ToArray(); - //if there's some process queued, we just set the first as the main and queue the otherones - if (queue.Count > 0) + while (_lock.LockContext != Core.Processing.ProcessContext.m_CurrentContext) ; //let's wait until we go back to the lock thread + + char[] final = chars.ToArray(); + //if there's some process queued, we just set the first as the main and queue the other ones + if (_lock.queue.Count > 0) { - Cosmos.HAL.Global.mDebugger.Send($"Removing {queue[0].name} from Queue and locking console to it"); - LockContext = queue[0]; - old = queue; - queue = new List(); + HAL.Global.mDebugger.Send($"Removing {_lock.queue[0].name} from Queue and locking console to it"); + _lock.LockContext = _lock.queue[0]; + old = _lock.queue; + _lock.queue = new List(); foreach (Core.Processing.ProcessContext.Context context in old) { - if (context != LockContext) - queue.Add(context); + if (context != _lock.LockContext) + _lock.queue.Add(context); } - } - return new string(final); - } - - public static void ResetColor() - { - set_BackgroundColor(ConsoleColor.Black); - set_ForegroundColor(ConsoleColor.White); - } - - public static void SetBufferSize(int width, int height) - { - WriteLine("Not implemented: SetBufferSize"); - } - - public static void SetCursorPosition(int left, int top) - { - set_CursorLeft(left); - set_CursorTop(top); - } - - //public static void SetError(TextWriter newError) { - // WriteLine("Not implemented: SetError"); - //} - - //public static void SetIn(TextReader newIn) { - // WriteLine("Not implemented: SetIn"); - //} - - //public static void SetOut(TextWriter newOut) { - // WriteLine("Not implemented: SetOut"); - //} - - public static void SetWindowPosition(int left, int top) - { - WriteLine("Not implemented: SetWindowPosition"); - } - - public static void SetWindowSize(int width, int height) - { - WriteLine("Not implemented: SetWindowSize"); - } - - #region Write - - public static void Write(bool aBool) - { - Write(aBool.ToString()); - } - - /* - * A .Net character can be effectevily more can one byte so calling the low level Console.Write() will be wrong as - * it accepts only bytes, we need to convert it using the specified OutputEncoding but to do this we have to convert - * it ToString first - */ - public static void Write(char aChar) => Write(aChar.ToString()); - - public static void Write(char[] aBuffer) => Write(aBuffer, 0, aBuffer.Length); - - /* Decimal type is not working yet... */ - //public static void Write(decimal aDecimal) => Write(aDecimal.ToString()); - - public static void Write(double aDouble) => Write(aDouble.ToString()); - - public static void Write(float aFloat) => Write(aFloat.ToString()); - - public static void Write(int aInt) => Write(aInt.ToString()); - - public static void Write(long aLong) => Write(aLong.ToString()); - - /* Correct behaviour printing null should not throw NRE or do nothing but should print an empty string */ - public static void Write(object value) => Write((value ?? String.Empty)); - - public static void Write(string aText) - { - var xConsole = GetConsole(); - if (xConsole == null) + } + return new string(final); + } + + public static void ResetColor() + { + set_BackgroundColor(ConsoleColor.Black); + set_ForegroundColor(ConsoleColor.White); + } + + public static void SetBufferSize(int width, int height) + { + WriteLine("Not implemented: SetBufferSize"); + } + + public static void SetCursorPosition(int left, int top) + { + set_CursorLeft(left); + set_CursorTop(top); + } + + //public static void SetError(TextWriter newError) { + // WriteLine("Not implemented: SetError"); + //} + + //public static void SetIn(TextReader newIn) { + // WriteLine("Not implemented: SetIn"); + //} + + //public static void SetOut(TextWriter newOut) { + // WriteLine("Not implemented: SetOut"); + //} + + public static void SetWindowPosition(int left, int top) + { + WriteLine("Not implemented: SetWindowPosition"); + } + + public static void SetWindowSize(int width, int height) + { + WriteLine("Not implemented: SetWindowSize"); + } + + #region Write + + public static void Write(bool aBool) + { + Write(aBool.ToString()); + } + + /* + * A .Net character can be effectevily more can one byte so calling the low level Console.Write() will be wrong as + * it accepts only bytes, we need to convert it using the specified OutputEncoding but to do this we have to convert + * it ToString first + */ + public static void Write(char aChar) => Write(aChar.ToString()); + + public static void Write(char[] aBuffer) => Write(aBuffer, 0, aBuffer.Length); + + /* Decimal type is not working yet... */ + //public static void Write(decimal aDecimal) => Write(aDecimal.ToString()); + + public static void Write(double aDouble) => Write(aDouble.ToString()); + + public static void Write(float aFloat) => Write(aFloat.ToString()); + + public static void Write(int aInt) => Write(aInt.ToString()); + + public static void Write(long aLong) => Write(aLong.ToString()); + + /* Correct behaviour printing null should not throw NRE or do nothing but should print an empty string */ + public static void Write(object value) => Write((value ?? String.Empty)); + + private static Cosmos.System.Console xConsole = null; + + private static List WOld = null; + private static LockSystem.Lock _Wlock = LockSystem.DefineLock("Console.Write"); + public static void Write(string aText) + { + if (_Wlock.LockContext == null) _Wlock.LockContext = Core.Processing.ProcessContext.m_CurrentContext; //if nobody locked the Console, just lock it + else if (_Wlock.LockContext != Core.Processing.ProcessContext.m_CurrentContext) { - // for now: - return; + _Wlock.queue.Add(Core.Processing.ProcessContext.m_CurrentContext); + while (_Wlock.LockContext != Core.Processing.ProcessContext.m_CurrentContext) ; } - - byte[] aTextEncoded = ConsoleOutputEncoding.GetBytes(aText); - GetConsole().Write(aTextEncoded); - } - - public static void Write(uint aInt) => Write(aInt.ToString()); - - public static void Write(ulong aLong) => Write(aLong.ToString()); - - public static void Write(string format, object arg0) => Write(String.Format(format, arg0)); - - public static void Write(string format, object arg0, object arg1) => Write(String.Format(format, arg0, arg1)); - - public static void Write(string format, object arg0, object arg1, object arg2) => Write(String.Format(format, arg0, arg1, arg2)); - - public static void Write(string format, object arg0, object arg1, object arg2, object arg3) => Write(String.Format(format, arg0, arg1, arg2, arg3)); - - public static void Write(string format, params object[] arg) => Write(String.Format(format, arg)); - - public static void Write(char[] aBuffer, int aIndex, int aCount) - { - if (aBuffer == null) + LockSystem.definedLocks["Console"] = _Wlock; + xConsole = GetConsole(); + if (xConsole == null) + { + // for now: + return; + } + + byte[] aTextEncoded = ConsoleOutputEncoding.GetBytes(aText); + GetConsole().Write(aTextEncoded); + //if there's some process queued, we just set the first as the main and queue the other ones + if (_Wlock.queue.Count > 0) { - throw new ArgumentNullException("aBuffer"); - } - if (aIndex < 0) - { - throw new ArgumentOutOfRangeException("aIndex"); - } - if (aCount < 0) - { - throw new ArgumentOutOfRangeException("aCount"); - } - if ((aBuffer.Length - aIndex) < aCount) - { - throw new ArgumentException(); - } - for (int i = 0; i < aCount; i++) - { - Write(aBuffer[aIndex + i]); - } - } - - //You'd expect this to be on System.Console wouldn't you? Well, it ain't so we just rely on Write(object value) - //public static void Write(byte aByte) { - // Write(aByte.ToString()); - //} - -#endregion - -#region WriteLine - - public static void WriteLine() => Write(Environment.NewLine); - - public static void WriteLine(bool aBool) => WriteLine(aBool.ToString()); - - public static void WriteLine(char aChar) => WriteLine(aChar.ToString()); - - public static void WriteLine(char[] aBuffer) => WriteLine(new String(aBuffer)); - - /* Decimal type is not working yet... */ - //public static void WriteLine(decimal aDecimal) => WriteLine(aDecimal.ToString()); - - public static void WriteLine(double aDouble) => WriteLine(aDouble.ToString()); - - public static void WriteLine(float aFloat) => WriteLine(aFloat.ToString()); - - public static void WriteLine(int aInt) => WriteLine(aInt.ToString()); - - public static void WriteLine(long aLong) => WriteLine(aLong.ToString()); - - /* Correct behaviour printing null should not throw NRE or do nothing but should print an empty line */ - public static void WriteLine(object value) => Write((value ?? String.Empty) + Environment.NewLine); - - public static void WriteLine(string aText) => Write(aText + Environment.NewLine); - - public static void WriteLine(uint aInt) => WriteLine(aInt.ToString()); - - public static void WriteLine(ulong aLong) => WriteLine(aLong.ToString()); - - public static void WriteLine(string format, object arg0) => WriteLine(String.Format(format, arg0)); - - public static void WriteLine(string format, object arg0, object arg1) => WriteLine(String.Format(format, arg0, arg1)); - - public static void WriteLine(string format, object arg0, object arg1, object arg2) => WriteLine(String.Format(format, arg0, arg1, arg2)); - - public static void WriteLine(string format, object arg0, object arg1, object arg2, object arg3) => WriteLine(String.Format(format, arg0, arg1, arg2, arg3)); - - public static void WriteLine(string format, params object[] arg) => WriteLine(String.Format(format, arg)); - - public static void WriteLine(char[] aBuffer, int aIndex, int aCount) - { - Write(aBuffer, aIndex, aCount); - WriteLine(); - } - -#endregion - - } -} + HAL.Global.mDebugger.Send($"Removing {_Wlock.queue[0].name} from Queue and locking console to it"); + _Wlock.LockContext = _Wlock.queue[0]; + WOld = _Wlock.queue; + _Wlock.queue = new List(); + foreach (Core.Processing.ProcessContext.Context context in WOld) + { + if (context != _Wlock.LockContext) + _Wlock.queue.Add(context); + } + } + } + + public static void Write(uint aInt) => Write(aInt.ToString()); + + public static void Write(ulong aLong) => Write(aLong.ToString()); + + public static void Write(string format, object arg0) => Write(String.Format(format, arg0)); + + public static void Write(string format, object arg0, object arg1) => Write(String.Format(format, arg0, arg1)); + + public static void Write(string format, object arg0, object arg1, object arg2) => Write(String.Format(format, arg0, arg1, arg2)); + + public static void Write(string format, object arg0, object arg1, object arg2, object arg3) => Write(String.Format(format, arg0, arg1, arg2, arg3)); + + public static void Write(string format, params object[] arg) => Write(String.Format(format, arg)); + + public static void Write(char[] aBuffer, int aIndex, int aCount) + { + if (aBuffer == null) + { + throw new ArgumentNullException("aBuffer"); + } + if (aIndex < 0) + { + throw new ArgumentOutOfRangeException("aIndex"); + } + if (aCount < 0) + { + throw new ArgumentOutOfRangeException("aCount"); + } + if ((aBuffer.Length - aIndex) < aCount) + { + throw new ArgumentException(); + } + for (int i = 0; i < aCount; i++) + { + Write(aBuffer[aIndex + i]); + } + } + + //You'd expect this to be on System.Console wouldn't you? Well, it ain't so we just rely on Write(object value) + //public static void Write(byte aByte) { + // Write(aByte.ToString()); + //} + +#endregion + +#region WriteLine + + public static void WriteLine() => Write(Environment.NewLine); + + public static void WriteLine(bool aBool) => WriteLine(aBool.ToString()); + + public static void WriteLine(char aChar) => WriteLine(aChar.ToString()); + + public static void WriteLine(char[] aBuffer) => WriteLine(new String(aBuffer)); + + /* Decimal type is not working yet... */ + //public static void WriteLine(decimal aDecimal) => WriteLine(aDecimal.ToString()); + + public static void WriteLine(double aDouble) => WriteLine(aDouble.ToString()); + + public static void WriteLine(float aFloat) => WriteLine(aFloat.ToString()); + + public static void WriteLine(int aInt) => WriteLine(aInt.ToString()); + + public static void WriteLine(long aLong) => WriteLine(aLong.ToString()); + + /* Correct behaviour printing null should not throw NRE or do nothing but should print an empty line */ + public static void WriteLine(object value) => Write((value ?? String.Empty) + Environment.NewLine); + + public static void WriteLine(string aText) => Write(aText + Environment.NewLine); + + public static void WriteLine(uint aInt) => WriteLine(aInt.ToString()); + + public static void WriteLine(ulong aLong) => WriteLine(aLong.ToString()); + + public static void WriteLine(string format, object arg0) => WriteLine(String.Format(format, arg0)); + + public static void WriteLine(string format, object arg0, object arg1) => WriteLine(String.Format(format, arg0, arg1)); + + public static void WriteLine(string format, object arg0, object arg1, object arg2) => WriteLine(String.Format(format, arg0, arg1, arg2)); + + public static void WriteLine(string format, object arg0, object arg1, object arg2, object arg3) => WriteLine(String.Format(format, arg0, arg1, arg2, arg3)); + + public static void WriteLine(string format, params object[] arg) => WriteLine(String.Format(format, arg)); + + public static void WriteLine(char[] aBuffer, int aIndex, int aCount) + { + Write(aBuffer, aIndex, aCount); + WriteLine(); + } + +#endregion + + } +} From 4af1b27e115264cdc90c7eb1b1dcbfb2cc84da88 Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Tue, 5 Jan 2021 11:21:29 -0500 Subject: [PATCH 013/314] Show message on what exactly is missing Show message on what exactly is missing --- .../Dependencies/InnoSetupDependency.cs | 5 +++ .../Dependencies/ReposDependency.cs | 21 +++++++++++ .../Dependencies/VisualStudioDependency.cs | 4 +++ .../VisualStudioWorkloadsDependency.cs | 36 +++++++++++++++++++ source/Cosmos.Build.Builder/IDependency.cs | 1 + .../ViewModels/MainWindowViewModel.cs | 4 +-- 6 files changed, 69 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs b/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs index c9d70e21c3..3580085afb 100644 --- a/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs @@ -16,6 +16,11 @@ internal class InnoSetupDependency : IDependency public string Name => "Inno Setup"; public bool ShouldInstallByDefault => true; + public string OtherDependencysThatAreMissing + { + get { return Name; } + } + private readonly IInnoSetupService _innoSetupService; public InnoSetupDependency(IInnoSetupService innoSetupService) diff --git a/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs b/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs index f80aabdd3b..0438187058 100644 --- a/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs @@ -15,6 +15,27 @@ internal class ReposDependency : IDependency public string Name => "Repos: IL2CPU, XSharp and Common"; public bool ShouldInstallByDefault => true; + public string OtherDependencysThatAreMissing + { + get + { + string result = ""; + if (!Directory.Exists(Path.GetFullPath(Path.Combine(_cosmosDir, "..", "IL2CPU")))) + { + result += "IL2CPU Repo, "; + } + if (!Directory.Exists(Path.GetFullPath(Path.Combine(_cosmosDir, "..", "XSharp")))) + { + result += "XSharp Repo, "; + } + if (!Directory.Exists(Path.GetFullPath(Path.Combine(_cosmosDir, "..", "Common")))) + { + result += "Common Repo, "; + } + return result; + } + } + private readonly string _cosmosDir; private readonly IEnumerable _repos; diff --git a/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs b/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs index 7e6df6d116..f9f6304b74 100644 --- a/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs @@ -11,6 +11,10 @@ internal class VisualStudioDependency : IDependency private static readonly Version MinimumVsVersion = new Version(15, 9); public bool ShouldInstallByDefault => true; public string Name => $"Visual Studio {MinimumVsVersion.Major}.{MinimumVsVersion.Minor}+"; + public string OtherDependencysThatAreMissing + { + get { return Name+"+"; } + } private readonly ISetupInstance2 _visualStudioInstance; diff --git a/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs b/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs index dd9423d86b..1b1fb439b8 100644 --- a/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs @@ -20,6 +20,30 @@ internal class VisualStudioWorkloadsDependency : IDependency public bool ShouldInstallByDefault => false; public string Name => "Visual Studio Workloads"; + public string OtherDependencysThatAreMissing + { + get + { + var missingPackages = ((string[])RequiredPackages.Clone()).ToList(); + foreach (var item in RequiredPackages) + { + if (IsPackageInstalled(item)) + { + missingPackages.Remove(item); + } + } + + //Add the missing packages together + string missingPackages_proper = ""; + foreach (var item in missingPackages) + { + missingPackages_proper += GetProperName(item) + ", "; + } + + return missingPackages_proper; + } + } + private readonly ISetupInstance2 _visualStudioInstance; public VisualStudioWorkloadsDependency(ISetupInstance2 visualStudioInstance) @@ -32,7 +56,19 @@ public Task IsInstalledAsync(CancellationToken cancellationToken) var installedPackages = _visualStudioInstance.GetPackages(); return Task.FromResult(RequiredPackages.All(p => IsPackageInstalled(p))); } + private string GetProperName(string packageId) + { + if (packageId == NetCoreToolsWorkload) + { + return ".NET Core cross-platform development"; + } + else if (packageId == VisualStudioExtensionsWorkload) + { + return "Visual Studio Extension development"; + } + return "Unknown Workload: " + packageId; + } public async Task InstallAsync(CancellationToken cancellationToken) { var vsInstallerPath = Environment.ExpandEnvironmentVariables( diff --git a/source/Cosmos.Build.Builder/IDependency.cs b/source/Cosmos.Build.Builder/IDependency.cs index f53867fb1b..3d6549b84c 100644 --- a/source/Cosmos.Build.Builder/IDependency.cs +++ b/source/Cosmos.Build.Builder/IDependency.cs @@ -8,6 +8,7 @@ internal interface IDependency string Name { get; } bool ShouldInstallByDefault { get; } + string OtherDependencysThatAreMissing { get; } Task IsInstalledAsync(CancellationToken cancellationToken); Task InstallAsync(CancellationToken cancellationToken); } diff --git a/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs b/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs index a1458532b0..fd4d6fd827 100644 --- a/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs +++ b/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs @@ -107,7 +107,7 @@ private async Task BuildAsync() } else { - _logger.LogMessage($"{dependency.Name} not found."); + _logger.LogMessage($"{dependency.Name} not found. Install {dependency.OtherDependencysThatAreMissing}"); if (dependency.ShouldInstallByDefault) { @@ -123,7 +123,7 @@ private async Task BuildAsync() } else { - MessageBox.Show($"{dependency.Name} is not installed. Please install {dependency.Name}"); + MessageBox.Show($"{dependency.Name} is not installed. Please install {dependency.OtherDependencysThatAreMissing}"); _logger.SetError(); _logger.NewSection("Error"); _logger.LogMessage($"{dependency.Name} not found."); From 97eb09659de54ba57df3d959b17c6b05058eb3f3 Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Tue, 5 Jan 2021 11:26:19 -0500 Subject: [PATCH 014/314] Small change removed comma on last package --- source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs b/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs index 0438187058..e2624dad0c 100644 --- a/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs @@ -30,7 +30,7 @@ public string OtherDependencysThatAreMissing } if (!Directory.Exists(Path.GetFullPath(Path.Combine(_cosmosDir, "..", "Common")))) { - result += "Common Repo, "; + result += "Common Repo"; } return result; } From 5d7732fafaf2b457e5ad7a4152fb83b1aff7ab9a Mon Sep 17 00:00:00 2001 From: F4lc0131 Date: Wed, 6 Jan 2021 01:32:18 +0100 Subject: [PATCH 015/314] Adapting to Mutex class as suggested Removing LockSystem that we don't need anymore --- source/Cosmos.System2/LockSystem.cs | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 source/Cosmos.System2/LockSystem.cs diff --git a/source/Cosmos.System2/LockSystem.cs b/source/Cosmos.System2/LockSystem.cs deleted file mode 100644 index b035991f8d..0000000000 --- a/source/Cosmos.System2/LockSystem.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Cosmos.System -{ - public class LockSystem - { - public static Dictionary definedLocks = new Dictionary(); - public class Lock - { - internal Lock() { } - public Core.Processing.ProcessContext.Context LockContext = null; - public List queue = new List(); - } - public static Lock DefineLock(string LockName) - { - definedLocks.Add(LockName, new Lock()); - return definedLocks[LockName]; - } - } -} From 5184a701b839113c8173555d36fe65ca67cd2b90 Mon Sep 17 00:00:00 2001 From: F4lc0131 Date: Wed, 6 Jan 2021 01:33:34 +0100 Subject: [PATCH 016/314] Adapting to Mutex class as suggested Modifying Console.ReadLine and Write to use Mutex instead of LockSystem --- .../System/ConsoleImpl.cs | 71 +++++-------------- 1 file changed, 16 insertions(+), 55 deletions(-) diff --git a/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs b/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs index a13cdb68dc..a36a0e6c06 100644 --- a/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs +++ b/source/Cosmos.System2_Plugs/System/ConsoleImpl.cs @@ -13,7 +13,9 @@ public static class ConsoleImpl private static ConsoleColor mForeground = ConsoleColor.White; private static ConsoleColor mBackground = ConsoleColor.Black; private static Encoding ConsoleInputEncoding = Encoding.ASCII; - private static Encoding ConsoleOutputEncoding = Encoding.ASCII; + private static Encoding ConsoleOutputEncoding = Encoding.ASCII; + private static Core.Processing.Mutex mConsoleGateRead = new Core.Processing.Mutex(); + private static Core.Processing.Mutex mConsoleGateWrite = new Core.Processing.Mutex(); private static readonly Cosmos.System.Console mFallbackConsole = new Cosmos.System.Console(null); @@ -429,21 +431,13 @@ public static ConsoleKeyInfo ReadKey(bool intercept) bool xControl = (key.Modifiers & ConsoleModifiers.Control) == ConsoleModifiers.Control; return new ConsoleKeyInfo(key.KeyChar, key.Key.ToConsoleKey(), xShift, xAlt, xControl); - } - - private static LockSystem.Lock _lock = LockSystem.DefineLock("Console"); - private static List chars = new List(32); - - private static List old = null; + } + + private static List chars = new List(32); public static String ReadLine() { - if (_lock.LockContext == null) _lock.LockContext = Core.Processing.ProcessContext.m_CurrentContext; //if nobody locked the Console, just lock it - else if (_lock.LockContext != Core.Processing.ProcessContext.m_CurrentContext) - { - _lock.queue.Add(Core.Processing.ProcessContext.m_CurrentContext); - while (_lock.LockContext != Core.Processing.ProcessContext.m_CurrentContext) ; - } - LockSystem.definedLocks["Console"] = _lock; + if (mConsoleGateRead != null) + mConsoleGateRead.Lock(); chars = new List(32); var xConsole = GetConsole(); if (xConsole == null) @@ -537,24 +531,11 @@ public static String ReadLine() currentCount++; } } - WriteLine(); - - while (_lock.LockContext != Core.Processing.ProcessContext.m_CurrentContext) ; //let's wait until we go back to the lock thread + WriteLine(); char[] final = chars.ToArray(); - //if there's some process queued, we just set the first as the main and queue the other ones - if (_lock.queue.Count > 0) - { - HAL.Global.mDebugger.Send($"Removing {_lock.queue[0].name} from Queue and locking console to it"); - _lock.LockContext = _lock.queue[0]; - old = _lock.queue; - _lock.queue = new List(); - foreach (Core.Processing.ProcessContext.Context context in old) - { - if (context != _lock.LockContext) - _lock.queue.Add(context); - } - } + if (mConsoleGateRead != null) + mConsoleGateRead.Unlock(); return new string(final); } @@ -628,39 +609,19 @@ public static void Write(bool aBool) public static void Write(object value) => Write((value ?? String.Empty)); private static Cosmos.System.Console xConsole = null; - - private static List WOld = null; - private static LockSystem.Lock _Wlock = LockSystem.DefineLock("Console.Write"); + public static void Write(string aText) { - if (_Wlock.LockContext == null) _Wlock.LockContext = Core.Processing.ProcessContext.m_CurrentContext; //if nobody locked the Console, just lock it - else if (_Wlock.LockContext != Core.Processing.ProcessContext.m_CurrentContext) + if (mConsoleGateWrite != null) { - _Wlock.queue.Add(Core.Processing.ProcessContext.m_CurrentContext); - while (_Wlock.LockContext != Core.Processing.ProcessContext.m_CurrentContext) ; - } - LockSystem.definedLocks["Console"] = _Wlock; - xConsole = GetConsole(); - if (xConsole == null) - { - // for now: - return; + mConsoleGateWrite.Lock(); } - byte[] aTextEncoded = ConsoleOutputEncoding.GetBytes(aText); GetConsole().Write(aTextEncoded); //if there's some process queued, we just set the first as the main and queue the other ones - if (_Wlock.queue.Count > 0) + if (mConsoleGateWrite != null) { - HAL.Global.mDebugger.Send($"Removing {_Wlock.queue[0].name} from Queue and locking console to it"); - _Wlock.LockContext = _Wlock.queue[0]; - WOld = _Wlock.queue; - _Wlock.queue = new List(); - foreach (Core.Processing.ProcessContext.Context context in WOld) - { - if (context != _Wlock.LockContext) - _Wlock.queue.Add(context); - } + mConsoleGateWrite.Unlock(); } } From 96b5ff34bf0dd96eac9f1cb6c2ea2fd7556968e1 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Sat, 9 Jan 2021 13:18:53 +0100 Subject: [PATCH 017/314] Add Aura files --- source/Cosmos.HAL2/Global.cs | 2 + source/Cosmos.HAL2/Network/MACAddress.cs | 23 + source/Cosmos.HAL2/Network/NetworkInit.cs | 57 ++ source/Cosmos.HAL2/NetworkDevice.cs | 27 +- source/Cosmos.System2/Global.cs | 2 +- source/Cosmos.System2/Network/ARP/ARPCache.cs | 16 +- .../Cosmos.System2/Network/ARP/ARPPacket.cs | 9 +- .../{IPv4 => ARP}/ARPPacket_Ethernet.cs | 13 +- .../Network/Config/DNSConfig.cs | 62 +++ .../{IPv4/Config.cs => Config/IPConfig.cs} | 87 ++- .../Network/Config/NetworkConfig.cs | 132 +++++ .../Cosmos.System2/Network/EthernetPacket.cs | 11 +- .../Cosmos.System2/Network/IPV4/ICMPClient.cs | 143 +++++ .../Network/IPV4/UDP/DHCP/DHCPClient.cs | 228 ++++++++ .../Network/IPV4/UDP/DHCP/DHCPPacket.cs | 496 ++++++++++++++++++ .../Network/IPV4/UDP/DNS/DNSClient.cs | 100 ++++ .../Network/IPV4/UDP/DNS/DNSPacket.cs | 375 +++++++++++++ source/Cosmos.System2/Network/IPv4/Address.cs | 45 +- .../Cosmos.System2/Network/IPv4/EndPoint.cs | 12 +- .../Cosmos.System2/Network/IPv4/ICMPPacket.cs | 79 ++- .../Cosmos.System2/Network/IPv4/IPPacket.cs | 29 +- .../Network/IPv4/OutgoingBuffer.cs | 28 +- .../Network/IPv4/UDP/UDPPacket.cs | 117 ++--- .../Network/IPv4/UDP/UdpClient.cs | 142 +++-- source/Cosmos.System2/Network/NetworkStack.cs | 98 +++- .../Cosmos.System2/Network/TempDictionary.cs | 31 +- 26 files changed, 2133 insertions(+), 231 deletions(-) create mode 100644 source/Cosmos.HAL2/Network/NetworkInit.cs rename source/Cosmos.System2/Network/{IPv4 => ARP}/ARPPacket_Ethernet.cs (96%) create mode 100644 source/Cosmos.System2/Network/Config/DNSConfig.cs rename source/Cosmos.System2/Network/{IPv4/Config.cs => Config/IPConfig.cs} (59%) create mode 100644 source/Cosmos.System2/Network/Config/NetworkConfig.cs create mode 100644 source/Cosmos.System2/Network/IPV4/ICMPClient.cs create mode 100644 source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs create mode 100644 source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs create mode 100644 source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs create mode 100644 source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs diff --git a/source/Cosmos.HAL2/Global.cs b/source/Cosmos.HAL2/Global.cs index 540fc81bcc..5bd14cba29 100644 --- a/source/Cosmos.HAL2/Global.cs +++ b/source/Cosmos.HAL2/Global.cs @@ -63,6 +63,8 @@ static public void Init(TextScreenBase textScreen) AHCI.InitDriver(); //EHCI.InitDriver(); + Network.NetworkInit.Init(); + mDebugger.Send("Done initializing Cosmos.HAL.Global"); } diff --git a/source/Cosmos.HAL2/Network/MACAddress.cs b/source/Cosmos.HAL2/Network/MACAddress.cs index 73541e5fc3..073e82917c 100644 --- a/source/Cosmos.HAL2/Network/MACAddress.cs +++ b/source/Cosmos.HAL2/Network/MACAddress.cs @@ -133,6 +133,29 @@ private static void PutByte(char[] aChars, int aIndex, byte aByte) aChars[aIndex + 1] = xChars[aByte & 0xF]; } + public UInt32 to32BitNumber() + { + return (UInt32)((bytes[0] << 40) | (bytes[1] << 32) | (bytes[2] << 24) | (bytes[3] << 16) | + (bytes[4] << 8) | (bytes[5] << 0)); + } + + private UInt32 hash; + /// + /// Hash value for this mac. Used to uniquely identify each mac + /// + public UInt32 Hash + { + get + { + if (hash == 0) + { + hash = to32BitNumber(); + } + + return hash; + } + } + public override string ToString() { // mac address consists of 6 2chars pairs, delimited by : diff --git a/source/Cosmos.HAL2/Network/NetworkInit.cs b/source/Cosmos.HAL2/Network/NetworkInit.cs new file mode 100644 index 0000000000..c20ca8ab5c --- /dev/null +++ b/source/Cosmos.HAL2/Network/NetworkInit.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Cosmos.HAL.Drivers.PCI.Network; + +namespace Cosmos.HAL.Network +{ + class NetworkInit + { + public static void Init() + { + int NetworkDeviceID = 0; + + Console.WriteLine("Searching for Ethernet Controllers..."); + + foreach (PCIDevice device in PCI.Devices) + { + if ((device.ClassCode == 0x02) && (device.Subclass == 0x00) && // is Ethernet Controller + device == PCI.GetDevice(device.bus, device.slot, device.function)) + { + + Console.WriteLine("Found " + PCIDevice.DeviceClass.GetDeviceString(device) + " on PCI " + device.bus + ":" + device.slot + ":" + device.function); + + #region PCNETII + + if (device.VendorID == (ushort)VendorID.AMD && device.DeviceID == (ushort)DeviceID.PCNETII) + { + + Console.WriteLine("NIC IRQ: " + device.InterruptLine); + + var AMDPCNetIIDevice = new AMDPCNetII(device); + + AMDPCNetIIDevice.NameID = ("eth" + NetworkDeviceID); + + Console.WriteLine("Registered at " + AMDPCNetIIDevice.NameID + " (" + AMDPCNetIIDevice.MACAddress.ToString() + ")"); + + AMDPCNetIIDevice.Enable(); + + NetworkDeviceID++; + } + + #endregion + + } + } + + if (NetworkDevice.Devices.Count == 0) + { + Console.WriteLine("No supported network card found!!"); + } + else + { + Console.WriteLine("Network initialization done!"); + } + } + } +} diff --git a/source/Cosmos.HAL2/NetworkDevice.cs b/source/Cosmos.HAL2/NetworkDevice.cs index a94edf5069..f752797909 100644 --- a/source/Cosmos.HAL2/NetworkDevice.cs +++ b/source/Cosmos.HAL2/NetworkDevice.cs @@ -1,8 +1,14 @@ -using System; +/* +* PROJECT: Aura Operating System Development +* CONTENT: Abstract Network Device Class +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; using System.Collections.Generic; using System.Linq; using System.Text; -using Cosmos.HAL; using Cosmos.HAL.Network; namespace Cosmos.HAL @@ -19,6 +25,18 @@ public abstract class NetworkDevice { public static List Devices { get; private set; } + public static NetworkDevice GetDeviceByName(string nameID) + { + foreach (var device in Devices) + { + if (device.NameID == nameID) + { + return device; + } + } + return null; + } + static NetworkDevice() { Devices = new List(); @@ -42,6 +60,11 @@ public abstract MACAddress MACAddress get; } + public string NameID + { + get; set; + } + public abstract string Name { get; diff --git a/source/Cosmos.System2/Global.cs b/source/Cosmos.System2/Global.cs index a90739daeb..2fc541ed94 100644 --- a/source/Cosmos.System2/Global.cs +++ b/source/Cosmos.System2/Global.cs @@ -89,7 +89,7 @@ public static void Init(TextScreenBase textScreen) NumLock = false; CapsLock = false; ScrollLock = false; - //Network.NetworkStack.Init(); + Network.NetworkStack.Init(); } /// diff --git a/source/Cosmos.System2/Network/ARP/ARPCache.cs b/source/Cosmos.System2/Network/ARP/ARPCache.cs index 83cd8b2e69..02219c7c52 100644 --- a/source/Cosmos.System2/Network/ARP/ARPCache.cs +++ b/source/Cosmos.System2/Network/ARP/ARPCache.cs @@ -1,5 +1,11 @@ -using System; -using sysIO = System.IO; +/* +* PROJECT: Aura Operating System Development +* CONTENT: ARP Cache (Contains MAC/IP) +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; using Cosmos.HAL.Network; namespace Cosmos.System.Network.ARP @@ -12,7 +18,7 @@ internal static class ARPCache /// /// Cache. /// - private static TempDictionary cache; + private static TempDictionary cache; /// /// Ensure cache exists. @@ -22,7 +28,7 @@ private static void ensureCacheExists() { if (cache == null) { - cache = new TempDictionary(); + cache = new TempDictionary(); } } @@ -50,7 +56,7 @@ internal static void Update(IPv4.Address ipAddress, MACAddress macAddress) ensureCacheExists(); if (ipAddress == null) { - global::System.Console.Write(""); + global::System.Console.Write(""); } UInt32 ip_hash = ipAddress.Hash; if (ip_hash == 0) diff --git a/source/Cosmos.System2/Network/ARP/ARPPacket.cs b/source/Cosmos.System2/Network/ARP/ARPPacket.cs index 8d4e5ef35a..196cd8cf3b 100644 --- a/source/Cosmos.System2/Network/ARP/ARPPacket.cs +++ b/source/Cosmos.System2/Network/ARP/ARPPacket.cs @@ -1,4 +1,11 @@ -using sys = System; +/* +* PROJECT: Aura Operating System Development +* CONTENT: ARP Packet +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; using Cosmos.HAL; using Cosmos.HAL.Network; using Cosmos.System.Network.IPv4; diff --git a/source/Cosmos.System2/Network/IPv4/ARPPacket_Ethernet.cs b/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs similarity index 96% rename from source/Cosmos.System2/Network/IPv4/ARPPacket_Ethernet.cs rename to source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs index 519fd1ee1a..c4c60375c6 100644 --- a/source/Cosmos.System2/Network/IPv4/ARPPacket_Ethernet.cs +++ b/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs @@ -1,9 +1,18 @@ -using System; +/* +* PROJECT: Aura Operating System Development +* CONTENT: ARP Packet ethernet +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; +using Cosmos.HAL; using Cosmos.HAL.Network; using Cosmos.System.Network.ARP; +using Cosmos.System.Network.IPv4; using Sys = System; -namespace Cosmos.System.Network.IPv4 +namespace Cosmos.System.Network.ARP { /// /// ARPPacket_Ethernet abstract class. See also: diff --git a/source/Cosmos.System2/Network/Config/DNSConfig.cs b/source/Cosmos.System2/Network/Config/DNSConfig.cs new file mode 100644 index 0000000000..e06b99607a --- /dev/null +++ b/source/Cosmos.System2/Network/Config/DNSConfig.cs @@ -0,0 +1,62 @@ +using Cosmos.System.Network.IPv4; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Cosmos.System.Network.Config +{ + /// + /// Contains DNS configuration + /// + class DNSConfig + { + /// + /// DNS Addresses list. + /// + public static List
DNSNameservers = new List
(); + + /// + /// Add IPv4 configuration. + /// + /// + public static void Add(Address nameserver) + { + foreach (var ns in DNSNameservers) + { + if (ns.address.ToString() == nameserver.address.ToString()) + { + return; + } + } + DNSNameservers.Add(nameserver); + } + + /// + /// Remove IPv4 configuration. + /// + /// + public static void Remove(Address nameserver) + { + int counter = 0; + + foreach (var ns in DNSNameservers) + { + if (ns.address.ToString() == nameserver.address.ToString()) + { + DNSNameservers.RemoveAt(counter); + } + counter++; + } + } + + /// + /// Call this to get your adress to request your DNS server + /// + /// Which server you want to get + /// DNS Server + public static Address Server(int index) + { + return DNSNameservers[index]; + } + } +} diff --git a/source/Cosmos.System2/Network/IPv4/Config.cs b/source/Cosmos.System2/Network/Config/IPConfig.cs similarity index 59% rename from source/Cosmos.System2/Network/IPv4/Config.cs rename to source/Cosmos.System2/Network/Config/IPConfig.cs index 3d8085bb55..8bbdbdeb83 100644 --- a/source/Cosmos.System2/Network/IPv4/Config.cs +++ b/source/Cosmos.System2/Network/Config/IPConfig.cs @@ -1,28 +1,64 @@ -using System.Collections.Generic; -using Cosmos.HAL; +/* +* PROJECT: Aura Operating System Development +* CONTENT: List of all IPs / Utils +* PROGRAMMERS: Valentin Charbonnier +* Alexy DA CRUZ +* Port of Cosmos Code. +*/ + +using System.Collections.Generic; using System; +using Cosmos.System.Network.IPv4; +using Cosmos.HAL; -namespace Cosmos.System.Network.IPv4 +namespace Cosmos.System.Network.Config { /// /// Contains a IPv4 configuration /// - public class Config + public class IPConfig { /// /// IPv4 configurations list. /// - private static readonly List ipConfigs = new List(); + private static readonly List ipConfigs = new List(); /// /// Add IPv4 configuration. /// /// - internal static void Add(Config config) + internal static void Add(IPConfig config) { ipConfigs.Add(config); } + /// + /// Remove IPv4 configuration. + /// + /// + internal static void Remove(IPConfig config) + { + int counter = 0; + + foreach (var ipconfig in ipConfigs) + { + if (ipconfig == config) + { + ipConfigs.RemoveAt(counter); + return; + } + counter++; + } + } + + /// + /// Remove All IPv4 configuration. + /// + internal static void RemoveAll() + { + ipConfigs.Clear(); + } + /// /// Find network. /// @@ -33,22 +69,39 @@ internal static Address FindNetwork(Address destIP) { Address default_gw = null; - for (int c = 0; c < ipConfigs.Count; c++) + foreach (IPConfig ipConfig in ipConfigs) { - if ((ipConfigs[c].IPAddress.Hash & ipConfigs[c].SubnetMask.Hash) == - (destIP.Hash & ipConfigs[c].SubnetMask.Hash)) + if ((ipConfig.IPAddress.Hash & ipConfig.SubnetMask.Hash) == + (destIP.Hash & ipConfig.SubnetMask.Hash)) + { + return ipConfig.IPAddress; + } + if ((default_gw == null) && (ipConfig.DefaultGateway.CompareTo(Address.Zero) != 0)) { - return ipConfigs[c].IPAddress; + default_gw = ipConfig.IPAddress; } - if ((default_gw == null) && (ipConfigs[c].DefaultGateway.CompareTo(Address.Zero) != 0)) + + if (!IsLocalAddress(destIP)) { - default_gw = ipConfigs[c].IPAddress; + return ipConfig.IPAddress; } } return default_gw; } + internal static bool Enable(NetworkDevice device, Address ip, Address subnet, Address gw) + { + if (device != null) + { + var config = new IPConfig(ip, subnet, gw); + NetworkStack.ConfigIP(device, config); + NetworkStack.debugger.Send(config.ToString()); + return true; + } + return false; + } + /// /// Check if address is local address. /// @@ -88,10 +141,10 @@ internal static Address FindRoute(Address destIP) { for (int c = 0; c < ipConfigs.Count; c++) { - if (ipConfigs[c].DefaultGateway.CompareTo(Address.Zero) != 0) - { + //if (ipConfigs[c].DefaultGateway.CompareTo(Address.Zero) != 0) + //{ return ipConfigs[c].DefaultGateway; - } + //} } return null; @@ -102,7 +155,7 @@ internal static Address FindRoute(Address destIP) ///
/// IP Address /// Subnet Mask - public Config(Address ip, Address subnet) + public IPConfig(Address ip, Address subnet) : this(ip, subnet, Address.Zero) { } @@ -113,7 +166,7 @@ public Config(Address ip, Address subnet) /// IP Address /// Subnet Mask /// Default gateway - public Config(Address ip, Address subnet, Address gw) + public IPConfig(Address ip, Address subnet, Address gw) { IPAddress = ip; SubnetMask = subnet; diff --git a/source/Cosmos.System2/Network/Config/NetworkConfig.cs b/source/Cosmos.System2/Network/Config/NetworkConfig.cs new file mode 100644 index 0000000000..3d1afdd6f4 --- /dev/null +++ b/source/Cosmos.System2/Network/Config/NetworkConfig.cs @@ -0,0 +1,132 @@ +/* +* PROJECT: Aura Operating System Development +* CONTENT: Network dictionary +* PROGRAMMERS: Valentin Charbonnier +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using Cosmos.HAL; + +namespace Cosmos.System.Network.Config +{ + public class NetworkConfig + { + public static List Keys = new List(); + public static List Values = new List(); + public static KeyValuePair CurrentConfig; + + public IPConfig this[NetworkDevice key] + { + get + { + return Get(key); + } + set + { + Values[Keys.IndexOf(key)] = value; + } + } + + public static int Count + { + get + { + return Keys.Count; + } + } + + public static bool ContainsKey(NetworkDevice k) + { + foreach (var device in Keys) + { + if (k == device) + { + return true; + } + } + return false; + } + + public static IPConfig Get(NetworkDevice key) + { + int index = 0; + + foreach (var device in Keys) + { + if (key == device) + { + break; + } + index++; + } + + return Values[index]; + } + + public static void Add(NetworkDevice key, IPConfig value) + { + Keys.Add(key); + Values.Add(value); + } + + public static NetworkDevice[] GetKeys() + { + return Keys.ToArray(); + } + + public static IPConfig[] GetValues() + { + return Values.ToArray(); + } + + public static NetworkDevice GetKeyByValue(IPConfig value) + { + var x = Values.IndexOf(value); + var x_ = Keys[x]; + return x_; + } + + public static void Remove(NetworkDevice key) + { + int index = 0; + + foreach (var device in Keys) + { + if (key == device) + { + break; + } + index++; + } + Keys.RemoveAt(index); + Values.RemoveAt(index); + } + + public static void Clear() + { + Keys = new List(); + Values = new List(); + } + + /// + /// Get Values + /// + /// + public static IEnumerator GetEnumerator_V() + { + return ((IEnumerable)Values).GetEnumerator(); + } + + /// + /// Default GetEnumerator (Keys) + /// + /// + public static IEnumerator GetEnumerator() + { + return ((IEnumerable)Keys).GetEnumerator(); + } + + } +} diff --git a/source/Cosmos.System2/Network/EthernetPacket.cs b/source/Cosmos.System2/Network/EthernetPacket.cs index becfb86fb2..ad3d71424e 100644 --- a/source/Cosmos.System2/Network/EthernetPacket.cs +++ b/source/Cosmos.System2/Network/EthernetPacket.cs @@ -1,4 +1,11 @@ -using System; +/* +* PROJECT: Aura Operating System Development +* CONTENT: Ethernet frame +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; using Cosmos.HAL.Network; namespace Cosmos.System.Network @@ -125,7 +132,7 @@ internal MACAddress DestinationMAC public virtual void PrepareForSending() { - + } /// diff --git a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs new file mode 100644 index 0000000000..6e7171b153 --- /dev/null +++ b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs @@ -0,0 +1,143 @@ +/* +* PROJECT: Aura Operating System Development +* CONTENT: ICMP Client +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using Cosmos.System.Network.Config; +using Cosmos.HAL; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Cosmos.System.Network.IPv4 +{ + /// + /// ICMPClient class. Used to manage the ICMP connection to a client. + /// + public class ICMPClient + { + /// + /// Clients dictionary. + /// + private static TempDictionary clients; + + /// + /// Destination address. + /// + protected Address destination; + + /// + /// RX buffer queue. + /// + protected Queue rxBuffer; + + /// + /// Assign clients dictionary. + /// + /// Thrown on fatal error (contact support). + static ICMPClient() + { + clients = new TempDictionary(); + } + + /// + /// Get client. + /// + /// IP Hash. + /// ICMPClient + internal static ICMPClient Client(uint iphash) + { + if (clients.ContainsKey(iphash) == true) + { + return clients[iphash]; + } + + return null; + } + + /// + /// Create new inctanse of the class. + /// + public ICMPClient() + { + rxBuffer = new Queue(8); + } + + /// + /// Connect to client. + /// + /// Destination address. + public void Connect(Address dest) + { + destination = dest; + clients.Add(dest.Hash, this); + } + + /// + /// Close connection. + /// + /// Thrown on fatal error (contact support). + public void Close() + { + if (clients.ContainsKey(destination.Hash) == true) + { + clients.Remove(destination.Hash); + } + } + + /// + /// Send ICMP Echo + /// + public void SendEcho() + { + Address source = IPConfig.FindNetwork(destination); + ICMPEchoRequest request = new ICMPEchoRequest(source, destination, 0x0001, 0x50); //this is working + OutgoingBuffer.AddPacket(request); //Aura doesn't work when this is called. + NetworkStack.Update(); + } + + /// + /// Receive data + /// + /// Source end point. + /// timeout value, default 5000ms + /// Address from Domain Name + /// Thrown on fatal error (contact support). + public int Receive(ref EndPoint source, int timeout = 5000) + { + int second = 0; + int _deltaT = 0; + + while (rxBuffer.Count < 1) + { + if (second > (timeout / 1000)) + { + return -1; + } + if (_deltaT != RTC.Second) + { + second++; + _deltaT = RTC.Second; + } + } + + ICMPEchoReply packet = new ICMPEchoReply(rxBuffer.Dequeue().RawData); + source.address = packet.SourceIP; + + return second; + } + + /// + /// Receive data from packet. + /// + /// Packet to receive. + /// Thrown on fatal error (contact support). + /// Thrown on IO error. + public void receiveData(ICMPPacket packet) + { + rxBuffer.Enqueue(packet); + } + } +} diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs new file mode 100644 index 0000000000..b78b38cf9d --- /dev/null +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs @@ -0,0 +1,228 @@ +using Cosmos.System.Network.IPv4; +using System; +using Cosmos.System.Network.IPv4.UDP.DNS; +using Cosmos.System.Network.Config; +using System.Collections.Generic; +using Cosmos.HAL; + +/* +* PROJECT: Aura Operating System Development +* CONTENT: DHCP - DHCP Core +* PROGRAMMER(S): Alexy DA CRUZ +*/ + +namespace Cosmos.System.Network.IPv4.UDP.DHCP +{ + /// + /// DHCPClient class. Used to manage the DHCP connection to a server. + /// + class DHCPClient + { + /// + /// Current DHCPClient + /// + public static DHCPClient currentClient; + + // + /// RX buffer queue. + /// + protected Queue rxBuffer; + + // + /// Is DHCP ascked check variable + /// + protected bool asked = false; + + /// + /// Get the IP address of the DHCP server + /// + /// + public static Address DHCPServerAddress(NetworkDevice networkDevice) + { + return NetworkConfig.Get(networkDevice).DefaultGateway; + } + + /// + /// Create new inctanse of the class. + /// + /// Thrown on fatal error (contact support). + /// Thrown if UdpClient with localPort 0 exists. + public DHCPClient() + { + rxBuffer = new Queue(8); + currentClient = this; + } + + /// + /// Close connection. + /// + /// Thrown on fatal error (contact support). + public void Close() + { + currentClient = null; + } + + /// + /// Receive data from packet. + /// + /// Packet to receive. + /// Thrown on fatal error (contact support). + /// Thrown on IO error. + public void receiveData(DHCPPacket packet) + { + rxBuffer.Enqueue(packet); + } + + /// + /// Receive data + /// + /// timeout value, default 5000ms + /// time value (-1 = timeout) + /// Thrown on fatal error (contact support). + private int Receive(int timeout = 5000) + { + int second = 0; + int _deltaT = 0; + + while (rxBuffer.Count < 1) + { + if (second > (timeout / 1000)) + { + return -1; + } + if (_deltaT != Cosmos.HAL.RTC.Second) + { + second++; + _deltaT = Cosmos.HAL.RTC.Second; + } + } + + var packet = rxBuffer.Dequeue(); + + if (packet.MessageType == 2) //Boot Reply + { + if (packet.RawData[284] == 0x02) //Offer packet received + { + SendRequestPacket(packet.Client, packet.Server); + } + else if (packet.RawData[284] == 0x05 || packet.RawData[284] == 0x06) //ACK or NAK DHCP packet received + { + DHCPAck ack = new DHCPAck(packet.RawData); + if (asked) + { + Apply(ack, true); + } + else + { + Apply(ack); + } + } + } + + return second; + } + + /// + /// Send a packet to the DHCP server to make the address available again + /// + public void SendReleasePacket() + { + foreach (NetworkDevice networkDevice in NetworkDevice.Devices) + { + Address source = IPConfig.FindNetwork(DHCPServerAddress(networkDevice)); + DHCPRelease dhcp_release = new DHCPRelease(source, DHCPServerAddress(networkDevice), networkDevice.MACAddress); + + OutgoingBuffer.AddPacket(dhcp_release); + NetworkStack.Update(); + + NetworkStack.RemoveAllConfigIP(); + + IPConfig.Enable(networkDevice, new Address(0, 0, 0, 0), new Address(0, 0, 0, 0), new Address(0, 0, 0, 0)); + } + Close(); + } + + /// + /// Send a packet to find the DHCP server and tell that we want a new IP address + /// + public void SendDiscoverPacket() + { + NetworkStack.RemoveAllConfigIP(); + + foreach (NetworkDevice networkDevice in NetworkDevice.Devices) + { + IPConfig.Enable(networkDevice, new Address(0, 0, 0, 0), new Address(0, 0, 0, 0), new Address(0, 0, 0, 0)); + + DHCPDiscover dhcp_discover = new DHCPDiscover(networkDevice.MACAddress); + OutgoingBuffer.AddPacket(dhcp_discover); + NetworkStack.Update(); + + asked = true; + } + + Receive(); + } + + /// + /// Send a request to apply the new IP configuration + /// + private void SendRequestPacket(Address RequestedAddress, Address DHCPServerAddress) + { + foreach (NetworkDevice networkDevice in NetworkDevice.Devices) + { + DHCPRequest dhcp_request = new DHCPRequest(networkDevice.MACAddress, RequestedAddress, DHCPServerAddress); + OutgoingBuffer.AddPacket(dhcp_request); + NetworkStack.Update(); + } + Receive(); + } + + /* + * Method called to applied the differents options received in the DHCP packet ACK + **/ + /// + /// Apply the new IP configuration received. + /// + /// DHCPOption class using the packetData from the received dhcp packet. + /// Enable/Disable the displaying of messages about DHCP applying and conf. Disabled by default. + /// + private void Apply(DHCPAck packet, bool message = false) + { + NetworkStack.RemoveAllConfigIP(); + + //cf. Roadmap. (have to change this, because some network interfaces are not configured in dhcp mode) [have to be done in 0.5.x] + foreach (NetworkDevice networkDevice in NetworkDevice.Devices) + { + if (packet.Client.ToString() == null || + packet.Client.ToString() == null || + packet.Client.ToString() == null || + packet.Client.ToString() == null) + { + NetworkStack.debugger.Send("Parsing DHCP ACK Packet failed, can't apply network configuration."); + } + else + { + if (message) + { + NetworkStack.debugger.Send("[DHCP ACK][" + networkDevice.Name + "] Packet received, applying IP configuration..."); + NetworkStack.debugger.Send(" IP Address : " + packet.Client.ToString()); + NetworkStack.debugger.Send(" Subnet mask : " + packet.Subnet.ToString()); + NetworkStack.debugger.Send(" Gateway : " + packet.Server.ToString()); + NetworkStack.debugger.Send(" DNS server : " + packet.DNS.ToString()); + } + + IPConfig.Enable(networkDevice, packet.Client, packet.Subnet, packet.Server); + DNSConfig.Add(packet.DNS); + + if (message) + { + NetworkStack.debugger.Send("[DHCP CONFIG][" + networkDevice.Name + "] IP configuration applied."); + asked = false; + } + } + } + + Close(); + } + } +} diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs new file mode 100644 index 0000000000..779665da66 --- /dev/null +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs @@ -0,0 +1,496 @@ +using Cosmos.HAL; +using Cosmos.HAL.Network; +using Cosmos.System.Network.IPv4; +using Cosmos.System.Network.IPv4.UDP; +using System; +using System.Collections.Generic; +using System.Text; + +/* +* PROJECT: Aura Operating System Development +* CONTENT: DHCP Packet +* PROGRAMMERS: Alexy DA CRUZ +*/ + +namespace Cosmos.System.Network.IPv4.UDP.DHCP +{ + + /// + /// DHCP Option + /// + public class DHCPOption + { + /// + /// DHCP Option Type + /// + public byte Type { get; set; } + + /// + /// DHCP Option Length + /// + public byte Length { get; set; } + + /// + /// DHCP Option Data + /// + public byte[] Data { get; set; } + } + + /// + /// DHCPPacket class. + /// + public class DHCPPacket : UDPPacket + { + int xID; + + /// + /// DHCP handler. + /// + /// Packet data. + /// Thrown if UDP_Data array length is greater than Int32.MaxValue. + /// Thrown on IO error. + public static void DHCPHandler(byte[] packetData) + { + DHCPPacket dhcp_packet = new DHCPPacket(packetData); + + DHCPClient receiver = DHCPClient.currentClient; + if (receiver != null) + { + receiver.receiveData(dhcp_packet); + } + } + + /// + /// Work around to make VMT scanner include the initFields method + /// + public static void VMTInclude() + { + new DHCPPacket(); + } + + /// + /// Create new inctanse of the class. + /// + internal DHCPPacket() : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + internal DHCPPacket(byte[] rawData) + : base(rawData) + { } + + /// + /// Create new inctanse of the class. + /// + /// Source MAC Address. + /// DHCP Data size + internal DHCPPacket(MACAddress mac_src, ushort dhcpDataSize) + : this(Address.Zero, Address.Broadcast, mac_src, dhcpDataSize) + { } + + /// + /// Create new inctanse of the class. + /// + /// Client IPv4 Address. + /// Server IPv4 Address. + /// Source MAC Address. + /// DHCP Data size + /// Thrown if data array length is greater than Int32.MaxValue. + /// Thrown if RawData is invalid or null. + internal DHCPPacket(Address client, Address server, MACAddress mac_src, ushort dhcpDataSize) + : base(client, server, 68, 67, (ushort)(dhcpDataSize + 240), MACAddress.Broadcast) + { + //Request + RawData[42] = 0x01; + + //ethernet + RawData[43] = 0x01; + + //Length mac + RawData[44] = 0x06; + + //hops + RawData[45] = 0x00; + + Random rnd = new Random(); + xID = rnd.Next(0, Int32.MaxValue); + RawData[46] = (byte)((xID >> 24) & 0xFF); + RawData[47] = (byte)((xID >> 16) & 0xFF); + RawData[48] = (byte)((xID >> 8) & 0xFF); + RawData[49] = (byte)((xID >> 0) & 0xFF); + + //second elapsed + RawData[50] = 0x00; + RawData[51] = 0x00; + + //option bootp + RawData[52] = 0x00; + RawData[53] = 0x00; + + //client ip address + RawData[54] = client.address[0]; + RawData[55] = client.address[1]; + RawData[56] = client.address[2]; + RawData[57] = client.address[3]; + + for (int i = 0; i < 13; i++) + { + RawData[58 + i] = 0x00; + } + + //Src mac + RawData[70] = mac_src.bytes[0]; + RawData[71] = mac_src.bytes[1]; + RawData[72] = mac_src.bytes[2]; + RawData[73] = mac_src.bytes[3]; + RawData[74] = mac_src.bytes[4]; + RawData[75] = mac_src.bytes[5]; + + //Fill 0 + for (int i = 0; i < 202; i++) + { + RawData[76 + i] = 0x00; + } + + //DHCP Magic cookie + RawData[278] = 0x63; + RawData[279] = 0x82; + RawData[280] = 0x53; + RawData[281] = 0x63; + + initFields(); + } + + /// + /// Init DHCPPacket fields. + /// + /// Thrown if RawData is invalid or null. + protected override void initFields() + { + base.initFields(); + MessageType = RawData[42]; + Client = new Address(RawData, 58); + Server = new Address(RawData, 62); + + if (RawData[282] != 0) + { + Options = new List(); + + for (int i = 0; i < RawData.Length - 282 && RawData[282 + i] != 0xFF; i += 2) //0xFF is DHCP packet end + { + DHCPOption option = new DHCPOption(); + option.Type = RawData[282 + i]; + option.Length = RawData[282 + i + 1]; + option.Data = new byte[option.Length]; + for (int j = 0; j < option.Length; j++) + { + option.Data[j] = RawData[282 + i + j + 2]; + } + Options.Add(option); + + i += option.Length; + } + } + } + + /// + /// Get DHCP message type + /// + internal byte MessageType { get; private set; } + + /// + /// Get Client IPv4 Address + /// + internal Address Client { get; private set; } + + /// + /// Get DHCP Server IPv4 Address + /// + internal Address Server { get; private set; } + + /// + /// Get DHCP Options + /// + internal List Options { get; private set; } + + } + + /// + /// DHCPDiscover class. + /// + internal class DHCPDiscover : DHCPPacket + { + /// + /// Create new inctanse of the class. + /// + internal DHCPDiscover() : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + internal DHCPDiscover(byte[] rawData) : base(rawData) + { } + + /// + /// Create new inctanse of the class. + /// + /// Source MAC Address. + /// Thrown if RawData is invalid or null. + internal DHCPDiscover(MACAddress mac_src) : base(mac_src, 10) //discover packet size + { + //Discover + RawData[282] = 0x35; + RawData[283] = 0x01; + RawData[284] = 0x01; + + //Parameters start here + RawData[285] = 0x37; + RawData[286] = 4; + + //Parameters* + RawData[287] = 0x01; + RawData[288] = 0x03; + RawData[289] = 0x0f; + RawData[290] = 0x06; + + RawData[291] = 0xff; //ENDMARK + } + + /// + /// Work around to make VMT scanner include the initFields method + /// + public new static void VMTInclude() + { + new DHCPDiscover(); + } + + protected override void initFields() + { + base.initFields(); + } + + } + + /// + /// DHCPRequest class. + /// + internal class DHCPRequest : DHCPPacket + { + + /// + /// Create new inctanse of the class. + /// + internal DHCPRequest() : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + internal DHCPRequest(byte[] rawData) : base(rawData) + { } + + /// + /// Create new inctanse of the class. + /// + /// Source MAC Address. + /// Requested Address. + /// DHCP server IPv4 Address. + /// Thrown if data array length is greater than Int32.MaxValue. + /// Thrown if RawData is invalid or null. + internal DHCPRequest(MACAddress mac_src, Address RequestedAddress, Address DHCPServerAddress) : base(mac_src, 22) + { + //Request + RawData[282] = 53; + RawData[283] = 1; + RawData[284] = 3; + + //Requested Address + RawData[285] = 50; + RawData[286] = 4; + + RawData[287] = RequestedAddress.address[0]; + RawData[288] = RequestedAddress.address[1]; + RawData[289] = RequestedAddress.address[2]; + RawData[290] = RequestedAddress.address[3]; + + RawData[291] = 54; + RawData[292] = 4; + + RawData[293] = DHCPServerAddress.address[0]; + RawData[294] = DHCPServerAddress.address[1]; + RawData[295] = DHCPServerAddress.address[2]; + RawData[296] = DHCPServerAddress.address[3]; + + //Parameters start here + RawData[297] = 0x37; + RawData[298] = 4; + + //Parameters + RawData[299] = 0x01; + RawData[300] = 0x03; + RawData[301] = 0x0f; + RawData[302] = 0x06; + + RawData[303] = 0xff; //ENDMARK + } + + /// + /// Work around to make VMT scanner include the initFields method + /// + public new static void VMTInclude() + { + new DHCPRequest(); + } + + /// + /// Init DHCPRequest fields. + /// + /// Thrown if RawData is invalid or null. + protected override void initFields() + { + base.initFields(); + } + + } + + /// + /// DHCPAck class. + /// + internal class DHCPAck : DHCPPacket + { + /// + /// Create new inctanse of the class. + /// + internal DHCPAck() : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + internal DHCPAck(byte[] rawData) : base(rawData) + { } + + /// + /// Work around to make VMT scanner include the initFields method + /// + public new static void VMTInclude() + { + new DHCPAck(); + } + + /// + /// Init DHCPAck fields. + /// + /// Thrown if RawData is invalid or null. + protected override void initFields() + { + base.initFields(); + + foreach (var option in Options) + { + if (option.Type == 1) //Mask + { + Subnet = new Address(option.Data, 0); + } + else if (option.Type == 6) //DNS + { + DNS = new Address(option.Data, 0); + } + } + } + + /// + /// Get Subnet IPv4 Address + /// + internal Address Subnet { get; private set; } + + /// + /// Get DNS IPv4 Address + /// + internal Address DNS { get; private set; } + + } + + /// + /// DHCPRelease class. + /// + internal class DHCPRelease : DHCPPacket + { + /// + /// Create new inctanse of the class. + /// + internal DHCPRelease() : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + internal DHCPRelease(byte[] rawData) : base(rawData) + { } + + /// + /// Create new inctanse of the class. + /// + /// Client IPv4 Address. + /// DHCP Server IPv4 Address. + /// Source MAC Address. + /// Thrown if data array length is greater than Int32.MaxValue. + /// Thrown if RawData is invalid or null. + internal DHCPRelease(Address client, Address server, MACAddress source) : base(client, server, source, 19) + { + //Release + RawData[282] = 0x35; + RawData[283] = 0x01; + RawData[284] = 0x07; + + //DHCP Server ID + RawData[285] = 0x36; + RawData[286] = 0x04; + + RawData[287] = server.address[0]; + RawData[288] = server.address[1]; + RawData[289] = server.address[2]; + RawData[290] = server.address[3]; + + //Client ID + RawData[291] = 0x3d; + RawData[292] = 7; + RawData[293] = 1; + + RawData[294] = source.bytes[0]; + RawData[295] = source.bytes[1]; + RawData[296] = source.bytes[2]; + RawData[297] = source.bytes[3]; + RawData[298] = source.bytes[4]; + RawData[299] = source.bytes[5]; + + RawData[300] = 0xff; //ENDMARK + } + + /// + /// Work around to make VMT scanner include the initFields method + /// + public new static void VMTInclude() + { + new DHCPRelease(); + } + + /// + /// Init DHCPRelease fields. + /// + /// Thrown if RawData is invalid or null. + protected override void initFields() + { + base.initFields(); + } + + } +} diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs new file mode 100644 index 0000000000..99668cb5fb --- /dev/null +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs @@ -0,0 +1,100 @@ +/* +* PROJECT: Aura Operating System Development +* CONTENT: DNS Client +* PROGRAMMERS: Valentin Charbonnier +*/ + +using Cosmos.System.Network.Config; +using Cosmos.HAL; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Cosmos.System.Network.IPv4.UDP.DNS +{ + /// + /// DnsClient class. Used to manage the DNS connection to a server. + /// + class DnsClient : UdpClient + { + /// + /// Domain Name query string + /// + private string queryurl; + + /// + /// Create new inctanse of the class. + /// + /// Thrown on fatal error (contact support). + /// Thrown if UdpClient with localPort 53 exists. + public DnsClient() : base(53) + { + } + + /// + /// Connect to client. + /// + /// Destination address. + public void Connect(Address address) + { + Connect(address, 53); + } + + /// + /// Send DNS Ask for Domain Name string + /// + /// Domain Name string. + public void SendAsk(string url) + { + Address source = IPConfig.FindNetwork(destination); + + queryurl = url; + + DNSPacketAsk askpacket = new DNSPacketAsk(source, destination, url); + + OutgoingBuffer.AddPacket(askpacket); + + NetworkStack.Update(); + } + + /// + /// Receive data + /// + /// timeout value, default 5000ms + /// Address from Domain Name + /// Thrown on fatal error (contact support). + public Address Receive(int timeout = 5000) + { + int second = 0; + int _deltaT = 0; + + while (rxBuffer.Count < 1) + { + if (second > (timeout / 1000)) + { + return null; + } + if (_deltaT != RTC.Second) + { + second++; + _deltaT = RTC.Second; + } + } + + DNSPacketAnswer packet = new DNSPacketAnswer(rxBuffer.Dequeue().RawData); + + if ((ushort)(packet.DNSFlags & 0x0F) == (ushort)ReplyCode.OK) + { + if (packet.Queries.Count > 0 && packet.Queries[0].Name == queryurl) + { + if (packet.Answers.Count > 0 && packet.Answers[0].Address.Length == 4) + { + return new Address(packet.Answers[0].Address, 0); + } + } + } + return null; + } + + } +} diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs new file mode 100644 index 0000000000..b09df143fc --- /dev/null +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs @@ -0,0 +1,375 @@ +/* +* PROJECT: Aura Operating System Development +* CONTENT: DNS Packet +* PROGRAMMERS: Valentin Charbonnier +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Cosmos.System.Network.IPv4.UDP.DNS +{ + + /// + /// ReplyCode set in Flags + /// + public enum ReplyCode + { + OK = 0000, + FormatError = 0001, + ServerFailure = 0010, + NameError = 0011, + NotSupported = 0100, + Refused = 0101 + } + + /// + /// DNS Query + /// + public class DNSQuery + { + public string Name { get; set; } + public ushort Type { get; set; } + public ushort Class { get; set; } + } + + /// + /// DNS Answer + /// + public class DNSAnswer + { + public ushort Name { get; set; } + public ushort Type { get; set; } + public ushort Class { get; set; } + public int TimeToLive { get; set; } + public ushort DataLenght { get; set; } + public byte[] Address { get; set; } + } + + /// + /// DNSPacket class. + /// + public class DNSPacket : UDPPacket + { + /// + /// DNS handler. + /// + /// Packet data. + /// Thrown on IO error. + internal static void DNSHandler(byte[] packetData) + { + DNSPacket dns_packet = new DNSPacket(packetData); + + DnsClient receiver = (DnsClient)UdpClient.Client(dns_packet.DestinationPort); + if (receiver != null) + { + receiver.receiveData(dns_packet); + } + } + + /// + /// Work around to make VMT scanner include the initFields method + /// + public static void VMTInclude() + { + new DNSPacket(); + } + + /// + /// Create new inctanse of the class. + /// + internal DNSPacket() + : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + public DNSPacket(byte[] rawData) + : base(rawData) + { } + + /// + /// Create new inctanse of the class. + /// + /// Source address. + /// Destination address. + /// Domain name number. + /// Length + /// Thrown if data array length is greater than Int32.MaxValue. + /// Thrown if RawData is invalid or null. + public DNSPacket(Address source, Address dest, ushort urlnb, ushort len) + : base(source, dest, 53, 53, (ushort)(len + 12)) + { + Random rnd = new Random(); + byte transactionID = (byte)rnd.Next(0, Int32.MaxValue); + RawData[this.DataOffset + 8] = (byte)((transactionID >> 8) & 0xFF); + RawData[this.DataOffset + 9] = (byte)((transactionID >> 0) & 0xFF); + + RawData[this.DataOffset + 10] = (byte)((0x0100 >> 8) & 0xFF); + RawData[this.DataOffset + 11] = (byte)((0x0100 >> 0) & 0xFF); + + RawData[this.DataOffset + 12] = (byte)((urlnb >> 8) & 0xFF); + RawData[this.DataOffset + 13] = (byte)((urlnb >> 0) & 0xFF); + + RawData[this.DataOffset + 14] = (byte)((0 >> 8) & 0xFF); + RawData[this.DataOffset + 15] = (byte)((0 >> 0) & 0xFF); + + RawData[this.DataOffset + 16] = (byte)((0 >> 8) & 0xFF); + RawData[this.DataOffset + 17] = (byte)((0 >> 0) & 0xFF); + + RawData[this.DataOffset + 18] = (byte)((0 >> 8) & 0xFF); + RawData[this.DataOffset + 19] = (byte)((0 >> 0) & 0xFF); + + initFields(); + } + + /// + /// Init DNSPacket fields. + /// + /// Thrown if RawData is invalid or null. + protected override void initFields() + { + base.initFields(); + TransactionID = (UInt16)((RawData[this.DataOffset + 8] << 8) | RawData[this.DataOffset + 9]); + DNSFlags = (UInt16)((RawData[this.DataOffset + 10] << 8) | RawData[this.DataOffset + 11]); + Questions = (UInt16)((RawData[this.DataOffset + 12] << 8) | RawData[this.DataOffset + 13]); + AnswerRRs = (UInt16)((RawData[this.DataOffset + 14] << 8) | RawData[this.DataOffset + 15]); + AuthorityRRs = (UInt16)((RawData[this.DataOffset + 16] << 8) | RawData[this.DataOffset + 17]); + AdditionalRRs = (UInt16)((RawData[this.DataOffset + 18] << 8) | RawData[this.DataOffset + 19]); + } + + /// + /// Get name from data and offset + /// + /// Data + /// Data offset + public string parseName(byte[] RawData, ref int index) + { + StringBuilder url = new StringBuilder(); + + while (RawData[index] != 0x00 && index < RawData.Length) + { + byte wordlength = RawData[index]; + index++; + for (int j = 0; j < wordlength; j++) + { + url.Append((char)RawData[index]); + index++; + } + url.Append('.'); + } + index++; //End 0x00 + return (url.ToString().Remove(url.Length - 1, 1)); + } + + /// + /// Get AnswerRRs + /// + internal ushort AnswerRRs { get; private set; } + + /// + /// Get AuthorityRRs + /// + internal ushort AuthorityRRs { get; private set; } + + /// + /// Get AdditionalRRs + /// + internal ushort AdditionalRRs { get; private set; } + + /// + /// Get Transaction ID + /// + internal ushort TransactionID { get; private set; } + + /// + /// Get DNS Flags + /// + internal ushort DNSFlags { get; private set; } + + /// + /// Get DNS Queries Number + /// + internal ushort Questions { get; private set; } + + /// + /// Get DNS Queries + /// + internal List Queries { get; set; } + + /// + /// Get DNS Answers + /// + internal List Answers { get; set; } + + /// + /// To string. + /// + /// string value. + public override string ToString() + { + return "DNS Packet Src=" + SourceIP + ":" + SourcePort + ", Dest=" + DestinationIP + ":" + DestinationPort; + } + + } + + /// + /// DNSPacketAsk class. + /// + public class DNSPacketAsk : DNSPacket + { + /// + /// Work around to make VMT scanner include the initFields method + /// + public static void VMTInclude() + { + new DNSPacketAsk(); + } + + /// + /// Create new inctanse of the class. + /// + internal DNSPacketAsk() + : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + public DNSPacketAsk(byte[] rawData) + : base(rawData) + { } + + /// + /// Create new inctanse of the class. + /// + /// Source address. + /// DNS Server address. + /// Domain name string. + /// Thrown if RawData is invalid or null. + public DNSPacketAsk(Address source, Address dest, string url) + : base(source, dest, 1, (ushort)(5 + url.Length + 1)) + { + int b = 0; + + foreach (string item in url.Split('.')) + { + byte[] word = Encoding.ASCII.GetBytes(item); + + RawData[this.DataOffset + 20 + b] = (byte)word.Length; //set word length + + b++; + + foreach (byte letter in word) + { + RawData[this.DataOffset + 20 + b] = letter; + b++; + } + + } + + RawData[this.DataOffset + 20 + b] = 0x00; + + RawData[this.DataOffset + 20 + b + 1] = 0x00; + RawData[this.DataOffset + 20 + b + 2] = 0x01; + + RawData[this.DataOffset + 20 + b + 3] = 0x00; + RawData[this.DataOffset + 20 + b + 4] = 0x01; + } + + /// + /// Init DNSPacketAsk fields. + /// + /// Thrown if RawData is invalid or null. + protected override void initFields() + { + base.initFields(); + } + } + + /// + /// DNSPacketAnswer class. + /// + public class DNSPacketAnswer : DNSPacket + { + /// + /// Work around to make VMT scanner include the initFields method + /// + public static void VMTInclude() + { + new DNSPacketAnswer(); + } + + /// + /// Create new inctanse of the class. + /// + internal DNSPacketAnswer() + : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + public DNSPacketAnswer(byte[] rawData) + : base(rawData) + { } + + /// + /// Init DNSPacketAnswer fields. + /// + /// Thrown if RawData is invalid or null. + protected override void initFields() + { + base.initFields(); + + if ((ushort)(DNSFlags & 0x0F) != (ushort)ReplyCode.OK) + { + NetworkStack.debugger.Send("DNS Packet response not OK. Passing packet."); + return; + } + + int index = DataOffset + 20; + if (Questions > 0) + { + Queries = new List(); + + for (int i = 0; i < Questions; i++) + { + DNSQuery query = new DNSQuery(); + query.Name = parseName(RawData, ref index); + query.Type = (ushort)((RawData[index + 0] << 8) | RawData[index + 1]); + query.Class = (ushort)((RawData[index + 2] << 8) | RawData[index + 3]); + Queries.Add(query); + index += 4; + } + } + if (AnswerRRs > 0) + { + Answers = new List(); + + for (int i = 0; i < AnswerRRs; i++) + { + DNSAnswer answer = new DNSAnswer(); + answer.Name = (ushort)((RawData[index + 0] << 8) | RawData[index + 1]); + answer.Type = (ushort)((RawData[index + 2] << 8) | RawData[index + 3]); + answer.Class = (ushort)((RawData[index + 4] << 8) | RawData[index + 5]); + answer.TimeToLive = (RawData[index + 6] << 24) | (RawData[index + 7] << 16) | (RawData[index + 8] << 8) | RawData[index + 9]; + answer.DataLenght = (ushort)((RawData[index + 10] << 8) | RawData[index + 11]); + index += 12; + answer.Address = new byte[answer.DataLenght]; + for (int j = 0; j < answer.DataLenght; j++, index++) + { + answer.Address[j] = RawData[index]; + } + Answers.Add(answer); + } + } + } + + } +} diff --git a/source/Cosmos.System2/Network/IPv4/Address.cs b/source/Cosmos.System2/Network/IPv4/Address.cs index 15d70548d5..9f31bb94d4 100644 --- a/source/Cosmos.System2/Network/IPv4/Address.cs +++ b/source/Cosmos.System2/Network/IPv4/Address.cs @@ -1,4 +1,11 @@ -using System; +/* +* PROJECT: Aura Operating System Development +* CONTENT: IP Address +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; namespace Cosmos.System.Network.IPv4 { @@ -69,12 +76,18 @@ public static Address Parse(string adr) string[] fragments = adr.Split('.'); if (fragments.Length == 4) { - byte first = byte.Parse(fragments[0]); - byte second = byte.Parse(fragments[1]); - byte third = byte.Parse(fragments[2]); - byte fourth = byte.Parse(fragments[3]); - - return new Address(first, second, third, fourth); + try + { + byte first = byte.Parse(fragments[0]); + byte second = byte.Parse(fragments[1]); + byte third = byte.Parse(fragments[2]); + byte fourth = byte.Parse(fragments[3]); + return new Address(first, second, third, fourth); + } + catch + { + return null; + } } else { @@ -82,6 +95,24 @@ public static Address Parse(string adr) } } + /// + /// Convert CIDR number to IPv4 Address + /// + /// CIDR number. + /// + public static Address CIDRToAddress(int cidr) + { + try + { + uint mask = 0xffffffff << (32 - cidr); + return new Address((byte)(mask >> 24), (byte)(mask >> 16 & 0xff), (byte)(mask >> 8 & 0xff), (byte)(mask & 0xff)); + } + catch + { + return null; + } + } + /// /// Check if address is a loopback address. /// diff --git a/source/Cosmos.System2/Network/IPv4/EndPoint.cs b/source/Cosmos.System2/Network/IPv4/EndPoint.cs index 33d6760153..9b3ea91908 100644 --- a/source/Cosmos.System2/Network/IPv4/EndPoint.cs +++ b/source/Cosmos.System2/Network/IPv4/EndPoint.cs @@ -1,7 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +/* +* PROJECT: Aura Operating System Development +* CONTENT: End point +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; namespace Cosmos.System.Network.IPv4 { diff --git a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs index 8d4a28b29e..741aa3487f 100644 --- a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs @@ -1,11 +1,18 @@ -using System; +/* +* PROJECT: Aura Operating System Development +* CONTENT: ICMP Packet (to ping for exemple) +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; namespace Cosmos.System.Network.IPv4 { /// /// ICMPPacket class. See also: . /// - internal class ICMPPacket : IPPacket + public class ICMPPacket : IPPacket { /// /// Packet type. @@ -22,7 +29,6 @@ internal class ICMPPacket : IPPacket /// /// Received reply. /// - public static ICMPEchoReply recvd_reply; /// /// Create new inctanse of the class. @@ -36,12 +42,15 @@ internal static void ICMPHandler(byte[] packetData) switch (icmp_packet.ICMP_Type) { case 0: - recvd_reply = new ICMPEchoReply(packetData); - NetworkStack.debugger.Send("Received ICMP Echo reply from " + recvd_reply.SourceIP.ToString()); + ICMPClient receiver = ICMPClient.Client(icmp_packet.SourceIP.Hash); + if (receiver != null) + { + receiver.receiveData(icmp_packet); + } + NetworkStack.debugger.Send("Received ICMP Echo reply from " + icmp_packet.SourceIP.ToString()); break; case 8: ICMPEchoRequest request = new ICMPEchoRequest(packetData); - NetworkStack.debugger.Send("Received " + request.ToString()); ICMPEchoReply reply = new ICMPEchoReply(request); NetworkStack.debugger.Send("Sending ICMP Echo reply to " + reply.DestinationIP.ToString()); OutgoingBuffer.AddPacket(reply); @@ -63,8 +72,7 @@ public static void VMTInclude() /// internal ICMPPacket() : base() - { - } + { } /// /// Create new inctanse of the class. @@ -111,7 +119,8 @@ internal ICMPPacket(Address source, Address dest, byte type, byte code, ushort i RawData[DataOffset + 6] = (byte)((seq >> 8) & 0xFF); RawData[DataOffset + 7] = (byte)((seq >> 0) & 0xFF); - icmpCRC = CalcICMPCRC((ushort)(icmpDataSize + 8)); + icmpCRC = CalcICMPCRC((ushort)(icmpDataSize)); + RawData[DataOffset + 2] = (byte)((icmpCRC >> 8) & 0xFF); RawData[DataOffset + 3] = (byte)((icmpCRC >> 0) & 0xFF); initFields(); @@ -130,19 +139,31 @@ protected ushort CalcICMPCRC(ushort length) /// /// Get ICMP type. /// - internal byte ICMP_Type => icmpType; + internal byte ICMP_Type + { + get { return icmpType; } + } /// /// Get ICMP code. /// - internal byte ICMP_Code => icmpCode; + internal byte ICMP_Code + { + get { return icmpCode; } + } /// /// Get ICMP CRC. /// - internal ushort ICMP_CRC => icmpCRC; + internal ushort ICMP_CRC + { + get { return icmpCRC; } + } /// /// Get ICMP data length. /// - internal ushort ICMP_DataLength => (ushort)(DataLength - 8); + internal ushort ICMP_DataLength + { + get { return (ushort)(DataLength - 8); } + } /// /// Get ICMP data. @@ -182,8 +203,8 @@ internal class ICMPEchoRequest : ICMPPacket /// Create new inctanse of the class. /// internal ICMPEchoRequest() - { - } + : base() + { } /// /// Create new inctanse of the class. @@ -225,8 +246,14 @@ protected override void initFields() icmpSequence = (ushort)((RawData[DataOffset + 6] << 8) | RawData[DataOffset + 7]); } - internal ushort ICMP_ID => icmpID; - internal ushort ICMP_Sequence => icmpSequence; + internal ushort ICMP_ID + { + get { return icmpID; } + } + internal ushort ICMP_Sequence + { + get { return icmpSequence; } + } /// /// To string. @@ -237,6 +264,7 @@ public override string ToString() return "ICMP Echo Request Src=" + SourceIP + ", Dest=" + DestinationIP + ", ID=" + icmpID + ", Sequence=" + icmpSequence; } } + /// /// ICMPEchoReply class. See also: . /// @@ -249,8 +277,8 @@ internal class ICMPEchoReply : ICMPPacket /// Create new inctanse of the class. /// internal ICMPEchoReply() - { - } + : base() + { } /// /// Create new inctanse of the class. @@ -287,8 +315,7 @@ protected override void initFields() /// ICMP echo request. /// Thrown if RawData is invalid or null. internal ICMPEchoReply(ICMPEchoRequest request) - : base(request.DestinationIP, request.SourceIP, 0, 0, - request.ICMP_ID, request.ICMP_Sequence, (ushort)(request.ICMP_DataLength + 8)) + : base(request.DestinationIP, request.SourceIP, 0, 0, request.ICMP_ID, request.ICMP_Sequence, (ushort)(request.ICMP_DataLength)) { for (int b = 0; b < ICMP_DataLength; b++) { @@ -305,11 +332,17 @@ internal ICMPEchoReply(ICMPEchoRequest request) /// /// Get ICMP ID. /// - internal UInt16 ICMP_ID => icmpID; + internal ushort ICMP_ID + { + get { return icmpID; } + } /// /// Get ICMP sequence. /// - internal UInt16 ICMP_Sequence => icmpSequence; + internal ushort ICMP_Sequence + { + get { return icmpSequence; } + } /// /// To string. diff --git a/source/Cosmos.System2/Network/IPv4/IPPacket.cs b/source/Cosmos.System2/Network/IPv4/IPPacket.cs index 0d093a582e..e6503cd393 100644 --- a/source/Cosmos.System2/Network/IPv4/IPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/IPPacket.cs @@ -1,6 +1,16 @@ -using sys = System; +/* +* PROJECT: Aura Operating System Development +* CONTENT: IPv4 Packet +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; +using Cosmos.HAL; using Cosmos.HAL.Network; using Cosmos.System.Network.ARP; +using Cosmos.System.Network.IPv4.UDP; +using Cosmos.System.Network.IPv4.UDP.DHCP; namespace Cosmos.System.Network.IPv4 { @@ -48,6 +58,10 @@ internal static void IPv4Handler(byte[] packetData) break; } } + else if (NetworkStack.MACMap.ContainsKey(ip_packet.DestinationMAC.Hash)) + { + DHCPPacket.DHCPHandler(packetData); + } } /// @@ -105,6 +119,19 @@ protected IPPacket(ushort dataLength, byte protocol, Address source, Address des : this(MACAddress.None, MACAddress.None, dataLength, protocol, source, dest, Flags) { } + /// + /// Create new inctanse of the class. + /// + /// Data length. + /// Protocol. + /// Source address. + /// Destionation address. + /// Flags. + /// /// Mac address + protected IPPacket(ushort dataLength, byte protocol, Address source, Address dest, byte Flags, MACAddress broadcast) + : this(MACAddress.None, broadcast, dataLength, protocol, source, dest, Flags) + { } + /// /// Create new inctanse of the class. /// diff --git a/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs b/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs index 085847dcb9..890fb07068 100644 --- a/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs +++ b/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs @@ -1,10 +1,18 @@ -using sys = System; -using System.Collections.Generic; +/* +* PROJECT: Aura Operating System Development +* CONTENT: To send packets +* PROGRAMMERS: Valentin Charbonnier +* Alexy Da Cruz +* Port of Cosmos Code. +*/ -using Cosmos.Debug.Kernel; +using System.Collections.Generic; using Cosmos.HAL; -using Cosmos.HAL.Network; using Cosmos.System.Network.ARP; +using System; +using Cosmos.Debug.Kernel; +using Cosmos.System.Network.Config; +using Cosmos.HAL.Network; namespace Cosmos.System.Network.IPv4 { @@ -21,7 +29,8 @@ private class BufferEntry /// /// Entry status. /// - public enum EntryStatus { + public enum EntryStatus + { /// /// Added. /// @@ -45,7 +54,8 @@ public enum EntryStatus { /// /// DHCP request. /// - DHCP_REQUEST }; + DHCP_REQUEST + }; /// /// Network Interface Controller. @@ -108,7 +118,7 @@ private static void ensureQueueExists() internal static void AddPacket(IPPacket packet) { ensureQueueExists(); - NetworkDevice nic = Config.FindInterface(packet.SourceIP); + NetworkDevice nic = IPConfig.FindInterface(packet.SourceIP); packet.SourceMAC = nic.MACAddress; queue.Add(new BufferEntry(nic, packet)); } @@ -157,9 +167,9 @@ internal static void Send() BufferEntry entry = queue[e]; if (entry.Status == BufferEntry.EntryStatus.ADDED) { - if (Config.IsLocalAddress(entry.Packet.DestinationIP) == false) + if (IPConfig.IsLocalAddress(entry.Packet.DestinationIP) == false) { - entry.nextHop = Config.FindRoute(entry.Packet.DestinationIP); + entry.nextHop = IPConfig.FindRoute(entry.Packet.DestinationIP); if (entry.nextHop == null) { entry.Status = BufferEntry.EntryStatus.DONE; diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs index e5b0ba56d4..dfe7c1b73f 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs @@ -1,8 +1,16 @@ -using System; +/* +* PROJECT: Aura Operating System Development +* CONTENT: UDP Packet +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using Cosmos.HAL; +using Cosmos.HAL.Network; +using System; using System.Text; -using sysIO = System.IO; -namespace Cosmos.System.Network.IPv4 +namespace Cosmos.System.Network.IPv4.UDP { /// /// UDPPacket class. @@ -20,31 +28,28 @@ public class UDPPacket : IPPacket /// Packet data. /// Thrown if UDP_Data array length is greater than Int32.MaxValue. /// Thrown on IO error. + internal static void UDPHandler(byte[] packetData) { UDPPacket udp_packet = new UDPPacket(packetData); - NetworkStack.debugger.Send("Received UDP packet from " + udp_packet.SourceIP.ToString() + ":" + udp_packet.SourcePort.ToString()); + NetworkStack.debugger.Send("[Received] UDP packet from " + udp_packet.SourceIP.ToString() + ":" + udp_packet.SourcePort.ToString()); - if (CheckCRC(udp_packet)) + if (udp_packet.SourcePort == 67) { - - if (udp_packet.SourcePort == 68) - { - //Network.DHCP.DHCPPacket.DHCPHandler(packetData); - return; - } - - NetworkStack.debugger.Send("Content: " + Encoding.ASCII.GetString(udp_packet.UDP_Data)); - UdpClient receiver = UdpClient.Client(udp_packet.DestinationPort); - if (receiver != null) - { - receiver.receiveData(udp_packet); - } + DHCP.DHCPPacket.DHCPHandler(packetData); + return; } - else + else if (udp_packet.SourcePort == 53) { - NetworkStack.debugger.Send("But checksum incorrect... Packet Passed."); + DNS.DNSPacket.DNSHandler(packetData); + return; + } + + UdpClient receiver = UdpClient.Client(udp_packet.DestinationPort); + if (receiver != null) + { + receiver.receiveData(udp_packet); } } @@ -106,10 +111,7 @@ public static byte[] MakeHeader(byte[] sourceIP, byte[] destIP, UInt16 udpLen, U public static bool CheckCRC(UDPPacket packet) { byte[] header = MakeHeader(packet.SourceIP.address, packet.DestinationIP.address, packet.UDP_Length, packet.SourcePort, packet.DestinationPort, packet.UDP_Data); - UInt16 calculatedcrc = Check(header, 0, header.Length); - //NetworkStack.debugger.Send("Calculated: 0x" + Utils.Conversion.DecToHex(calculatedcrc)); - //NetworkStack.debugger.Send("Received: 0x" + Utils.Conversion.DecToHex(packet.udpCRC)); - if (calculatedcrc == packet.udpCRC) + if (CalcOcCRC(header, 0, header.Length) == packet.udpCRC) { return true; } @@ -119,27 +121,6 @@ public static bool CheckCRC(UDPPacket packet) } } - /// - /// Calculate CRC. - /// - /// Buffer. - /// Offset. - /// Length. - /// ushort value. - protected static ushort Check(byte[] buffer, ushort offset, int length) - { - uint crc = 0; - - for (ushort w = offset; w < offset + length; w += 2) - { - crc += (ushort)((buffer[w] << 8) | buffer[w + 1]); - } - - crc = (~((crc & 0xFFFF) + (crc >> 16))); - return (ushort)crc; - - } - /// /// Work around to make VMT scanner include the initFields method /// @@ -164,6 +145,20 @@ public UDPPacket(byte[] rawData) { } + public UDPPacket(Address source, Address dest, UInt16 srcport, UInt16 destport, UInt16 datalength) + : base((ushort)(datalength + 8), 17, source, dest, 0x00) + { + MakePacket(srcport, destport, datalength); + initFields(); + } + + public UDPPacket(Address source, Address dest, UInt16 srcport, UInt16 destport, UInt16 datalength, MACAddress destmac) + : base((ushort)(datalength + 8), 17, source, dest, 0x00, destmac) + { + MakePacket(srcport, destport, datalength); + initFields(); + } + /// /// Create new inctanse of the class. /// @@ -177,29 +172,31 @@ public UDPPacket(byte[] rawData) public UDPPacket(Address source, Address dest, ushort srcPort, ushort destPort, byte[] data) : base((ushort)(data.Length + 8), 17, source, dest, 0x00) { - RawData[DataOffset + 0] = (byte)((srcPort >> 8) & 0xFF); - RawData[DataOffset + 1] = (byte)((srcPort >> 0) & 0xFF); - RawData[DataOffset + 2] = (byte)((destPort >> 8) & 0xFF); - RawData[DataOffset + 3] = (byte)((destPort >> 0) & 0xFF); - UDP_Length = (ushort)(data.Length + 8); - - RawData[DataOffset + 4] = (byte)((UDP_Length >> 8) & 0xFF); - RawData[DataOffset + 5] = (byte)((UDP_Length >> 0) & 0xFF); - - byte[] header = MakeHeader(source.address, dest.address, UDP_Length, srcPort, destPort, data); - UInt16 calculatedcrc = Check(header, 0, header.Length); - - RawData[DataOffset + 6] = (byte)((calculatedcrc >> 8) & 0xFF); - RawData[DataOffset + 7] = (byte)((calculatedcrc >> 0) & 0xFF); + MakePacket(srcPort, destPort, (ushort)data.Length); for (int b = 0; b < data.Length; b++) { - RawData[DataOffset + 8 + b] = data[b]; + RawData[this.DataOffset + 8 + b] = data[b]; } initFields(); } + private void MakePacket(ushort srcport, ushort destport, ushort length) + { + RawData[this.DataOffset + 0] = (byte)((srcport >> 8) & 0xFF); + RawData[this.DataOffset + 1] = (byte)((srcport >> 0) & 0xFF); + RawData[this.DataOffset + 2] = (byte)((destport >> 8) & 0xFF); + RawData[this.DataOffset + 3] = (byte)((destport >> 0) & 0xFF); + UDP_Length = (ushort)(length + 8); + + RawData[this.DataOffset + 4] = (byte)((UDP_Length >> 8) & 0xFF); + RawData[this.DataOffset + 5] = (byte)((UDP_Length >> 0) & 0xFF); + + RawData[this.DataOffset + 6] = (byte)((0 >> 8) & 0xFF); + RawData[this.DataOffset + 7] = (byte)((0 >> 0) & 0xFF); + } + /// /// Init UDPPacket fields. /// diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs index 6d691b2d19..127b653594 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs @@ -1,46 +1,26 @@ -using System; -using Sys = System; +/* +* PROJECT: Aura Operating System Development +* CONTENT: UDP Client +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using Cosmos.System.Network.Config; +using System; using System.Collections.Generic; +using System.Text; -namespace Cosmos.System.Network +namespace Cosmos.System.Network.IPv4.UDP { /// /// UdpClient class. Used to manage the UDP connection to a client. /// public class UdpClient { - // TODO: Once we support more than just IPv4, we really need to base all the IPv4 classes on abstract classes - // that represent the required functionality, then we can generalize the stack to be independent from IPv4 or IPv6 - /// - /// Datagram class. - /// - internal class DataGram - { - /// - /// Data array. - /// - internal byte[] data; - /// - /// Source end point. - /// - internal IPv4.EndPoint source; - - /// - /// Create new inctanse of the class. - /// - /// Data array. - /// Source end point. - internal DataGram(byte[] data, IPv4.EndPoint src) - { - this.data = data; - this.source = src; - } - } - /// /// Clients dictionary. /// - private static TempDictionary clients; + private static TempDictionary clients; /// /// Local port. @@ -58,7 +38,7 @@ internal DataGram(byte[] data, IPv4.EndPoint src) /// /// RX buffer queue. /// - private Queue rxBuffer; + protected Queue rxBuffer; /// /// Assign clients dictionary. @@ -66,7 +46,7 @@ internal DataGram(byte[] data, IPv4.EndPoint src) /// Thrown on fatal error (contact support). static UdpClient() { - clients = new TempDictionary(); + clients = new TempDictionary(); } /// @@ -76,9 +56,9 @@ static UdpClient() /// UdpClient internal static UdpClient Client(ushort destPort) { - if (clients.ContainsKey((UInt32)destPort) == true) + if (clients.ContainsKey((uint)destPort) == true) { - return clients[(UInt32)destPort]; + return clients[(uint)destPort]; } return null; @@ -90,7 +70,7 @@ internal static UdpClient Client(ushort destPort) /// Thrown on fatal error (contact support). /// Thrown if UdpClient with localPort 0 exists. public UdpClient() - :this(0) + : this(0) { } /// @@ -99,14 +79,14 @@ public UdpClient() /// Local port. /// Thrown on fatal error (contact support). /// Thrown if localPort already exists. - public UdpClient(Int32 localPort) + public UdpClient(int localPort) { - this.rxBuffer = new Queue(8); + rxBuffer = new Queue(8); this.localPort = localPort; if (localPort > 0) { - UdpClient.clients.Add((UInt32)localPort, this); + clients.Add((uint)localPort, this); } } @@ -117,11 +97,11 @@ public UdpClient(Int32 localPort) /// Destination port. /// Thrown on fatal error (contact support). /// Thrown if UdpClient with localPort 0 exists. - public UdpClient(IPv4.Address dest, Int32 destPort) + public UdpClient(Address dest, int destPort) : this(0) { - this.destination = dest; - this.destinationPort = destPort; + destination = dest; + destinationPort = destPort; } /// @@ -129,10 +109,22 @@ public UdpClient(IPv4.Address dest, Int32 destPort) /// /// Destination address. /// Destination port. - public void Connect(IPv4.Address dest, Int32 destPort) + public void Connect(Address dest, int destPort) { - this.destination = dest; - this.destinationPort = destPort; + destination = dest; + destinationPort = destPort; + } + + /// + /// Close connection. + /// + /// Thrown on fatal error (contact support). + public void Close() + { + if (clients.ContainsKey((uint)localPort) == true) + { + clients.Remove((uint)localPort); + } } /// @@ -145,13 +137,13 @@ public void Connect(IPv4.Address dest, Int32 destPort) /// Thrown on IO error. public void Send(byte[] data) { - if ((this.destination == null) || - (this.destinationPort == 0)) + if ((destination == null) || (destinationPort == 0)) { throw new Exception("Must establish a default remote host by calling Connect() before using this Send() overload"); } - Send(data, this.destination, this.destinationPort); + Send(data, destination, destinationPort); + NetworkStack.Update(); } /// @@ -163,25 +155,31 @@ public void Send(byte[] data) /// Thrown on fatal error (contact support). /// Thrown if data array length is greater than Int32.MaxValue. /// Thrown on IO error. - public void Send(byte[] data, IPv4.Address dest, Int32 destPort) + public void Send(byte[] data, Address dest, int destPort) { - IPv4.Address source = IPv4.Config.FindNetwork(dest); - IPv4.UDPPacket packet = new IPv4.UDPPacket(source, dest, (UInt16)this.localPort, (UInt16)destPort, data); - - Sys.Console.WriteLine("Sending " + packet.ToString()); - IPv4.OutgoingBuffer.AddPacket(packet); + Address source = IPConfig.FindNetwork(dest); + UDPPacket packet = new UDPPacket(source, dest, (ushort)localPort, (ushort)destPort, data); + OutgoingBuffer.AddPacket(packet); } /// - /// Close connection. + /// Receive data from end point. /// - /// Thrown on fatal error (contact support). - public void Close() + /// Source end point. + /// byte array value. + /// Thrown on fatal error (contact support). + public byte[] NonBlockingReceive(ref EndPoint source) { - if (UdpClient.clients.ContainsKey((UInt32)this.localPort) == true) + if (rxBuffer.Count < 1) { - UdpClient.clients.Remove((UInt32)this.localPort); + return null; } + + UDPPacket packet = new UDPPacket(rxBuffer.Dequeue().RawData); + source.address = packet.SourceIP; + source.port = packet.SourcePort; + + return packet.UDP_Data; } /// @@ -190,18 +188,15 @@ public void Close() /// Source end point. /// byte array value. /// Thrown on fatal error (contact support). - public byte[] Receive(ref IPv4.EndPoint source) + public byte[] Receive(ref EndPoint source) { - if (this.rxBuffer.Count < 1) - { - return null; - } + while (rxBuffer.Count < 1) ; - DataGram packet = rxBuffer.Dequeue(); - source.address = packet.source.address; - source.port = packet.source.port; + UDPPacket packet = new UDPPacket(rxBuffer.Dequeue().RawData); + source.address = packet.SourceIP; + source.port = packet.SourcePort; - return packet.data; + return packet.UDP_Data; } /// @@ -210,14 +205,9 @@ public byte[] Receive(ref IPv4.EndPoint source) /// Packet to receive. /// Thrown on fatal error (contact support). /// Thrown on IO error. - internal void receiveData(IPv4.UDPPacket packet) + public void receiveData(UDPPacket packet) { - byte[] data = packet.UDP_Data; - IPv4.EndPoint source = new IPv4.EndPoint(packet.SourceIP, packet.SourcePort); - - Sys.Console.WriteLine("Received " + data.Length + " bytes data from " + source.ToString()); - - this.rxBuffer.Enqueue(new DataGram(data, source)); + rxBuffer.Enqueue(packet); } } } diff --git a/source/Cosmos.System2/Network/NetworkStack.cs b/source/Cosmos.System2/Network/NetworkStack.cs index 6ea9d2c6d6..8e6ef296b9 100644 --- a/source/Cosmos.System2/Network/NetworkStack.cs +++ b/source/Cosmos.System2/Network/NetworkStack.cs @@ -1,10 +1,18 @@ -using System; -using Sys = System; +/* +* PROJECT: Aura Operating System Development +* CONTENT: Network Intialization + Packet Handler +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; using System.Collections.Generic; +using Cosmos.Debug.Kernel; using Cosmos.HAL; using Cosmos.System.Network.ARP; +using Cosmos.System.Network.Config; using Cosmos.System.Network.IPv4; -using Cosmos.Debug.Kernel; +using Cosmos.System.Network.IPv4.UDP; namespace Cosmos.System.Network { @@ -21,7 +29,11 @@ public static class NetworkStack /// /// Get address dictionary. /// - internal static TempDictionary AddressMap { get; private set; } + internal static TempDictionary AddressMap { get; private set; } + /// + /// Get address dictionary. + /// + internal static TempDictionary MACMap { get; private set; } /// /// Initialize the Network Stack to prepare it for operation. @@ -29,7 +41,8 @@ public static class NetworkStack /// Thrown on fatal error (contact support). public static void Init() { - AddressMap = new TempDictionary(); + AddressMap = new TempDictionary(); + MACMap = new TempDictionary(); // VMT Scanner issue workaround ARPPacket.VMTInclude(); @@ -43,6 +56,20 @@ public static void Init() //TCPPacket.VMTInclude(); } + /// + /// Set ConfigIP for NetworkDevice + /// + /// Network device. + /// /// IP Config + private static void SetConfigIP(NetworkDevice nic, IPConfig config) + { + NetworkConfig.Add(nic, config); + AddressMap.Add(config.IPAddress.Hash, nic); + MACMap.Add(nic.MACAddress.Hash, nic); + IPConfig.Add(config); + nic.DataReceived = HandlePacket; + } + /// /// Configure a IP configuration on the given network device. /// Multiple IP Configurations can be made, like *nix environments @@ -59,11 +86,64 @@ public static void Init() /// Thrown on fatal error (contact support). /// Thrown on IO error. /// Thrown on fatal error (contact support). - public static void ConfigIP(NetworkDevice nic, Config config) + public static void ConfigIP(NetworkDevice nic, IPConfig config) { - AddressMap.Add(config.IPAddress.Hash, nic); - Config.Add(config); - nic.DataReceived = HandlePacket; + if (NetworkConfig.ContainsKey(nic)) + { + RemoveIPConfig(nic); + SetConfigIP(nic, config); + } + else + { + SetConfigIP(nic, config); + } + NetworkConfig.CurrentConfig = new KeyValuePair(nic, config); + } + + /// + /// Check if Config is empty + /// bool value. + /// + public static bool ConfigEmpty() + { + int counter = 0; + + foreach (NetworkDevice device in NetworkConfig.Keys) + { + counter++; + } + if (counter == 0) + { + return true; + } + else + { + return false; + } + } + + /// + /// Remove All IPConfig + /// + public static void RemoveAllConfigIP() + { + AddressMap.Clear(); + MACMap.Clear(); + IPConfig.RemoveAll(); + NetworkConfig.Clear(); + } + + /// + /// Remove IPConfig + /// + /// Network device. + public static void RemoveIPConfig(NetworkDevice nic) + { + IPConfig config = NetworkConfig.Get(nic); + AddressMap.Remove(config.IPAddress.Hash); + MACMap.Remove(nic.MACAddress.Hash); + IPConfig.Remove(config); + NetworkConfig.Remove(nic); } /// diff --git a/source/Cosmos.System2/Network/TempDictionary.cs b/source/Cosmos.System2/Network/TempDictionary.cs index 2b95bc9b16..72c0715649 100644 --- a/source/Cosmos.System2/Network/TempDictionary.cs +++ b/source/Cosmos.System2/Network/TempDictionary.cs @@ -1,4 +1,11 @@ -using System; +/* +* PROJECT: Aura Operating System Development +* CONTENT: An other dictionnary class +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; using System.Collections.Generic; namespace Cosmos.System.Network @@ -7,9 +14,9 @@ namespace Cosmos.System.Network /// TempDictionary template class. /// /// TempDictionary type name. - internal class TempDictionary + internal class TempDictionary { - private List mKeys; + private List mKeys; private List mValues; /// @@ -22,7 +29,7 @@ internal class TempDictionary /// /// Thrown on fatal error (contact support). public TempDictionary() - :this(2) + : this(2) { } /// @@ -32,14 +39,14 @@ public TempDictionary() /// Thrown if initialSize is less than 0. public TempDictionary(int initialSize) { - this.mKeys = new List(initialSize); + this.mKeys = new List(initialSize); this.mValues = new List(initialSize); } /// /// Get TempDictionary{TValue} keys array. /// - public UInt32[] Keys + public TKey[] Keys { get { @@ -70,7 +77,7 @@ public TValue this[UInt32 key] { for (int i = 0; i < mKeys.Count; i++) { - if (mKeys[i].CompareTo(key) == 0) + if (mKeys[i].Equals(key)) { return mValues[i]; } @@ -82,7 +89,7 @@ public TValue this[UInt32 key] { for (int i = 0; i < mKeys.Count; i++) { - if (mKeys[i].CompareTo(key) == 0) + if (mKeys[i].Equals(key)) { mValues[i] = value; return; @@ -98,11 +105,11 @@ public TValue this[UInt32 key] /// /// Key to check if exists. /// bool value. - public bool ContainsKey(UInt32 key) + public bool ContainsKey(TKey key) { for (int i = 0; i < mKeys.Count; i++) { - if (mKeys[i] == key) + if (mKeys[i].Equals(key)) { return true; } @@ -117,7 +124,7 @@ public bool ContainsKey(UInt32 key) /// Object key. /// Object value. /// Thrown if key already exists. - public void Add(UInt32 key, TValue val) + public void Add(TKey key, TValue val) { if (ContainsKey(key) == true) { @@ -133,7 +140,7 @@ public void Add(UInt32 key, TValue val) /// /// Key of the item to remove. /// Thrown on fatal error (contact support). - public void Remove(UInt32 key) + public void Remove(TKey key) { int idx = mKeys.IndexOf(key); if (idx != -1) From 053902b3eae67e67e1d53bd6404665597e369cd2 Mon Sep 17 00:00:00 2001 From: KM198912 <55886806+KM198912@users.noreply.github.com> Date: Wed, 13 Jan 2021 09:01:27 +0100 Subject: [PATCH 018/314] Update RestoreSources.props myget currently has a issue where it cant find roslyn-tools, so disable it for the time being so the devkit builds --- build/Targets/RestoreSources.props | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build/Targets/RestoreSources.props b/build/Targets/RestoreSources.props index 0043818b38..30d4275242 100644 --- a/build/Targets/RestoreSources.props +++ b/build/Targets/RestoreSources.props @@ -8,8 +8,7 @@ https://www.myget.org/F/cosmos/api/v3/index.json; https://ci.appveyor.com/nuget/cosmos-common; https://ci.appveyor.com/nuget/il2cpu; - https://ci.appveyor.com/nuget/xsharp; - https://dotnet.myget.org/F/roslyn-tools/api/v3/index.json + https://ci.appveyor.com/nuget/xsharp $(RestoreSources);$(DefaultPackageOutputPath) From ee9e7fe15eea12ce2f297c14101fd300b5e3bee2 Mon Sep 17 00:00:00 2001 From: Quajak Date: Wed, 13 Jan 2021 10:36:22 +0100 Subject: [PATCH 019/314] Revert "Implement non linear framebuffer detection for VBE multiboot" --- source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs b/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs index f50d52a2fe..b7174ef8a7 100644 --- a/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs +++ b/source/Cosmos.HAL2/Drivers/Video/VBEDriver.cs @@ -81,21 +81,8 @@ public VBEDriver(ushort xres, ushort yres, ushort bpp) if (VBE.IsAvailable()) //VBE VESA Enabled Mulitboot Parsing { Global.mDebugger.SendInternal($"Creating VBE VESA driver with Mode {xres}*{yres}@{bpp}"); - - var ModeInfo = VBE.getModeInfo(); - - if ((ModeInfo.pitch / (bpp / 8)) == ModeInfo.width) //linear framebuffer detection - { - IO.LinearFrameBuffer = new MemoryBlock(VBE.getLfbOffset(), (uint)xres * yres * (uint)(bpp / 8)); - lastbuffer = new ManagedMemoryBlock((uint)xres * yres * (uint)(bpp / 8)); - } - else - { - uint OffScreenSize = (ModeInfo.pitch / (uint)(bpp / 8)) - ModeInfo.width; - - IO.LinearFrameBuffer = new MemoryBlock(VBE.getLfbOffset(), (uint)(xres * yres * (uint)(bpp / 8)) + (OffScreenSize * yres * (uint)(bpp / 8))); - lastbuffer = new ManagedMemoryBlock((uint)(xres * yres * (uint)(bpp / 8)) + (OffScreenSize * yres * (uint)(bpp / 8))); - } + IO.LinearFrameBuffer = new MemoryBlock(VBE.getLfbOffset(), (uint)xres * yres * (uint)(bpp / 8)); + lastbuffer = new ManagedMemoryBlock((uint)xres * yres * (uint)(bpp / 8)); } else if (ISAModeAvailable()) //Bochs Graphics Adaptor ISA Mode { From 9225e210c2bfe8e7be9664161a361f07dbfaf46e Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Sat, 16 Jan 2021 15:44:56 -0500 Subject: [PATCH 020/314] Update InterlockedImpl.cs --- .../System/Threading/InterlockedImpl.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/source/Cosmos.Core_Plugs/System/Threading/InterlockedImpl.cs b/source/Cosmos.Core_Plugs/System/Threading/InterlockedImpl.cs index 751e5909c4..89929b89a3 100644 --- a/source/Cosmos.Core_Plugs/System/Threading/InterlockedImpl.cs +++ b/source/Cosmos.Core_Plugs/System/Threading/InterlockedImpl.cs @@ -1,3 +1,4 @@ +using System; using System.Threading; using IL2CPU.API.Attribs; @@ -10,9 +11,62 @@ public static int Decrement(ref int aData) { return aData -= 1; } + public static long Decrement(ref long aData) + { + return aData -= 1; + } public static int Increment(ref int aData) { return aData += 1; } + public static long Increment(ref long aData) + { + return aData += 1; + } + public static int Exchange(ref int loc1, int aData) + { + int orgValue = loc1; + loc1 = aData; + return orgValue; + } + public static long Exchange(ref long loc1, long aData) + { + long orgValue = loc1; + loc1 = aData; + return orgValue; + } + public static float Exchange(ref float loc1, float aData) + { + float orgValue = loc1; + loc1 = aData; + return orgValue; + } + public static double Exchange(ref double loc1, double aData) + { + double orgValue = loc1; + loc1 = aData; + return orgValue; + } + public static Object Exchange(ref Object loc1, Object aData) + { + Object orgValue = loc1; + loc1 = aData; + return orgValue; + } + public static IntPtr Exchange(ref IntPtr loc1, IntPtr aData) + { + IntPtr orgValue = loc1; + loc1 = aData; + return orgValue; + } + public static EventHandler CompareExchange(ref EventHandler loc1, EventHandler val, EventHandler comparand) + { + EventHandler old = loc1; + if (loc1 == comparand) + { + loc1 = val; + } + return old; + } } } From cf8d41686e5a3bbb2cb23cf208b45b3d0c60f032 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 19 Jan 2021 18:07:45 +0100 Subject: [PATCH 021/314] Make Enable public --- source/Cosmos.System2/Network/Config/IPConfig.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.System2/Network/Config/IPConfig.cs b/source/Cosmos.System2/Network/Config/IPConfig.cs index 8bbdbdeb83..f248388c0d 100644 --- a/source/Cosmos.System2/Network/Config/IPConfig.cs +++ b/source/Cosmos.System2/Network/Config/IPConfig.cs @@ -90,7 +90,7 @@ internal static Address FindNetwork(Address destIP) return default_gw; } - internal static bool Enable(NetworkDevice device, Address ip, Address subnet, Address gw) + public static bool Enable(NetworkDevice device, Address ip, Address subnet, Address gw) { if (device != null) { From c310d5453580aa3a8a5f5f705e1ac512d7e5305d Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 10:41:34 +0100 Subject: [PATCH 022/314] Use Global debugger For some unknown reasons, NetworkStack debugger is not working --- source/Cosmos.HAL2/Global.cs | 4 +++- source/Cosmos.System2/Global.cs | 5 ++++- source/Cosmos.System2/Network/ARP/ARPPacket.cs | 10 +++++----- .../Network/ARP/ARPPacket_Ethernet.cs | 4 ++-- .../Cosmos.System2/Network/Config/IPConfig.cs | 2 +- .../Network/IPV4/UDP/DHCP/DHCPClient.cs | 14 +++++++------- .../Network/IPV4/UDP/DNS/DNSPacket.cs | 2 +- .../Cosmos.System2/Network/IPv4/ICMPPacket.cs | 6 +++--- source/Cosmos.System2/Network/IPv4/IPPacket.cs | 2 +- .../Network/IPv4/OutgoingBuffer.cs | 2 +- .../Network/IPv4/UDP/UDPPacket.cs | 2 +- source/Cosmos.System2/Network/NetworkStack.cs | 17 ++++------------- 12 files changed, 33 insertions(+), 37 deletions(-) diff --git a/source/Cosmos.HAL2/Global.cs b/source/Cosmos.HAL2/Global.cs index 5bd14cba29..cc801aa9d9 100644 --- a/source/Cosmos.HAL2/Global.cs +++ b/source/Cosmos.HAL2/Global.cs @@ -4,6 +4,7 @@ using Cosmos.Core; using Cosmos.Debug.Kernel; using Cosmos.HAL.BlockDevice; +using Cosmos.HAL.Network; namespace Cosmos.HAL { @@ -63,7 +64,8 @@ static public void Init(TextScreenBase textScreen) AHCI.InitDriver(); //EHCI.InitDriver(); - Network.NetworkInit.Init(); + mDebugger.Send("Network Devices Init"); + NetworkInit.Init(); mDebugger.Send("Done initializing Cosmos.HAL.Global"); diff --git a/source/Cosmos.System2/Global.cs b/source/Cosmos.System2/Global.cs index 2fc541ed94..bc2320d306 100644 --- a/source/Cosmos.System2/Global.cs +++ b/source/Cosmos.System2/Global.cs @@ -86,10 +86,13 @@ public static void Init(TextScreenBase textScreen) mDebugger.Send("HW Init"); HAL.Global.Init(textScreen); + + Network.NetworkStack.Init(); + mDebugger.Send("Network Stack Init"); + NumLock = false; CapsLock = false; ScrollLock = false; - Network.NetworkStack.Init(); } /// diff --git a/source/Cosmos.System2/Network/ARP/ARPPacket.cs b/source/Cosmos.System2/Network/ARP/ARPPacket.cs index 196cd8cf3b..f1aaa84590 100644 --- a/source/Cosmos.System2/Network/ARP/ARPPacket.cs +++ b/source/Cosmos.System2/Network/ARP/ARPPacket.cs @@ -58,7 +58,7 @@ internal static void ARPHandler(byte[] packetData) ARPRequest_Ethernet arp_request = new ARPRequest_Ethernet(packetData); if (arp_request.SenderIP == null) { - NetworkStack.debugger.Send("SenderIP null in ARPHandler!"); + Global.mDebugger.Send("SenderIP null in ARPHandler!"); } arp_request = new ARPRequest_Ethernet(packetData); @@ -66,7 +66,7 @@ internal static void ARPHandler(byte[] packetData) if (NetworkStack.AddressMap.ContainsKey(arp_request.TargetIP.Hash) == true) { - NetworkStack.debugger.Send("ARP Request Recvd from " + arp_request.SenderIP.ToString()); + Global.mDebugger.Send("ARP Request Recvd from " + arp_request.SenderIP.ToString()); NetworkDevice nic = NetworkStack.AddressMap[arp_request.TargetIP.Hash]; ARPReply_Ethernet reply = @@ -81,9 +81,9 @@ internal static void ARPHandler(byte[] packetData) if ((arp_packet.HardwareType == 1) && (arp_packet.ProtocolType == 0x0800)) { ARPReply_Ethernet arp_reply = new ARPReply_Ethernet(packetData); - NetworkStack.debugger.Send("Received ARP Reply"); - NetworkStack.debugger.Send(arp_reply.ToString()); - NetworkStack.debugger.Send("ARP Reply Recvd from " + arp_reply.SenderIP.ToString()); + Global.mDebugger.Send("Received ARP Reply"); + Global.mDebugger.Send(arp_reply.ToString()); + Global.mDebugger.Send("ARP Reply Recvd from " + arp_reply.SenderIP.ToString()); ARPCache.Update(arp_reply.SenderIP, arp_reply.SenderMAC); OutgoingBuffer.ARPCache_Update(arp_reply); diff --git a/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs b/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs index c4c60375c6..cd7eeea929 100644 --- a/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs +++ b/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs @@ -62,7 +62,7 @@ protected override void initFields() mSenderIP = new Address(RawData, 28); if (SenderIP == null) { - NetworkStack.debugger.Send("But its already null again"); + Global.mDebugger.Send("But its already null again"); } mTargetMAC = new MACAddress(RawData, 32); mTargetIP = new Address(RawData, 38); @@ -219,7 +219,7 @@ internal ARPRequest_Ethernet(byte[] rawData) { if (SenderIP == null) { - NetworkStack.debugger.Send("In ARPRequest_Ethernet, SenderIP is null!"); + Global.mDebugger.Send("In ARPRequest_Ethernet, SenderIP is null!"); } } diff --git a/source/Cosmos.System2/Network/Config/IPConfig.cs b/source/Cosmos.System2/Network/Config/IPConfig.cs index f248388c0d..c04c09d751 100644 --- a/source/Cosmos.System2/Network/Config/IPConfig.cs +++ b/source/Cosmos.System2/Network/Config/IPConfig.cs @@ -96,7 +96,7 @@ public static bool Enable(NetworkDevice device, Address ip, Address subnet, Addr { var config = new IPConfig(ip, subnet, gw); NetworkStack.ConfigIP(device, config); - NetworkStack.debugger.Send(config.ToString()); + Global.mDebugger.Send("Config OK."); return true; } return false; diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs index b78b38cf9d..95645a9b83 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs @@ -198,17 +198,17 @@ private void Apply(DHCPAck packet, bool message = false) packet.Client.ToString() == null || packet.Client.ToString() == null) { - NetworkStack.debugger.Send("Parsing DHCP ACK Packet failed, can't apply network configuration."); + Global.mDebugger.Send("Parsing DHCP ACK Packet failed, can't apply network configuration."); } else { if (message) { - NetworkStack.debugger.Send("[DHCP ACK][" + networkDevice.Name + "] Packet received, applying IP configuration..."); - NetworkStack.debugger.Send(" IP Address : " + packet.Client.ToString()); - NetworkStack.debugger.Send(" Subnet mask : " + packet.Subnet.ToString()); - NetworkStack.debugger.Send(" Gateway : " + packet.Server.ToString()); - NetworkStack.debugger.Send(" DNS server : " + packet.DNS.ToString()); + Global.mDebugger.Send("[DHCP ACK][" + networkDevice.Name + "] Packet received, applying IP configuration..."); + Global.mDebugger.Send(" IP Address : " + packet.Client.ToString()); + Global.mDebugger.Send(" Subnet mask : " + packet.Subnet.ToString()); + Global.mDebugger.Send(" Gateway : " + packet.Server.ToString()); + Global.mDebugger.Send(" DNS server : " + packet.DNS.ToString()); } IPConfig.Enable(networkDevice, packet.Client, packet.Subnet, packet.Server); @@ -216,7 +216,7 @@ private void Apply(DHCPAck packet, bool message = false) if (message) { - NetworkStack.debugger.Send("[DHCP CONFIG][" + networkDevice.Name + "] IP configuration applied."); + Global.mDebugger.Send("[DHCP CONFIG][" + networkDevice.Name + "] IP configuration applied."); asked = false; } } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs index b09df143fc..89fd171d5d 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs @@ -329,7 +329,7 @@ protected override void initFields() if ((ushort)(DNSFlags & 0x0F) != (ushort)ReplyCode.OK) { - NetworkStack.debugger.Send("DNS Packet response not OK. Passing packet."); + Global.mDebugger.Send("DNS Packet response not OK. Passing packet."); return; } diff --git a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs index 741aa3487f..f47acd641e 100644 --- a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs @@ -37,7 +37,7 @@ public class ICMPPacket : IPPacket /// Thrown if packetData is invalid. internal static void ICMPHandler(byte[] packetData) { - NetworkStack.debugger.Send("ICMP Handler called"); + Global.mDebugger.Send("ICMP Handler called"); ICMPPacket icmp_packet = new ICMPPacket(packetData); switch (icmp_packet.ICMP_Type) { @@ -47,12 +47,12 @@ internal static void ICMPHandler(byte[] packetData) { receiver.receiveData(icmp_packet); } - NetworkStack.debugger.Send("Received ICMP Echo reply from " + icmp_packet.SourceIP.ToString()); + Global.mDebugger.Send("Received ICMP Echo reply from " + icmp_packet.SourceIP.ToString()); break; case 8: ICMPEchoRequest request = new ICMPEchoRequest(packetData); ICMPEchoReply reply = new ICMPEchoReply(request); - NetworkStack.debugger.Send("Sending ICMP Echo reply to " + reply.DestinationIP.ToString()); + Global.mDebugger.Send("Sending ICMP Echo reply to " + reply.DestinationIP.ToString()); OutgoingBuffer.AddPacket(reply); NetworkStack.Update(); break; diff --git a/source/Cosmos.System2/Network/IPv4/IPPacket.cs b/source/Cosmos.System2/Network/IPv4/IPPacket.cs index e6503cd393..dfd4d230a5 100644 --- a/source/Cosmos.System2/Network/IPv4/IPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/IPPacket.cs @@ -38,7 +38,7 @@ internal static void IPv4Handler(byte[] packetData) //Sys.Console.WriteLine(ip_packet.ToString()); if (ip_packet.SourceIP == null) { - NetworkStack.debugger.Send("SourceIP null in IPv4Handler!"); + Global.mDebugger.Send("SourceIP null in IPv4Handler!"); } ARPCache.Update(ip_packet.SourceIP, ip_packet.SourceMAC); diff --git a/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs b/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs index 890fb07068..a948401310 100644 --- a/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs +++ b/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs @@ -157,7 +157,7 @@ internal static void Send() if (second >= 4) { - NetworkStack.debugger.Send("No response in 4 secondes..."); + Global.mDebugger.Send("No response in 4 secondes..."); break; } diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs index dfe7c1b73f..1661663580 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs @@ -33,7 +33,7 @@ internal static void UDPHandler(byte[] packetData) { UDPPacket udp_packet = new UDPPacket(packetData); - NetworkStack.debugger.Send("[Received] UDP packet from " + udp_packet.SourceIP.ToString() + ":" + udp_packet.SourcePort.ToString()); + Global.mDebugger.Send("[Received] UDP packet from " + udp_packet.SourceIP.ToString() + ":" + udp_packet.SourcePort.ToString()); if (udp_packet.SourcePort == 67) { diff --git a/source/Cosmos.System2/Network/NetworkStack.cs b/source/Cosmos.System2/Network/NetworkStack.cs index 8e6ef296b9..6eec1c1d8c 100644 --- a/source/Cosmos.System2/Network/NetworkStack.cs +++ b/source/Cosmos.System2/Network/NetworkStack.cs @@ -5,6 +5,8 @@ * Port of Cosmos Code. */ +#define COSMOSDEBUG + using System; using System.Collections.Generic; using Cosmos.Debug.Kernel; @@ -43,17 +45,6 @@ public static void Init() { AddressMap = new TempDictionary(); MACMap = new TempDictionary(); - - // VMT Scanner issue workaround - ARPPacket.VMTInclude(); - ARPPacket_Ethernet.VMTInclude(); - ARPReply_Ethernet.VMTInclude(); - ARPRequest_Ethernet.VMTInclude(); - ICMPPacket.VMTInclude(); - ICMPEchoReply.VMTInclude(); - ICMPEchoRequest.VMTInclude(); - UDPPacket.VMTInclude(); - //TCPPacket.VMTInclude(); } /// @@ -156,10 +147,10 @@ public static void RemoveIPConfig(NetworkDevice nic) /// Thrown on fatal error (contact support). internal static void HandlePacket(byte[] packetData) { - debugger.Send("Packet Received Length=" + packetData.Length.ToString()); + Global.mDebugger.Send("Packet Received Length=" + packetData.Length.ToString()); if (packetData == null) { - debugger.Send("Error packet data null"); + Global.mDebugger.Send("Error packet data null"); return; } From 3c18c68c8ef6eb0b6c5703a81de6b0553540bf8e Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 14:49:31 +0100 Subject: [PATCH 023/314] Fix IRQ --- source/Cosmos.Core/PIC.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.Core/PIC.cs b/source/Cosmos.Core/PIC.cs index 266152047f..e8b44ce048 100644 --- a/source/Cosmos.Core/PIC.cs +++ b/source/Cosmos.Core/PIC.cs @@ -129,8 +129,8 @@ private void Remap(byte masterStart, byte masterMask, byte slaveStart, byte slav // set masks: Master.Data.Byte = masterMask; IOPort.Wait(); - Slave.Data.Byte = slaveMask; - IOPort.Wait(); + //Slave.Data.Byte = slaveMask; + //IOPort.Wait(); } /// From 89c4fc2da318e2b30649416750941452f771dfce Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 14:52:03 +0100 Subject: [PATCH 024/314] Remove useless debug --- source/Cosmos.System2/Network/NetworkStack.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/source/Cosmos.System2/Network/NetworkStack.cs b/source/Cosmos.System2/Network/NetworkStack.cs index 6eec1c1d8c..6b45c266cb 100644 --- a/source/Cosmos.System2/Network/NetworkStack.cs +++ b/source/Cosmos.System2/Network/NetworkStack.cs @@ -147,7 +147,6 @@ public static void RemoveIPConfig(NetworkDevice nic) /// Thrown on fatal error (contact support). internal static void HandlePacket(byte[] packetData) { - Global.mDebugger.Send("Packet Received Length=" + packetData.Length.ToString()); if (packetData == null) { Global.mDebugger.Send("Error packet data null"); From 4872875f5bd10c5abfa588b050cd8dcbdeed1cfe Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 15:15:37 +0100 Subject: [PATCH 025/314] Add NetworkTest --- .../Cosmos.TestRunner.Full.csproj | 1 + .../Cosmos.TestRunner.Full/TestKernelSets.cs | 1 + Tests/Kernels/NetworkTest/Kernel.cs | 47 +++++++++++++++++++ Tests/Kernels/NetworkTest/NetworkTest.csproj | 14 ++++++ 4 files changed, 63 insertions(+) create mode 100644 Tests/Kernels/NetworkTest/Kernel.cs create mode 100644 Tests/Kernels/NetworkTest/NetworkTest.csproj diff --git a/Tests/Cosmos.TestRunner.Full/Cosmos.TestRunner.Full.csproj b/Tests/Cosmos.TestRunner.Full/Cosmos.TestRunner.Full.csproj index e9ad60390a..aa2fb1739a 100644 --- a/Tests/Cosmos.TestRunner.Full/Cosmos.TestRunner.Full.csproj +++ b/Tests/Cosmos.TestRunner.Full/Cosmos.TestRunner.Full.csproj @@ -29,6 +29,7 @@ + diff --git a/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs b/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs index 07af2745ba..e988fe34b0 100644 --- a/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs +++ b/Tests/Cosmos.TestRunner.Full/TestKernelSets.cs @@ -31,6 +31,7 @@ public static IEnumerable GetStableKernelTypes() //yield return typeof(KernelGen3.Boot); yield return typeof(GraphicTest.Kernel); + yield return typeof(NetworkTest.Kernel); /* Please see the notes on the kernel itself before enabling it */ //yield return typeof(ConsoleTest.Kernel); /* This is a bit slow and works only because ring check is disabled to decide if leave it enabled */ diff --git a/Tests/Kernels/NetworkTest/Kernel.cs b/Tests/Kernels/NetworkTest/Kernel.cs new file mode 100644 index 0000000000..6cd544c24c --- /dev/null +++ b/Tests/Kernels/NetworkTest/Kernel.cs @@ -0,0 +1,47 @@ +using Cosmos.HAL; +using Cosmos.System.Network.Config; +using Cosmos.System.Network.IPv4; +using Cosmos.System.Network.IPv4.UDP; +using Cosmos.TestRunner; +using System; +using System.Collections.Generic; +using System.Text; +using Sys = Cosmos.System; + +namespace NetworkTest +{ + public class Kernel : Sys.Kernel + { + protected override void BeforeRun() + { + } + + protected override void Run() + { + /** IPConfig Enable test **/ + mDebugger.Send($"Testing IPConfig.Enable"); + //get nic by name + NetworkDevice nic = NetworkDevice.GetDeviceByName("eth0"); + if (Equals(nic, null)) + { + mDebugger.Send($"eth0 not found."); + TestController.Failed(); + } + //Enable network config + IPConfig.Enable(nic, new Address(192, 168, 1, 69), new Address(255, 255, 255, 0), new Address(192, 168, 1, 254)); + + Address ip = new Address(192, 168, 1, 70); + int port = 4242; + string message = "Hello from Cosmos!"; + + /** Udp test **/ + var xClient = new UdpClient(port); + xClient.Connect(ip, port); + xClient.Send(Encoding.ASCII.GetBytes(message)); + mDebugger.Send("Sent UDP packet to " + ip.ToString() + ":" + port); + xClient.Close(); + + TestController.Completed(); + } + } +} diff --git a/Tests/Kernels/NetworkTest/NetworkTest.csproj b/Tests/Kernels/NetworkTest/NetworkTest.csproj new file mode 100644 index 0000000000..d6e0d7a18b --- /dev/null +++ b/Tests/Kernels/NetworkTest/NetworkTest.csproj @@ -0,0 +1,14 @@ + + + + netcoreapp2.0 + True + + + + + + + + + From b24c006befec85b702df6581a1c73ffe21c26093 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 15:28:43 +0100 Subject: [PATCH 026/314] Begin article. --- Docs/articles/Kernel/Network.md | 3 +++ Docs/articles/toc.md | 1 + 2 files changed, 4 insertions(+) create mode 100644 Docs/articles/Kernel/Network.md diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md new file mode 100644 index 0000000000..bbda1c0e0a --- /dev/null +++ b/Docs/articles/Kernel/Network.md @@ -0,0 +1,3 @@ +# Network + +In this article we will discuss about Networking on Cosmos, how the use the Network Stack, send and received packets. \ No newline at end of file diff --git a/Docs/articles/toc.md b/Docs/articles/toc.md index be98130663..99ddec63c6 100644 --- a/Docs/articles/toc.md +++ b/Docs/articles/toc.md @@ -19,6 +19,7 @@ ## [Startup](Kernel/Startup.md) ## [Graphics](Kernel/CGS.md) ## [Virtual File System](Kernel/VFS.md) +## [Network](Kernel/Network.md) # Reference ## [x86](Reference/x86.md) From e0c754a5b1d7974b403337ccb93be3743d27a806 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 18:48:39 +0100 Subject: [PATCH 027/314] Update Network.md --- Docs/articles/Kernel/Network.md | 77 ++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index bbda1c0e0a..bbbd948a6f 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -1,3 +1,78 @@ # Network -In this article we will discuss about Networking on Cosmos, how the use the Network Stack, send and received packets. \ No newline at end of file +In this article we will discuss about Networking on Cosmos, how to use the Network Stack, send and received packets. For now, availables protocols are **ARP**, **IPv4**, **UDP**, **ICMP**, **DHCP** and **DNS** but the team is also working on TCP. + +All protocols here doesn't support every feature described by their RFC and may have some bugs or architecture issues, if you find something anormal please [submit an issue](http://https://github.com/CosmosOS/Cosmos/issues/new/choose "repository") on our repository. + +Each protocol have a Client class wich 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 optionnaly 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: +```csharp +using Cosmos.System.Network; +``` + +Before anything, a Network Configuration must be set (local machine IPv4 address, subnet mask and gateway). It can be manually set with IPConfig.Enable or dynamically set throught a DHCP server. For DHCP, Cosmos will ask to the DHCP server (usually default gateway) for an address in your local network. + +### Manually set IPv4 Config +```csharp +NetworkDevice nic = NetworkDevice.GetDeviceByName("eth0"); //get network device by name +IPConfig.Enable(nic, new Address(192, 168, 1, 69), new Address(255, 255, 255, 0), new Address(192, 168, 1, 254)); //enable IPv4 configuration +``` +### Dynamically set IPv4 Config through DHCP +```csharp +var xClient = new DHCPClient(); + +/** Send a DHCP Discover packet **/ +//This will automatically set the IP config after DHCP response +xClient.SendDiscoverPacket(); + +/** Send a DHCP Release packet **/ +xClient.SendReleasePacket(); //will tell the DHCP server to delete the address + +xClient.Close(); +``` + +## 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 +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); +xClient.Receive(ref endpoint); //set endpoint to remote machine IP:port +xClient.NonBlockingReceive(ref endpoint); //retrieve receive buffer without waiting + +xClient.Close(); //don't forget to close! +``` + +## ICMP +For ICMP, we will only 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 +var xClient = new ICMPClient(); +xClient.Connect(new Address(192, 168, 1, 254)); + +/** Send ICMP Echo **/ +xClient.SendEcho(); + +/** Receive ICMP Response **/ +int time = xClient.Receive(ref endpoint); //return elapsed time / timeout if no response + +xClient.Close(); //don't forget to close! +``` +## DNS +DNS can be used to retrieve corresponse between a domain name and an IP address. For now DNS can only ask for one domain name at the same time. +```csharp +var xClient = new DnsClient(); +xClient.Connect(new Address(192, 168, 1, 254)); //DNS Server address + +/** Send DNS ask for a single domain name **/ +xClient.SendAsk("github.com"); + +/** Receive DNS Response **/ +Address destination = xClient.Receive(); //can set a timeout value +xClient.Close(); +``` From 1a3c05aae90e81dd68810805024244f68ec08653 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 19:36:53 +0100 Subject: [PATCH 028/314] Change test --- Tests/Kernels/NetworkTest/Kernel.cs | 73 ++++++++++++++----- .../Cosmos.System2/Network/ARP/ARPPacket.cs | 4 +- .../Cosmos.System2/Network/EthernetPacket.cs | 2 +- .../Network/IPV4/UDP/DHCP/DHCPPacket.cs | 2 +- .../Cosmos.System2/Network/IPv4/IPPacket.cs | 2 +- 5 files changed, 59 insertions(+), 24 deletions(-) diff --git a/Tests/Kernels/NetworkTest/Kernel.cs b/Tests/Kernels/NetworkTest/Kernel.cs index 6cd544c24c..e9d17cd967 100644 --- a/Tests/Kernels/NetworkTest/Kernel.cs +++ b/Tests/Kernels/NetworkTest/Kernel.cs @@ -1,7 +1,10 @@ using Cosmos.HAL; +using Cosmos.System.Network.ARP; using Cosmos.System.Network.Config; using Cosmos.System.Network.IPv4; using Cosmos.System.Network.IPv4.UDP; +using Cosmos.System.Network.IPv4.UDP.DHCP; +using Cosmos.System.Network.IPv4.UDP.DNS; using Cosmos.TestRunner; using System; using System.Collections.Generic; @@ -18,28 +21,60 @@ protected override void BeforeRun() protected override void Run() { - /** IPConfig Enable test **/ - mDebugger.Send($"Testing IPConfig.Enable"); - //get nic by name - NetworkDevice nic = NetworkDevice.GetDeviceByName("eth0"); - if (Equals(nic, null)) + /** + * Since DNS and DHCP are inherited and will call parent classes at creation. UDP, IP and EthernetFrame don't need tests + **/ + + /** DNS Packet Parsing Test **/ + byte[] dnsPacketData = new byte[] { - mDebugger.Send($"eth0 not found."); - TestController.Failed(); - } - //Enable network config - IPConfig.Enable(nic, new Address(192, 168, 1, 69), new Address(255, 255, 255, 0), new Address(192, 168, 1, 254)); + 0xB8, 0xD9, 0x4D, 0xC1, 0xA5, 0xFC, 0x98, 0xFA, 0x9B, 0xD4, 0xEB, 0x29, 0x08, 0x00, 0x45, 0x00, 0x00, 0x38, 0xC3, 0x1C, 0x00, 0x00, 0x80, 0x11, 0x00, + 0x00, 0xC0, 0xA8, 0x01, 0x46, 0xC0, 0xA8, 0x01, 0xFE, 0xF0, 0x66, 0x00, 0x35, 0x00, 0x24, 0x84, 0xCA, 0xD6, 0x80, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x69, 0x74, 0x74, 0x65, 0x72, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x01, 0x00, 0x01 + }; + DNSPacket dnsPacket = new DNSPacket(dnsPacketData); + Equals(dnsPacketData, dnsPacket.RawData); - Address ip = new Address(192, 168, 1, 70); - int port = 4242; - string message = "Hello from Cosmos!"; + /** UDP Packet Parsing Test **/ + byte[] udpPacketData = new byte[] + { + 0x98, 0xFA, 0x9B, 0xD4, 0xEB, 0x29, 0xD8, 0xCE, 0x3A, 0x89, 0x3E, 0xD9, 0x08, 0x00, 0x45, 0x00, 0x00, 0x22, 0x0C, 0x74, 0x40, 0x00, 0x40, 0x11, 0xAA, + 0xBE, 0xC0, 0xA8, 0x01, 0x02, 0xC0, 0xA8, 0x01, 0x46, 0x10, 0x92, 0x10, 0x92, 0x00, 0x0E, 0x37, 0x22, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21 + }; + UDPPacket udpPacket = new UDPPacket(udpPacketData); + Equals(udpPacketData, udpPacket.RawData); - /** Udp test **/ - var xClient = new UdpClient(port); - xClient.Connect(ip, port); - xClient.Send(Encoding.ASCII.GetBytes(message)); - mDebugger.Send("Sent UDP packet to " + ip.ToString() + ":" + port); - xClient.Close(); + /** DHCP Packet Parsing Test **/ + byte[] dhcpPacketData = new byte[] + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0xD9, 0x4D, 0xC1, 0xA5, 0xFC, 0x08, 0x00, 0x45, 0xC0, 0x01, 0x59, 0x46, 0x3F, 0x00, 0x00, 0x40, 0x11, 0x6F, + 0xEF, 0xC0, 0xA8, 0x01, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x43, 0x00, 0x44, 0x01, 0x45, 0xD3, 0xC8, 0x02, 0x01, 0x06, 0x00, 0x84, 0xA9, 0x5A, 0x66, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8, 0x01, 0x47, 0xC0, 0xA8, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x34, 0xE1, 0x2D, 0xA3, 0x06, + 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x36, 0x04, 0xC0, 0xA8, 0x01, 0xFE, 0x33, 0x04, 0x00, 0x01, 0x51, 0x80, 0x3A, 0x04, 0x00, + 0x00, 0xA8, 0xC0, 0x3B, 0x04, 0x00, 0x01, 0x27, 0x50, 0x1C, 0x04, 0xC0, 0xA8, 0x01, 0xFF, 0x51, 0x12, 0x03, 0xFF, 0xFF, 0x44, 0x45, 0x53, 0x4B, 0x54, + 0x4F, 0x50, 0x2D, 0x49, 0x51, 0x48, 0x4A, 0x33, 0x31, 0x43, 0x06, 0x04, 0xC0, 0xA8, 0x01, 0xFE, 0x0F, 0x03, 0x6C, 0x61, 0x6E, 0x03, 0x04, 0xC0, 0xA8, + 0x01, 0xFE, 0x01, 0x04, 0xFF, 0xFF, 0xFF, 0x00, 0xFF + }; + DHCPPacket dhcpPacket = new DHCPPacket(dhcpPacketData); + Equals(dhcpPacketData, dhcpPacket.RawData); + + /** ARP Packet Parsing Test **/ + byte[] arpPacketData = new byte[] + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0xD9, 0x4D, 0xC1, 0xA5, 0xFC, 0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xB8, 0xD9, 0x4D, + 0xC1, 0xA5, 0xFC, 0xC0, 0xA8, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xA8, 0x01, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + ARPPacket arpPacket = new ARPPacket(arpPacketData); + Equals(arpPacketData, arpPacket.RawData); TestController.Completed(); } diff --git a/source/Cosmos.System2/Network/ARP/ARPPacket.cs b/source/Cosmos.System2/Network/ARP/ARPPacket.cs index f1aaa84590..80dc5b4a2c 100644 --- a/source/Cosmos.System2/Network/ARP/ARPPacket.cs +++ b/source/Cosmos.System2/Network/ARP/ARPPacket.cs @@ -15,7 +15,7 @@ namespace Cosmos.System.Network.ARP /// /// ARPPacket class. See also: . /// - internal class ARPPacket : EthernetPacket + public class ARPPacket : EthernetPacket { /// /// Hardware type. @@ -110,7 +110,7 @@ internal ARPPacket() /// Create new inctanse of the class. /// /// Raw data. - internal ARPPacket(byte[] rawData) + public ARPPacket(byte[] rawData) : base(rawData) { } diff --git a/source/Cosmos.System2/Network/EthernetPacket.cs b/source/Cosmos.System2/Network/EthernetPacket.cs index ad3d71424e..3fa7ad17d8 100644 --- a/source/Cosmos.System2/Network/EthernetPacket.cs +++ b/source/Cosmos.System2/Network/EthernetPacket.cs @@ -86,7 +86,7 @@ protected EthernetPacket(MACAddress dest, MACAddress src, ushort type, int packe /// /// Get raw data byte array. /// - internal byte[] RawData { get; } + public byte[] RawData { get; } /// /// Get and set source MAC address. diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs index 779665da66..9314686000 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs @@ -78,7 +78,7 @@ internal DHCPPacket() : base() /// Create new inctanse of the class. /// /// Raw data. - internal DHCPPacket(byte[] rawData) + public DHCPPacket(byte[] rawData) : base(rawData) { } diff --git a/source/Cosmos.System2/Network/IPv4/IPPacket.cs b/source/Cosmos.System2/Network/IPv4/IPPacket.cs index dfd4d230a5..bc43167e50 100644 --- a/source/Cosmos.System2/Network/IPv4/IPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/IPPacket.cs @@ -80,7 +80,7 @@ internal IPPacket() /// Create new inctanse of the class. /// /// Raw data. - internal IPPacket(byte[] rawData) + public IPPacket(byte[] rawData) : base(rawData) { } From 46ca973d3f809c386daa18977b75ff460660757e Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 19:38:06 +0100 Subject: [PATCH 029/314] Change sln --- Test.sln | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Test.sln b/Test.sln index c443647530..ab389453f9 100644 --- a/Test.sln +++ b/Test.sln @@ -166,6 +166,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessorTests", "Tests\Ker EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cosmos.Compiler.Tests.BclSystem", "Tests\Kernels\Cosmos.Compiler.Tests.Bcl.System\Cosmos.Compiler.Tests.BclSystem.csproj", "{30D9FA9C-0B4D-40FF-8903-6B9E9C825729}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetworkTest", "Tests\Kernels\NetworkTest\NetworkTest.csproj", "{96855A39-A96B-4BDB-A6AE-29676DFEF637}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -639,6 +641,14 @@ Global {30D9FA9C-0B4D-40FF-8903-6B9E9C825729}.Release|Any CPU.Build.0 = Release|Any CPU {30D9FA9C-0B4D-40FF-8903-6B9E9C825729}.Release|x86.ActiveCfg = Release|Any CPU {30D9FA9C-0B4D-40FF-8903-6B9E9C825729}.Release|x86.Build.0 = Release|Any CPU + {96855A39-A96B-4BDB-A6AE-29676DFEF637}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96855A39-A96B-4BDB-A6AE-29676DFEF637}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96855A39-A96B-4BDB-A6AE-29676DFEF637}.Debug|x86.ActiveCfg = Debug|Any CPU + {96855A39-A96B-4BDB-A6AE-29676DFEF637}.Debug|x86.Build.0 = Debug|Any CPU + {96855A39-A96B-4BDB-A6AE-29676DFEF637}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96855A39-A96B-4BDB-A6AE-29676DFEF637}.Release|Any CPU.Build.0 = Release|Any CPU + {96855A39-A96B-4BDB-A6AE-29676DFEF637}.Release|x86.ActiveCfg = Release|Any CPU + {96855A39-A96B-4BDB-A6AE-29676DFEF637}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -718,6 +728,7 @@ Global {BB6A5306-4C7A-4973-A48E-9FE3E683EAEC} = {29EEC029-6A2B-478A-B6E5-D63A91388ABA} {3F28939D-5E06-44AC-8FC6-ADBBB89AC97B} = {ECEA7778-E786-4317-90B9-A2D4427CB91C} {30D9FA9C-0B4D-40FF-8903-6B9E9C825729} = {ECEA7778-E786-4317-90B9-A2D4427CB91C} + {96855A39-A96B-4BDB-A6AE-29676DFEF637} = {ECEA7778-E786-4317-90B9-A2D4427CB91C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4418C803-277E-448F-A0A0-52788FA215AD} From 660def90c4ed71dbb56c1598359d887d354f8e1b Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 19:43:10 +0100 Subject: [PATCH 030/314] Correct typos --- Docs/articles/Kernel/Network.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index bbbd948a6f..b2ddc44359 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -1,17 +1,17 @@ # Network -In this article we will discuss about Networking on Cosmos, how to use the Network Stack, send and received packets. For now, availables protocols are **ARP**, **IPv4**, **UDP**, **ICMP**, **DHCP** and **DNS** but the team is also working on TCP. +In this article we will discuss about Networking on Cosmos, how to use the Network Stack, send and received packets. For now, available protocols are **ARP**, **IPv4**, **UDP**, **ICMP**, **DHCP** and **DNS** but the team is also working on TCP. -All protocols here doesn't support every feature described by their RFC and may have some bugs or architecture issues, if you find something anormal please [submit an issue](http://https://github.com/CosmosOS/Cosmos/issues/new/choose "repository") on our repository. +All protocols here don't necessary support every feature described by their RFC and may have some bugs or architecture issues, if you find something abnormal please [submit an issue](http://https://github.com/CosmosOS/Cosmos/issues/new/choose "repository") on our repository. -Each protocol have a Client class wich 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 optionnaly set by parameter. Please note that all finished connections should be closed using Close(). +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: ```csharp using Cosmos.System.Network; ``` -Before anything, a Network Configuration must be set (local machine IPv4 address, subnet mask and gateway). It can be manually set with IPConfig.Enable or dynamically set throught a DHCP server. For DHCP, Cosmos will ask to the DHCP server (usually default gateway) for an address in your local network. +Before anything, a Network Configuration must be set (local machine IPv4 address, subnet mask and gateway). It can be manually set with IPConfig.Enable or dynamically set through a DHCP server. For DHCP, Cosmos will ask to the DHCP server (usually default gateway) for an address in your local network. ### Manually set IPv4 Config ```csharp @@ -64,7 +64,7 @@ int time = xClient.Receive(ref endpoint); //return elapsed time / timeout if no xClient.Close(); //don't forget to close! ``` ## DNS -DNS can be used to retrieve corresponse between a domain name and an IP address. For now DNS can only ask for one domain name at the same time. +DNS can be used to get an IP address from a Domain Name string. For now DNS can only ask for one domain name at the same time. ```csharp var xClient = new DnsClient(); xClient.Connect(new Address(192, 168, 1, 254)); //DNS Server address From dd2e1fcfcf288c7fcf12d295547634ff295d5594 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 19:43:25 +0100 Subject: [PATCH 031/314] Correct typos From b7b69f1de7b3a72d2f4a4d25c6a2e055e66dbb1a Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 20:12:34 +0100 Subject: [PATCH 032/314] Make DHCP and DNS Client public --- source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs | 2 +- source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs index 95645a9b83..a5cfb55048 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs @@ -16,7 +16,7 @@ namespace Cosmos.System.Network.IPv4.UDP.DHCP /// /// DHCPClient class. Used to manage the DHCP connection to a server. /// - class DHCPClient + public class DHCPClient { /// /// Current DHCPClient diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs index 99668cb5fb..daad628942 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs @@ -15,7 +15,7 @@ namespace Cosmos.System.Network.IPv4.UDP.DNS /// /// DnsClient class. Used to manage the DNS connection to a server. /// - class DnsClient : UdpClient + public class DnsClient : UdpClient { /// /// Domain Name query string From c6397760af076c3da524436629b0b0eba387754a Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 20:26:53 +0100 Subject: [PATCH 033/314] Make receiveData internal --- source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs | 2 +- source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs index a5cfb55048..dbc9bb537a 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs @@ -68,7 +68,7 @@ public void Close() /// Packet to receive. /// Thrown on fatal error (contact support). /// Thrown on IO error. - public void receiveData(DHCPPacket packet) + internal void receiveData(DHCPPacket packet) { rxBuffer.Enqueue(packet); } diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs index 127b653594..8faa8167f1 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs @@ -205,7 +205,7 @@ public byte[] Receive(ref EndPoint source) /// Packet to receive. /// Thrown on fatal error (contact support). /// Thrown on IO error. - public void receiveData(UDPPacket packet) + internal void receiveData(UDPPacket packet) { rxBuffer.Enqueue(packet); } From fa31327b46a2252298c6e988f8ce7d5b2bf62456 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 21:02:22 +0100 Subject: [PATCH 034/314] Make EndPoint, FindNetwork and DNSConfig public --- source/Cosmos.System2/Network/Config/DNSConfig.cs | 2 +- source/Cosmos.System2/Network/Config/IPConfig.cs | 2 +- source/Cosmos.System2/Network/IPv4/EndPoint.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/Cosmos.System2/Network/Config/DNSConfig.cs b/source/Cosmos.System2/Network/Config/DNSConfig.cs index e06b99607a..9f74ecbfe8 100644 --- a/source/Cosmos.System2/Network/Config/DNSConfig.cs +++ b/source/Cosmos.System2/Network/Config/DNSConfig.cs @@ -8,7 +8,7 @@ namespace Cosmos.System.Network.Config /// /// Contains DNS configuration /// - class DNSConfig + public class DNSConfig { /// /// DNS Addresses list. diff --git a/source/Cosmos.System2/Network/Config/IPConfig.cs b/source/Cosmos.System2/Network/Config/IPConfig.cs index c04c09d751..671adf5e31 100644 --- a/source/Cosmos.System2/Network/Config/IPConfig.cs +++ b/source/Cosmos.System2/Network/Config/IPConfig.cs @@ -65,7 +65,7 @@ internal static void RemoveAll() /// Destination IP address. /// Address value. /// Thrown on fatal error (contact support). - internal static Address FindNetwork(Address destIP) + public static Address FindNetwork(Address destIP) { Address default_gw = null; diff --git a/source/Cosmos.System2/Network/IPv4/EndPoint.cs b/source/Cosmos.System2/Network/IPv4/EndPoint.cs index 9b3ea91908..3e68142d02 100644 --- a/source/Cosmos.System2/Network/IPv4/EndPoint.cs +++ b/source/Cosmos.System2/Network/IPv4/EndPoint.cs @@ -17,11 +17,11 @@ public class EndPoint : IComparable /// /// Address. /// - internal Address address; + public Address address; /// /// Port. /// - internal UInt16 port; + public UInt16 port; /// /// Create new inctanse of the class. From d199707fe1824f4a99f6f4048d01681c1f236af7 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 21:13:36 +0100 Subject: [PATCH 035/314] Make NetworkInit public --- source/Cosmos.HAL2/Network/NetworkInit.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.HAL2/Network/NetworkInit.cs b/source/Cosmos.HAL2/Network/NetworkInit.cs index c20ca8ab5c..44e827aaec 100644 --- a/source/Cosmos.HAL2/Network/NetworkInit.cs +++ b/source/Cosmos.HAL2/Network/NetworkInit.cs @@ -5,7 +5,7 @@ namespace Cosmos.HAL.Network { - class NetworkInit + public class NetworkInit { public static void Init() { From da4d55ec1a97f5d65420caaee05ef6cb681b2cea Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 22:23:20 +0100 Subject: [PATCH 036/314] TempDictionarry removed --- source/Cosmos.System2/Network/ARP/ARPCache.cs | 5 +- .../Cosmos.System2/Network/IPV4/ICMPClient.cs | 4 +- .../Network/IPv4/UDP/UdpClient.cs | 4 +- source/Cosmos.System2/Network/NetworkStack.cs | 8 +- .../Cosmos.System2/Network/TempDictionary.cs | 177 ------------------ 5 files changed, 11 insertions(+), 187 deletions(-) delete mode 100644 source/Cosmos.System2/Network/TempDictionary.cs diff --git a/source/Cosmos.System2/Network/ARP/ARPCache.cs b/source/Cosmos.System2/Network/ARP/ARPCache.cs index 02219c7c52..b963d1c259 100644 --- a/source/Cosmos.System2/Network/ARP/ARPCache.cs +++ b/source/Cosmos.System2/Network/ARP/ARPCache.cs @@ -6,6 +6,7 @@ */ using System; +using System.Collections.Generic; using Cosmos.HAL.Network; namespace Cosmos.System.Network.ARP @@ -18,7 +19,7 @@ internal static class ARPCache /// /// Cache. /// - private static TempDictionary cache; + private static Dictionary cache; /// /// Ensure cache exists. @@ -28,7 +29,7 @@ private static void ensureCacheExists() { if (cache == null) { - cache = new TempDictionary(); + cache = new Dictionary(); } } diff --git a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs index 6e7171b153..cee7a74ead 100644 --- a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs @@ -21,7 +21,7 @@ public class ICMPClient /// /// Clients dictionary. /// - private static TempDictionary clients; + private static Dictionary clients; /// /// Destination address. @@ -39,7 +39,7 @@ public class ICMPClient /// Thrown on fatal error (contact support). static ICMPClient() { - clients = new TempDictionary(); + clients = new Dictionary(); } /// diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs index 8faa8167f1..25eb5b1a47 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs @@ -20,7 +20,7 @@ public class UdpClient /// /// Clients dictionary. /// - private static TempDictionary clients; + private static Dictionary clients; /// /// Local port. @@ -46,7 +46,7 @@ public class UdpClient /// Thrown on fatal error (contact support). static UdpClient() { - clients = new TempDictionary(); + clients = new Dictionary(); } /// diff --git a/source/Cosmos.System2/Network/NetworkStack.cs b/source/Cosmos.System2/Network/NetworkStack.cs index 6b45c266cb..5ba6da6ef4 100644 --- a/source/Cosmos.System2/Network/NetworkStack.cs +++ b/source/Cosmos.System2/Network/NetworkStack.cs @@ -31,11 +31,11 @@ public static class NetworkStack /// /// Get address dictionary. /// - internal static TempDictionary AddressMap { get; private set; } + internal static Dictionary AddressMap { get; private set; } /// /// Get address dictionary. /// - internal static TempDictionary MACMap { get; private set; } + internal static Dictionary MACMap { get; private set; } /// /// Initialize the Network Stack to prepare it for operation. @@ -43,8 +43,8 @@ public static class NetworkStack /// Thrown on fatal error (contact support). public static void Init() { - AddressMap = new TempDictionary(); - MACMap = new TempDictionary(); + AddressMap = new Dictionary(); + MACMap = new Dictionary(); } /// diff --git a/source/Cosmos.System2/Network/TempDictionary.cs b/source/Cosmos.System2/Network/TempDictionary.cs deleted file mode 100644 index 72c0715649..0000000000 --- a/source/Cosmos.System2/Network/TempDictionary.cs +++ /dev/null @@ -1,177 +0,0 @@ -/* -* PROJECT: Aura Operating System Development -* CONTENT: An other dictionnary class -* PROGRAMMERS: Valentin Charbonnier -* Port of Cosmos Code. -*/ - -using System; -using System.Collections.Generic; - -namespace Cosmos.System.Network -{ - /// - /// TempDictionary template class. - /// - /// TempDictionary type name. - internal class TempDictionary - { - private List mKeys; - private List mValues; - - /// - /// Get the number of elements in the list. - /// - public int Count { get; private set; } - - /// - /// Create new inctanse of the class. - /// - /// Thrown on fatal error (contact support). - public TempDictionary() - : this(2) - { } - - /// - /// Create new inctanse of the class, with a specified initial size. - /// - /// Initial size. - /// Thrown if initialSize is less than 0. - public TempDictionary(int initialSize) - { - this.mKeys = new List(initialSize); - this.mValues = new List(initialSize); - } - - /// - /// Get TempDictionary{TValue} keys array. - /// - public TKey[] Keys - { - get - { - return this.mKeys.ToArray(); - } - } - - /// - /// Get TempDictionary{TValue} values array. - /// - public TValue[] Values - { - get - { - return this.mValues.ToArray(); - } - } - - /// - /// Get and set the element with the specified key. - /// - /// Key of an element. - /// TValue value. - /// (set) Thrown if no element with the specified key is found. - public TValue this[UInt32 key] - { - get - { - for (int i = 0; i < mKeys.Count; i++) - { - if (mKeys[i].Equals(key)) - { - return mValues[i]; - } - } - - return default(TValue); - } - set - { - for (int i = 0; i < mKeys.Count; i++) - { - if (mKeys[i].Equals(key)) - { - mValues[i] = value; - return; - } - } - - throw new ArgumentOutOfRangeException("key", "Key not found"); - } - } - - /// - /// Check if the key exists in the TempDictionary{TValue}. - /// - /// Key to check if exists. - /// bool value. - public bool ContainsKey(TKey key) - { - for (int i = 0; i < mKeys.Count; i++) - { - if (mKeys[i].Equals(key)) - { - return true; - } - } - - return false; - } - - /// - /// Adds an object at the end of the TempDictionary{TValue}. - /// - /// Object key. - /// Object value. - /// Thrown if key already exists. - public void Add(TKey key, TValue val) - { - if (ContainsKey(key) == true) - { - throw new ArgumentException("key", "Key already exists"); - } - - mKeys.Add(key); - mValues.Add(val); - } - - /// - /// Removes the element with the specified key of the TempDictionary{TValue}. - /// - /// Key of the item to remove. - /// Thrown on fatal error (contact support). - public void Remove(TKey key) - { - int idx = mKeys.IndexOf(key); - if (idx != -1) - { - this.Remove(idx); - } - } - - /// - /// Removes the element at the specified index of the TempDictionary{TValue}. - /// - /// Index of the item to remove. - /// Thrown if no such index exists in the TempDictionary. - public void Remove(int index) - { - if (index > mKeys.Count - 1) - { - throw new ArgumentOutOfRangeException("index", "No such index"); - } - - mKeys.RemoveAt(index); - mValues.RemoveAt(index); - } - - /// - /// Removes all elements from the TempDictionary{TValue}. - /// - public void Clear() - { - mKeys.Clear(); - mValues.Clear(); - } - } -} From cf8a8519b27586a0347ebaea36a38d819cbcac1e Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 22:37:30 +0100 Subject: [PATCH 037/314] Remove VMTInclude + Separate DHCP paquets by class --- .../Cosmos.System2/Network/ARP/ARPPacket.cs | 8 - .../Network/ARP/ARPPacket_Ethernet.cs | 16 - .../Network/IPV4/UDP/DHCP/DHCPAck.cs | 57 ++++ .../Network/IPV4/UDP/DHCP/DHCPDiscover.cs | 56 ++++ .../Network/IPV4/UDP/DHCP/DHCPPacket.cs | 284 ------------------ .../Network/IPV4/UDP/DHCP/DHCPRelease.cs | 75 +++++ .../Network/IPV4/UDP/DHCP/DHCPRequest.cs | 84 ++++++ .../Network/IPV4/UDP/DNS/DNSPacket.cs | 24 -- .../Cosmos.System2/Network/IPv4/ICMPPacket.cs | 24 -- .../Network/IPv4/UDP/UDPPacket.cs | 76 ----- 10 files changed, 272 insertions(+), 432 deletions(-) create mode 100644 source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs create mode 100644 source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs create mode 100644 source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs create mode 100644 source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs diff --git a/source/Cosmos.System2/Network/ARP/ARPPacket.cs b/source/Cosmos.System2/Network/ARP/ARPPacket.cs index 80dc5b4a2c..8620d7c573 100644 --- a/source/Cosmos.System2/Network/ARP/ARPPacket.cs +++ b/source/Cosmos.System2/Network/ARP/ARPPacket.cs @@ -91,14 +91,6 @@ internal static void ARPHandler(byte[] packetData) } } - /// - /// Work around to make VMT scanner include the initFields method - /// - public static void VMTInclude() - { - new ARPPacket(); - } - /// /// Create new inctanse of the class. /// diff --git a/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs b/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs index cd7eeea929..ce7df0ed5a 100644 --- a/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs +++ b/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs @@ -145,14 +145,6 @@ public override string ToString() /// internal class ARPReply_Ethernet : ARPPacket_Ethernet { - /// - /// Work around to make VMT scanner include the initFields method - /// - public new static void VMTInclude() - { - new ARPReply_Ethernet(); - } - /// /// Create new inctanse of the class. /// @@ -195,14 +187,6 @@ public override string ToString() /// internal class ARPRequest_Ethernet : ARPPacket_Ethernet { - /// - /// Work around to make VMT scanner include the initFields method - /// - public new static void VMTInclude() - { - new ARPRequest_Ethernet(); - } - /// /// Create new inctanse of the class. /// diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs new file mode 100644 index 0000000000..0d9ac642cd --- /dev/null +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Cosmos.System.Network.IPv4.UDP.DHCP +{ + /// + /// DHCPAck class. + /// + internal class DHCPAck : DHCPPacket + { + /// + /// Create new inctanse of the class. + /// + internal DHCPAck() : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + internal DHCPAck(byte[] rawData) : base(rawData) + { } + + /// + /// Init DHCPAck fields. + /// + /// Thrown if RawData is invalid or null. + protected override void initFields() + { + base.initFields(); + + foreach (var option in Options) + { + if (option.Type == 1) //Mask + { + Subnet = new Address(option.Data, 0); + } + else if (option.Type == 6) //DNS + { + DNS = new Address(option.Data, 0); + } + } + } + + /// + /// Get Subnet IPv4 Address + /// + internal Address Subnet { get; private set; } + + /// + /// Get DNS IPv4 Address + /// + internal Address DNS { get; private set; } + + } +} diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs new file mode 100644 index 0000000000..c38be28d2b --- /dev/null +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs @@ -0,0 +1,56 @@ +using System; +using Cosmos.HAL.Network; +using Cosmos.System.Network.IPv4.UDP.DHCP; + +namespace Cosmos.System.Network.IPv4.UDP.DHCP +{ + /// + /// DHCPDiscover class. + /// + internal class DHCPDiscover : DHCPPacket + { + /// + /// Create new inctanse of the class. + /// + internal DHCPDiscover() : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + internal DHCPDiscover(byte[] rawData) : base(rawData) + { } + + /// + /// Create new inctanse of the class. + /// + /// Source MAC Address. + /// Thrown if RawData is invalid or null. + internal DHCPDiscover(MACAddress mac_src) : base(mac_src, 10) //discover packet size + { + //Discover + RawData[282] = 0x35; + RawData[283] = 0x01; + RawData[284] = 0x01; + + //Parameters start here + RawData[285] = 0x37; + RawData[286] = 4; + + //Parameters* + RawData[287] = 0x01; + RawData[288] = 0x03; + RawData[289] = 0x0f; + RawData[290] = 0x06; + + RawData[291] = 0xff; //ENDMARK + } + + protected override void initFields() + { + base.initFields(); + } + + } +} diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs index 9314686000..d89430ad80 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs @@ -60,14 +60,6 @@ public static void DHCPHandler(byte[] packetData) } } - /// - /// Work around to make VMT scanner include the initFields method - /// - public static void VMTInclude() - { - new DHCPPacket(); - } - /// /// Create new inctanse of the class. /// @@ -217,280 +209,4 @@ protected override void initFields() internal List Options { get; private set; } } - - /// - /// DHCPDiscover class. - /// - internal class DHCPDiscover : DHCPPacket - { - /// - /// Create new inctanse of the class. - /// - internal DHCPDiscover() : base() - { } - - /// - /// Create new inctanse of the class. - /// - /// Raw data. - internal DHCPDiscover(byte[] rawData) : base(rawData) - { } - - /// - /// Create new inctanse of the class. - /// - /// Source MAC Address. - /// Thrown if RawData is invalid or null. - internal DHCPDiscover(MACAddress mac_src) : base(mac_src, 10) //discover packet size - { - //Discover - RawData[282] = 0x35; - RawData[283] = 0x01; - RawData[284] = 0x01; - - //Parameters start here - RawData[285] = 0x37; - RawData[286] = 4; - - //Parameters* - RawData[287] = 0x01; - RawData[288] = 0x03; - RawData[289] = 0x0f; - RawData[290] = 0x06; - - RawData[291] = 0xff; //ENDMARK - } - - /// - /// Work around to make VMT scanner include the initFields method - /// - public new static void VMTInclude() - { - new DHCPDiscover(); - } - - protected override void initFields() - { - base.initFields(); - } - - } - - /// - /// DHCPRequest class. - /// - internal class DHCPRequest : DHCPPacket - { - - /// - /// Create new inctanse of the class. - /// - internal DHCPRequest() : base() - { } - - /// - /// Create new inctanse of the class. - /// - /// Raw data. - internal DHCPRequest(byte[] rawData) : base(rawData) - { } - - /// - /// Create new inctanse of the class. - /// - /// Source MAC Address. - /// Requested Address. - /// DHCP server IPv4 Address. - /// Thrown if data array length is greater than Int32.MaxValue. - /// Thrown if RawData is invalid or null. - internal DHCPRequest(MACAddress mac_src, Address RequestedAddress, Address DHCPServerAddress) : base(mac_src, 22) - { - //Request - RawData[282] = 53; - RawData[283] = 1; - RawData[284] = 3; - - //Requested Address - RawData[285] = 50; - RawData[286] = 4; - - RawData[287] = RequestedAddress.address[0]; - RawData[288] = RequestedAddress.address[1]; - RawData[289] = RequestedAddress.address[2]; - RawData[290] = RequestedAddress.address[3]; - - RawData[291] = 54; - RawData[292] = 4; - - RawData[293] = DHCPServerAddress.address[0]; - RawData[294] = DHCPServerAddress.address[1]; - RawData[295] = DHCPServerAddress.address[2]; - RawData[296] = DHCPServerAddress.address[3]; - - //Parameters start here - RawData[297] = 0x37; - RawData[298] = 4; - - //Parameters - RawData[299] = 0x01; - RawData[300] = 0x03; - RawData[301] = 0x0f; - RawData[302] = 0x06; - - RawData[303] = 0xff; //ENDMARK - } - - /// - /// Work around to make VMT scanner include the initFields method - /// - public new static void VMTInclude() - { - new DHCPRequest(); - } - - /// - /// Init DHCPRequest fields. - /// - /// Thrown if RawData is invalid or null. - protected override void initFields() - { - base.initFields(); - } - - } - - /// - /// DHCPAck class. - /// - internal class DHCPAck : DHCPPacket - { - /// - /// Create new inctanse of the class. - /// - internal DHCPAck() : base() - { } - - /// - /// Create new inctanse of the class. - /// - /// Raw data. - internal DHCPAck(byte[] rawData) : base(rawData) - { } - - /// - /// Work around to make VMT scanner include the initFields method - /// - public new static void VMTInclude() - { - new DHCPAck(); - } - - /// - /// Init DHCPAck fields. - /// - /// Thrown if RawData is invalid or null. - protected override void initFields() - { - base.initFields(); - - foreach (var option in Options) - { - if (option.Type == 1) //Mask - { - Subnet = new Address(option.Data, 0); - } - else if (option.Type == 6) //DNS - { - DNS = new Address(option.Data, 0); - } - } - } - - /// - /// Get Subnet IPv4 Address - /// - internal Address Subnet { get; private set; } - - /// - /// Get DNS IPv4 Address - /// - internal Address DNS { get; private set; } - - } - - /// - /// DHCPRelease class. - /// - internal class DHCPRelease : DHCPPacket - { - /// - /// Create new inctanse of the class. - /// - internal DHCPRelease() : base() - { } - - /// - /// Create new inctanse of the class. - /// - /// Raw data. - internal DHCPRelease(byte[] rawData) : base(rawData) - { } - - /// - /// Create new inctanse of the class. - /// - /// Client IPv4 Address. - /// DHCP Server IPv4 Address. - /// Source MAC Address. - /// Thrown if data array length is greater than Int32.MaxValue. - /// Thrown if RawData is invalid or null. - internal DHCPRelease(Address client, Address server, MACAddress source) : base(client, server, source, 19) - { - //Release - RawData[282] = 0x35; - RawData[283] = 0x01; - RawData[284] = 0x07; - - //DHCP Server ID - RawData[285] = 0x36; - RawData[286] = 0x04; - - RawData[287] = server.address[0]; - RawData[288] = server.address[1]; - RawData[289] = server.address[2]; - RawData[290] = server.address[3]; - - //Client ID - RawData[291] = 0x3d; - RawData[292] = 7; - RawData[293] = 1; - - RawData[294] = source.bytes[0]; - RawData[295] = source.bytes[1]; - RawData[296] = source.bytes[2]; - RawData[297] = source.bytes[3]; - RawData[298] = source.bytes[4]; - RawData[299] = source.bytes[5]; - - RawData[300] = 0xff; //ENDMARK - } - - /// - /// Work around to make VMT scanner include the initFields method - /// - public new static void VMTInclude() - { - new DHCPRelease(); - } - - /// - /// Init DHCPRelease fields. - /// - /// Thrown if RawData is invalid or null. - protected override void initFields() - { - base.initFields(); - } - - } } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs new file mode 100644 index 0000000000..acdba9ba69 --- /dev/null +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Cosmos.HAL.Network; + +namespace Cosmos.System.Network.IPv4.UDP.DHCP +{ + /// + /// DHCPRelease class. + /// + internal class DHCPRelease : DHCPPacket + { + /// + /// Create new inctanse of the class. + /// + internal DHCPRelease() : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + internal DHCPRelease(byte[] rawData) : base(rawData) + { } + + /// + /// Create new inctanse of the class. + /// + /// Client IPv4 Address. + /// DHCP Server IPv4 Address. + /// Source MAC Address. + /// Thrown if data array length is greater than Int32.MaxValue. + /// Thrown if RawData is invalid or null. + internal DHCPRelease(Address client, Address server, MACAddress source) : base(client, server, source, 19) + { + //Release + RawData[282] = 0x35; + RawData[283] = 0x01; + RawData[284] = 0x07; + + //DHCP Server ID + RawData[285] = 0x36; + RawData[286] = 0x04; + + RawData[287] = server.address[0]; + RawData[288] = server.address[1]; + RawData[289] = server.address[2]; + RawData[290] = server.address[3]; + + //Client ID + RawData[291] = 0x3d; + RawData[292] = 7; + RawData[293] = 1; + + RawData[294] = source.bytes[0]; + RawData[295] = source.bytes[1]; + RawData[296] = source.bytes[2]; + RawData[297] = source.bytes[3]; + RawData[298] = source.bytes[4]; + RawData[299] = source.bytes[5]; + + RawData[300] = 0xff; //ENDMARK + } + + /// + /// Init DHCPRelease fields. + /// + /// Thrown if RawData is invalid or null. + protected override void initFields() + { + base.initFields(); + } + + } +} diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs new file mode 100644 index 0000000000..c9cdc055cd --- /dev/null +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Cosmos.HAL.Network; +using Cosmos.System.Network.IPv4; +using Cosmos.System.Network.IPv4.UDP.DHCP; + +namespace Cosmos.System.Network.IPv4.UDP.DHCP +{ + /// + /// DHCPRequest class. + /// + internal class DHCPRequest : DHCPPacket + { + + /// + /// Create new inctanse of the class. + /// + internal DHCPRequest() : base() + { } + + /// + /// Create new inctanse of the class. + /// + /// Raw data. + internal DHCPRequest(byte[] rawData) : base(rawData) + { } + + /// + /// Create new inctanse of the class. + /// + /// Source MAC Address. + /// Requested Address. + /// DHCP server IPv4 Address. + /// Thrown if data array length is greater than Int32.MaxValue. + /// Thrown if RawData is invalid or null. + internal DHCPRequest(MACAddress mac_src, Address RequestedAddress, Address DHCPServerAddress) : base(mac_src, 22) + { + //Request + RawData[282] = 53; + RawData[283] = 1; + RawData[284] = 3; + + //Requested Address + RawData[285] = 50; + RawData[286] = 4; + + RawData[287] = RequestedAddress.address[0]; + RawData[288] = RequestedAddress.address[1]; + RawData[289] = RequestedAddress.address[2]; + RawData[290] = RequestedAddress.address[3]; + + RawData[291] = 54; + RawData[292] = 4; + + RawData[293] = DHCPServerAddress.address[0]; + RawData[294] = DHCPServerAddress.address[1]; + RawData[295] = DHCPServerAddress.address[2]; + RawData[296] = DHCPServerAddress.address[3]; + + //Parameters start here + RawData[297] = 0x37; + RawData[298] = 4; + + //Parameters + RawData[299] = 0x01; + RawData[300] = 0x03; + RawData[301] = 0x0f; + RawData[302] = 0x06; + + RawData[303] = 0xff; //ENDMARK + } + + /// + /// Init DHCPRequest fields. + /// + /// Thrown if RawData is invalid or null. + protected override void initFields() + { + base.initFields(); + } + + } +} diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs index 89fd171d5d..f85d046cac 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs @@ -68,14 +68,6 @@ internal static void DNSHandler(byte[] packetData) } } - /// - /// Work around to make VMT scanner include the initFields method - /// - public static void VMTInclude() - { - new DNSPacket(); - } - /// /// Create new inctanse of the class. /// @@ -221,14 +213,6 @@ public override string ToString() /// public class DNSPacketAsk : DNSPacket { - /// - /// Work around to make VMT scanner include the initFields method - /// - public static void VMTInclude() - { - new DNSPacketAsk(); - } - /// /// Create new inctanse of the class. /// @@ -296,14 +280,6 @@ protected override void initFields() /// public class DNSPacketAnswer : DNSPacket { - /// - /// Work around to make VMT scanner include the initFields method - /// - public static void VMTInclude() - { - new DNSPacketAnswer(); - } - /// /// Create new inctanse of the class. /// diff --git a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs index f47acd641e..d55214ede8 100644 --- a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs @@ -59,14 +59,6 @@ internal static void ICMPHandler(byte[] packetData) } } - /// - /// Work around to make VMT scanner include the initFields method - /// - public static void VMTInclude() - { - new ICMPPacket(); - } - /// /// Create new inctanse of the class. /// @@ -230,14 +222,6 @@ internal ICMPEchoRequest(Address source, Address dest, ushort id, ushort sequenc RawData[DataOffset + 3] = (byte)((icmpCRC >> 0) & 0xFF); } - /// - /// Work around to make VMT scanner include the initFields method - /// - public new static void VMTInclude() - { - new ICMPEchoRequest(); - } - protected override void initFields() { //Sys.Console.WriteLine("ICMPEchoRequest.initFields() called;"); @@ -289,14 +273,6 @@ internal ICMPEchoReply(byte[] rawData) { } - /// - /// Work around to make VMT scanner include the initFields method - /// - public new static void VMTInclude() - { - new ICMPEchoReply(); - } - /// /// Init ICMPEchoReply fields. /// diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs index 1661663580..ce4315f5b2 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs @@ -53,82 +53,6 @@ internal static void UDPHandler(byte[] packetData) } } - /// - /// Make header. - /// - /// Source IP. - /// Destination IP. - /// UDP length. - /// Source port. - /// Destination port. - /// UDP data. - /// byte array value. - /// Thrown if UDP_Data array length is greater than Int32.MaxValue. - public static byte[] MakeHeader(byte[] sourceIP, byte[] destIP, UInt16 udpLen, UInt16 sourcePort, UInt16 destPort, byte[] UDP_Data) - { - byte[] header = new byte[18 + UDP_Data.Length]; - - header[0] = sourceIP[0]; - header[1] = sourceIP[1]; - header[2] = sourceIP[2]; - header[3] = sourceIP[3]; - - header[4] = destIP[0]; - header[5] = destIP[1]; - header[6] = destIP[2]; - header[7] = destIP[3]; - - header[8] = 0x00; - - header[9] = 0x11; - - header[10] = (byte)((udpLen >> 8) & 0xFF); - header[11] = (byte)((udpLen >> 0) & 0xFF); - - header[12] = (byte)((sourcePort >> 8) & 0xFF); - header[13] = (byte)((sourcePort >> 0) & 0xFF); - - header[14] = (byte)((destPort >> 8) & 0xFF); - header[15] = (byte)((destPort >> 0) & 0xFF); - - header[16] = (byte)((udpLen >> 8) & 0xFF); - header[17] = (byte)((udpLen >> 0) & 0xFF); - - for (int i = 0; i < UDP_Data.Length; i++) - { - header[18 + i] = UDP_Data[i]; - } - - return header; - } - - /// - /// Check CRC. - /// - /// Packer to be checked. - /// bool value. - /// Thrown if packet.UDP_Data lenght if greater than Int32.MaxValue. - public static bool CheckCRC(UDPPacket packet) - { - byte[] header = MakeHeader(packet.SourceIP.address, packet.DestinationIP.address, packet.UDP_Length, packet.SourcePort, packet.DestinationPort, packet.UDP_Data); - if (CalcOcCRC(header, 0, header.Length) == packet.udpCRC) - { - return true; - } - else - { - return false; - } - } - - /// - /// Work around to make VMT scanner include the initFields method - /// - public static void VMTInclude() - { - new UDPPacket(); - } - /// /// Create new inctanse of the class. /// From 325366fc8452e38fba6302ecaf2e43fe9181d92a Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 22:45:40 +0100 Subject: [PATCH 038/314] ConfigEmpty rewrite + Capitalize initFields InvalidOperationException --- .../Cosmos.System2/Network/ARP/ARPPacket.cs | 6 +++--- .../Network/ARP/ARPPacket_Ethernet.cs | 6 +++--- .../Cosmos.System2/Network/EthernetPacket.cs | 10 +++++----- .../Network/IPV4/UDP/DHCP/DHCPAck.cs | 4 ++-- .../Network/IPV4/UDP/DHCP/DHCPDiscover.cs | 4 ++-- .../Network/IPV4/UDP/DHCP/DHCPPacket.cs | 6 +++--- .../Network/IPV4/UDP/DHCP/DHCPRelease.cs | 4 ++-- .../Network/IPV4/UDP/DHCP/DHCPRequest.cs | 4 ++-- .../Network/IPV4/UDP/DNS/DNSClient.cs | 2 +- .../Network/IPV4/UDP/DNS/DNSPacket.cs | 14 ++++++------- .../Cosmos.System2/Network/IPv4/ICMPPacket.cs | 20 +++++++++---------- .../Cosmos.System2/Network/IPv4/IPPacket.cs | 6 +++--- .../Network/IPv4/UDP/UDPPacket.cs | 10 +++++----- .../Network/IPv4/UDP/UdpClient.cs | 2 +- source/Cosmos.System2/Network/NetworkStack.cs | 8 +------- 15 files changed, 50 insertions(+), 56 deletions(-) diff --git a/source/Cosmos.System2/Network/ARP/ARPPacket.cs b/source/Cosmos.System2/Network/ARP/ARPPacket.cs index 8620d7c573..574cbb591e 100644 --- a/source/Cosmos.System2/Network/ARP/ARPPacket.cs +++ b/source/Cosmos.System2/Network/ARP/ARPPacket.cs @@ -109,9 +109,9 @@ public ARPPacket(byte[] rawData) /// /// Init ARPPacket fields. /// - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); aHardwareType = (ushort)((RawData[14] << 8) | RawData[15]); aProtocolType = (ushort)((RawData[16] << 8) | RawData[17]); aHardwareLen = RawData[18]; @@ -143,7 +143,7 @@ protected ARPPacket(MACAddress dest, MACAddress src, ushort hwType, ushort proto RawData[20] = (byte)(operation >> 8); RawData[21] = (byte)(operation >> 0); - initFields(); + InitFields(); } /// diff --git a/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs b/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs index ce7df0ed5a..90a5683532 100644 --- a/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs +++ b/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs @@ -55,9 +55,9 @@ internal ARPPacket_Ethernet(byte[] rawData) /// Init ARPPacket_Ethernet fields. /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); mSenderMAC = new MACAddress(RawData, 22); mSenderIP = new Address(RawData, 28); if (SenderIP == null) @@ -94,7 +94,7 @@ protected ARPPacket_Ethernet(UInt16 operation, MACAddress senderMAC, Address sen RawData[38 + i] = targetIP.address[i]; } - initFields(); + InitFields(); } /// diff --git a/source/Cosmos.System2/Network/EthernetPacket.cs b/source/Cosmos.System2/Network/EthernetPacket.cs index 3fa7ad17d8..4ae2615b9e 100644 --- a/source/Cosmos.System2/Network/EthernetPacket.cs +++ b/source/Cosmos.System2/Network/EthernetPacket.cs @@ -39,13 +39,13 @@ protected EthernetPacket() protected EthernetPacket(byte[] rawData) { RawData = rawData; - initFields(); + InitFields(); } /// /// Init EthernetPacket fields. /// - protected virtual void initFields() + protected virtual void InitFields() { destMAC = new MACAddress(RawData, 0); srcMAC = new MACAddress(RawData, 6); @@ -80,7 +80,7 @@ protected EthernetPacket(MACAddress dest, MACAddress src, ushort type, int packe RawData[12] = (byte)(type >> 8); RawData[13] = (byte)(type >> 0); - initFields(); + InitFields(); } /// @@ -100,7 +100,7 @@ internal MACAddress SourceMAC { RawData[6 + i] = value.bytes[i]; } - initFields(); + InitFields(); } } @@ -116,7 +116,7 @@ internal MACAddress DestinationMAC { RawData[i] = value.bytes[i]; } - initFields(); + InitFields(); } } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs index 0d9ac642cd..f7b374c853 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs @@ -26,9 +26,9 @@ internal DHCPAck(byte[] rawData) : base(rawData) /// Init DHCPAck fields. /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); foreach (var option in Options) { diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs index c38be28d2b..a9f0f440b9 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs @@ -47,9 +47,9 @@ internal DHCPDiscover(MACAddress mac_src) : base(mac_src, 10) //discover packet RawData[291] = 0xff; //ENDMARK } - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); } } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs index d89430ad80..2e611a1c2a 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs @@ -153,16 +153,16 @@ internal DHCPPacket(Address client, Address server, MACAddress mac_src, ushort d RawData[280] = 0x53; RawData[281] = 0x63; - initFields(); + InitFields(); } /// /// Init DHCPPacket fields. /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); MessageType = RawData[42]; Client = new Address(RawData, 58); Server = new Address(RawData, 62); diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs index acdba9ba69..e9d9ff92e5 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs @@ -66,9 +66,9 @@ internal DHCPRelease(Address client, Address server, MACAddress source) : base(c /// Init DHCPRelease fields. /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); } } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs index c9cdc055cd..7f01533855 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs @@ -75,9 +75,9 @@ internal DHCPRequest(MACAddress mac_src, Address RequestedAddress, Address DHCPS /// Init DHCPRequest fields. /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); } } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs index daad628942..dec08b9bc2 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs @@ -23,7 +23,7 @@ public class DnsClient : UdpClient private string queryurl; /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Thrown on fatal error (contact support). /// Thrown if UdpClient with localPort 53 exists. diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs index f85d046cac..6d81029311 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs @@ -115,16 +115,16 @@ public DNSPacket(Address source, Address dest, ushort urlnb, ushort len) RawData[this.DataOffset + 18] = (byte)((0 >> 8) & 0xFF); RawData[this.DataOffset + 19] = (byte)((0 >> 0) & 0xFF); - initFields(); + InitFields(); } /// /// Init DNSPacket fields. /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); TransactionID = (UInt16)((RawData[this.DataOffset + 8] << 8) | RawData[this.DataOffset + 9]); DNSFlags = (UInt16)((RawData[this.DataOffset + 10] << 8) | RawData[this.DataOffset + 11]); Questions = (UInt16)((RawData[this.DataOffset + 12] << 8) | RawData[this.DataOffset + 13]); @@ -269,9 +269,9 @@ public DNSPacketAsk(Address source, Address dest, string url) /// Init DNSPacketAsk fields. /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); } } @@ -299,9 +299,9 @@ public DNSPacketAnswer(byte[] rawData) /// Init DNSPacketAnswer fields. /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); if ((ushort)(DNSFlags & 0x0F) != (ushort)ReplyCode.OK) { diff --git a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs index d55214ede8..c8094e35a9 100644 --- a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs @@ -79,10 +79,10 @@ internal ICMPPacket(byte[] rawData) /// Init ICMPPacket fields.1 /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - //Sys.Console.WriteLine("ICMPPacket.initFields() called;"); - base.initFields(); + //Sys.Console.WriteLine("ICMPPacket.InitFields() called;"); + base.InitFields(); icmpType = RawData[DataOffset]; icmpCode = RawData[DataOffset + 1]; icmpCRC = (ushort)((RawData[DataOffset + 2] << 8) | RawData[DataOffset + 3]); @@ -115,7 +115,7 @@ internal ICMPPacket(Address source, Address dest, byte type, byte code, ushort i RawData[DataOffset + 2] = (byte)((icmpCRC >> 8) & 0xFF); RawData[DataOffset + 3] = (byte)((icmpCRC >> 0) & 0xFF); - initFields(); + InitFields(); } /// @@ -222,10 +222,10 @@ internal ICMPEchoRequest(Address source, Address dest, ushort id, ushort sequenc RawData[DataOffset + 3] = (byte)((icmpCRC >> 0) & 0xFF); } - protected override void initFields() + protected override void InitFields() { - //Sys.Console.WriteLine("ICMPEchoRequest.initFields() called;"); - base.initFields(); + //Sys.Console.WriteLine("ICMPEchoRequest.InitFields() called;"); + base.InitFields(); icmpID = (ushort)((RawData[DataOffset + 4] << 8) | RawData[DataOffset + 5]); icmpSequence = (ushort)((RawData[DataOffset + 6] << 8) | RawData[DataOffset + 7]); } @@ -277,10 +277,10 @@ internal ICMPEchoReply(byte[] rawData) /// Init ICMPEchoReply fields. /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - //Sys.Console.WriteLine("ICMPEchoReply.initFields() called;"); - base.initFields(); + //Sys.Console.WriteLine("ICMPEchoReply.InitFields() called;"); + base.InitFields(); icmpID = (ushort)((RawData[DataOffset + 4] << 8) | RawData[DataOffset + 5]); icmpSequence = (ushort)((RawData[DataOffset + 6] << 8) | RawData[DataOffset + 7]); } diff --git a/source/Cosmos.System2/Network/IPv4/IPPacket.cs b/source/Cosmos.System2/Network/IPv4/IPPacket.cs index bc43167e50..f5d6350dcb 100644 --- a/source/Cosmos.System2/Network/IPv4/IPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/IPPacket.cs @@ -89,9 +89,9 @@ public IPPacket(byte[] rawData) /// Init IPPacket fields. /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); IPVersion = (byte)((RawData[14] & 0xF0) >> 4); ipHeaderLength = (byte)(RawData[14] & 0x0F); TypeOfService = RawData[15]; @@ -172,7 +172,7 @@ public IPPacket(MACAddress srcMAC, MACAddress destMAC, ushort dataLength, byte p RawData[24] = (byte)((IPCRC >> 8) & 0xFF); RawData[25] = (byte)((IPCRC >> 0) & 0xFF); - initFields(); + InitFields(); } /// diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs index ce4315f5b2..cca779d8e9 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs @@ -73,14 +73,14 @@ public UDPPacket(Address source, Address dest, UInt16 srcport, UInt16 destport, : base((ushort)(datalength + 8), 17, source, dest, 0x00) { MakePacket(srcport, destport, datalength); - initFields(); + InitFields(); } public UDPPacket(Address source, Address dest, UInt16 srcport, UInt16 destport, UInt16 datalength, MACAddress destmac) : base((ushort)(datalength + 8), 17, source, dest, 0x00, destmac) { MakePacket(srcport, destport, datalength); - initFields(); + InitFields(); } /// @@ -103,7 +103,7 @@ public UDPPacket(Address source, Address dest, ushort srcPort, ushort destPort, RawData[this.DataOffset + 8 + b] = data[b]; } - initFields(); + InitFields(); } private void MakePacket(ushort srcport, ushort destport, ushort length) @@ -125,9 +125,9 @@ private void MakePacket(ushort srcport, ushort destport, ushort length) /// Init UDPPacket fields. /// /// Thrown if RawData is invalid or null. - protected override void initFields() + protected override void InitFields() { - base.initFields(); + base.InitFields(); SourcePort = (ushort)((RawData[DataOffset] << 8) | RawData[DataOffset + 1]); DestinationPort = (ushort)((RawData[DataOffset + 2] << 8) | RawData[DataOffset + 3]); UDP_Length = (ushort)((RawData[DataOffset + 4] << 8) | RawData[DataOffset + 5]); diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs index 25eb5b1a47..4702cda710 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs @@ -139,7 +139,7 @@ public void Send(byte[] data) { if ((destination == null) || (destinationPort == 0)) { - throw new Exception("Must establish a default remote host by calling Connect() before using this Send() overload"); + throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); } Send(data, destination, destinationPort); diff --git a/source/Cosmos.System2/Network/NetworkStack.cs b/source/Cosmos.System2/Network/NetworkStack.cs index 5ba6da6ef4..747914b79b 100644 --- a/source/Cosmos.System2/Network/NetworkStack.cs +++ b/source/Cosmos.System2/Network/NetworkStack.cs @@ -97,13 +97,7 @@ public static void ConfigIP(NetworkDevice nic, IPConfig config) /// public static bool ConfigEmpty() { - int counter = 0; - - foreach (NetworkDevice device in NetworkConfig.Keys) - { - counter++; - } - if (counter == 0) + if (NetworkConfig.Keys.Count == 0) { return true; } From aa728c48357f89455ba5d0d1ac6ff8a4251be256 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 20 Jan 2021 22:47:31 +0100 Subject: [PATCH 039/314] Instance typo fix --- source/Cosmos.Core/Global.cs | 2 +- source/Cosmos.HAL2/BlockDevice/Partition.cs | 2 +- .../Drivers/PCI/Video/VMWareSVGAII.cs | 2 +- source/Cosmos.HAL2/Global.cs | 2 +- source/Cosmos.HAL2/TextScreen.cs | 2 +- source/Cosmos.System2/Global.cs | 2 +- source/Cosmos.System2/Graphics/Bitmap.cs | 4 ++-- source/Cosmos.System2/Network/ARP/ARPPacket.cs | 6 +++--- .../Network/ARP/ARPPacket_Ethernet.cs | 18 +++++++++--------- .../Cosmos.System2/Network/EthernetPacket.cs | 8 ++++---- .../Cosmos.System2/Network/IPV4/ICMPClient.cs | 2 +- .../Network/IPV4/UDP/DHCP/DHCPAck.cs | 4 ++-- .../Network/IPV4/UDP/DHCP/DHCPClient.cs | 2 +- .../Network/IPV4/UDP/DHCP/DHCPDiscover.cs | 6 +++--- .../Network/IPV4/UDP/DHCP/DHCPPacket.cs | 8 ++++---- .../Network/IPV4/UDP/DHCP/DHCPRelease.cs | 6 +++--- .../Network/IPV4/UDP/DHCP/DHCPRequest.cs | 6 +++--- .../Network/IPV4/UDP/DNS/DNSPacket.cs | 16 ++++++++-------- source/Cosmos.System2/Network/IPv4/Address.cs | 4 ++-- source/Cosmos.System2/Network/IPv4/EndPoint.cs | 2 +- .../Cosmos.System2/Network/IPv4/ICMPPacket.cs | 18 +++++++++--------- source/Cosmos.System2/Network/IPv4/IPPacket.cs | 10 +++++----- .../Network/IPv4/OutgoingBuffer.cs | 2 +- .../Network/IPv4/UDP/UDPPacket.cs | 6 +++--- .../Network/IPv4/UDP/UdpClient.cs | 6 +++--- source/Cosmos.System2/Network/NetworkStack.cs | 2 +- source/Cosmos.System2/Text/CP437Encoding.cs | 4 ++-- source/Cosmos.System2/Text/CP858Encoding.cs | 4 ++-- .../Text/CosmosEncodingProvider.cs | 4 ++-- source/Cosmos.System2/Text/EncodingTable.cs | 6 +++--- .../Cosmos.System2/Text/SingleByteEncoding.cs | 2 +- 31 files changed, 84 insertions(+), 84 deletions(-) diff --git a/source/Cosmos.Core/Global.cs b/source/Cosmos.Core/Global.cs index 770ee6242f..8c5a64b24c 100644 --- a/source/Cosmos.Core/Global.cs +++ b/source/Cosmos.Core/Global.cs @@ -41,7 +41,7 @@ static public CPU CPU } /// - /// Init inctanse. + /// Init instance. /// static public void Init() { diff --git a/source/Cosmos.HAL2/BlockDevice/Partition.cs b/source/Cosmos.HAL2/BlockDevice/Partition.cs index 960a0696d9..f5891e8267 100644 --- a/source/Cosmos.HAL2/BlockDevice/Partition.cs +++ b/source/Cosmos.HAL2/BlockDevice/Partition.cs @@ -17,7 +17,7 @@ public class Partition : BlockDevice private readonly UInt64 mStartingSector; /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// A hosting device. /// A starting sector. diff --git a/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs b/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs index 33397c3558..9f0df3dd16 100644 --- a/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs +++ b/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs @@ -475,7 +475,7 @@ private enum Capability private uint capabilities; /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// public VMWareSVGAII() { diff --git a/source/Cosmos.HAL2/Global.cs b/source/Cosmos.HAL2/Global.cs index cc801aa9d9..075ffb75cc 100644 --- a/source/Cosmos.HAL2/Global.cs +++ b/source/Cosmos.HAL2/Global.cs @@ -22,7 +22,7 @@ public static class Global // TODO: continue adding exceptions to the list, as HAL and Core would be documented. /// - /// Init inctanse. + /// Init instance. /// /// Text screen. /// Thrown on IO error. diff --git a/source/Cosmos.HAL2/TextScreen.cs b/source/Cosmos.HAL2/TextScreen.cs index a75ceded87..c4548e7499 100644 --- a/source/Cosmos.HAL2/TextScreen.cs +++ b/source/Cosmos.HAL2/TextScreen.cs @@ -23,7 +23,7 @@ public class TextScreen : TextScreenBase protected readonly MemoryBlock08 mRAM; /// - /// Creat new inctanse of the class. + /// Creat new instance of the class. /// public TextScreen() { diff --git a/source/Cosmos.System2/Global.cs b/source/Cosmos.System2/Global.cs index bc2320d306..62f4879128 100644 --- a/source/Cosmos.System2/Global.cs +++ b/source/Cosmos.System2/Global.cs @@ -18,7 +18,7 @@ namespace Cosmos.System public static class Global { /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// static Global() { diff --git a/source/Cosmos.System2/Graphics/Bitmap.cs b/source/Cosmos.System2/Graphics/Bitmap.cs index 94b06b7197..49ddb9dbd6 100644 --- a/source/Cosmos.System2/Graphics/Bitmap.cs +++ b/source/Cosmos.System2/Graphics/Bitmap.cs @@ -145,7 +145,7 @@ public Bitmap(string path, ColorOrder colorOrder = ColorOrder.BGR) : base(0, 0, } /// - /// Create new inctanse of the class, with a specified image data byte array. + /// Create new instance of the class, with a specified image data byte array. /// /// byte array. /// Thrown if imageData is null / memory error. @@ -168,7 +168,7 @@ public Bitmap(byte[] imageData) : this(imageData, ColorOrder.BGR) //Call the ima } /// - /// Create new inctanse of the class, with a specified image data byte array. + /// Create new instance of the class, with a specified image data byte array. /// /// byte array. /// Order of colors in each pixel. diff --git a/source/Cosmos.System2/Network/ARP/ARPPacket.cs b/source/Cosmos.System2/Network/ARP/ARPPacket.cs index 574cbb591e..6b45dda7bd 100644 --- a/source/Cosmos.System2/Network/ARP/ARPPacket.cs +++ b/source/Cosmos.System2/Network/ARP/ARPPacket.cs @@ -92,14 +92,14 @@ internal static void ARPHandler(byte[] packetData) } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal ARPPacket() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. public ARPPacket(byte[] rawData) @@ -120,7 +120,7 @@ protected override void InitFields() } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Destination MAC address. /// Source MAC address. diff --git a/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs b/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs index 90a5683532..0c58382815 100644 --- a/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs +++ b/source/Cosmos.System2/Network/ARP/ARPPacket_Ethernet.cs @@ -37,14 +37,14 @@ internal abstract class ARPPacket_Ethernet : ARPPacket protected Address mTargetIP; /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal ARPPacket_Ethernet() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. internal ARPPacket_Ethernet(byte[] rawData) @@ -69,7 +69,7 @@ protected override void InitFields() } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Operation. /// Source MAC address. @@ -146,14 +146,14 @@ public override string ToString() internal class ARPReply_Ethernet : ARPPacket_Ethernet { /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal ARPReply_Ethernet() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. internal ARPReply_Ethernet(byte[] rawData) @@ -161,7 +161,7 @@ internal ARPReply_Ethernet(byte[] rawData) { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Source MAC address. /// Source IP address. @@ -188,14 +188,14 @@ public override string ToString() internal class ARPRequest_Ethernet : ARPPacket_Ethernet { /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal ARPRequest_Ethernet() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. internal ARPRequest_Ethernet(byte[] rawData) @@ -208,7 +208,7 @@ internal ARPRequest_Ethernet(byte[] rawData) } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Source MAC address. /// Source IP address. diff --git a/source/Cosmos.System2/Network/EthernetPacket.cs b/source/Cosmos.System2/Network/EthernetPacket.cs index 4ae2615b9e..5016ea4f2e 100644 --- a/source/Cosmos.System2/Network/EthernetPacket.cs +++ b/source/Cosmos.System2/Network/EthernetPacket.cs @@ -26,14 +26,14 @@ public class EthernetPacket protected MACAddress destMAC; /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// protected EthernetPacket() { } /// - /// Create new inctanse of the class, with specified raw data. + /// Create new instance of the class, with specified raw data. /// /// Raw data. protected EthernetPacket(byte[] rawData) @@ -53,7 +53,7 @@ protected virtual void InitFields() } /// - /// Create new inctanse of the class, with specified type and size. + /// Create new instance of the class, with specified type and size. /// /// Type. /// Size. @@ -63,7 +63,7 @@ protected EthernetPacket(ushort type, int packet_size) } /// - /// Create new inctanse of the class, with specified dsetination, source, type and size. + /// Create new instance of the class, with specified dsetination, source, type and size. /// /// Destination. /// Source. diff --git a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs index cee7a74ead..c95f0dbd5c 100644 --- a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs @@ -58,7 +58,7 @@ internal static ICMPClient Client(uint iphash) } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// public ICMPClient() { diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs index f7b374c853..dced264527 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs @@ -10,13 +10,13 @@ namespace Cosmos.System.Network.IPv4.UDP.DHCP internal class DHCPAck : DHCPPacket { /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal DHCPAck() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. internal DHCPAck(byte[] rawData) : base(rawData) diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs index dbc9bb537a..e1deba718f 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs @@ -43,7 +43,7 @@ public static Address DHCPServerAddress(NetworkDevice networkDevice) } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Thrown on fatal error (contact support). /// Thrown if UdpClient with localPort 0 exists. diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs index a9f0f440b9..7409100275 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs @@ -10,20 +10,20 @@ namespace Cosmos.System.Network.IPv4.UDP.DHCP internal class DHCPDiscover : DHCPPacket { /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal DHCPDiscover() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. internal DHCPDiscover(byte[] rawData) : base(rawData) { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Source MAC Address. /// Thrown if RawData is invalid or null. diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs index 2e611a1c2a..9ec9ae2576 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs @@ -61,13 +61,13 @@ public static void DHCPHandler(byte[] packetData) } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal DHCPPacket() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. public DHCPPacket(byte[] rawData) @@ -75,7 +75,7 @@ public DHCPPacket(byte[] rawData) { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Source MAC Address. /// DHCP Data size @@ -84,7 +84,7 @@ internal DHCPPacket(MACAddress mac_src, ushort dhcpDataSize) { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Client IPv4 Address. /// Server IPv4 Address. diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs index e9d9ff92e5..e35dd0a9e6 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs @@ -11,20 +11,20 @@ namespace Cosmos.System.Network.IPv4.UDP.DHCP internal class DHCPRelease : DHCPPacket { /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal DHCPRelease() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. internal DHCPRelease(byte[] rawData) : base(rawData) { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Client IPv4 Address. /// DHCP Server IPv4 Address. diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs index 7f01533855..9d39c41634 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs @@ -14,20 +14,20 @@ internal class DHCPRequest : DHCPPacket { /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal DHCPRequest() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. internal DHCPRequest(byte[] rawData) : base(rawData) { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Source MAC Address. /// Requested Address. diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs index 6d81029311..2cff9a0aff 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs @@ -69,14 +69,14 @@ internal static void DNSHandler(byte[] packetData) } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal DNSPacket() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. public DNSPacket(byte[] rawData) @@ -84,7 +84,7 @@ public DNSPacket(byte[] rawData) { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Source address. /// Destination address. @@ -214,14 +214,14 @@ public override string ToString() public class DNSPacketAsk : DNSPacket { /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal DNSPacketAsk() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. public DNSPacketAsk(byte[] rawData) @@ -229,7 +229,7 @@ public DNSPacketAsk(byte[] rawData) { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Source address. /// DNS Server address. @@ -281,14 +281,14 @@ protected override void InitFields() public class DNSPacketAnswer : DNSPacket { /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal DNSPacketAnswer() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. public DNSPacketAnswer(byte[] rawData) diff --git a/source/Cosmos.System2/Network/IPv4/Address.cs b/source/Cosmos.System2/Network/IPv4/Address.cs index 9f31bb94d4..545b61e517 100644 --- a/source/Cosmos.System2/Network/IPv4/Address.cs +++ b/source/Cosmos.System2/Network/IPv4/Address.cs @@ -31,7 +31,7 @@ public class Address : IComparable internal byte[] address = new byte[4]; /// - /// Create new inctanse of the class, with specified IP address. + /// Create new instance of the class, with specified IP address. /// /// First block of the address. /// Second block of the address. @@ -46,7 +46,7 @@ public Address(byte aFirst, byte aSecond, byte aThird, byte aFourth) } /// - /// Create new inctanse of the class, with specified buffer and offset. + /// Create new instance of the class, with specified buffer and offset. /// /// Buffer. /// Offset. diff --git a/source/Cosmos.System2/Network/IPv4/EndPoint.cs b/source/Cosmos.System2/Network/IPv4/EndPoint.cs index 3e68142d02..1c70562629 100644 --- a/source/Cosmos.System2/Network/IPv4/EndPoint.cs +++ b/source/Cosmos.System2/Network/IPv4/EndPoint.cs @@ -24,7 +24,7 @@ public class EndPoint : IComparable public UInt16 port; /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Adress. /// Port. diff --git a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs index c8094e35a9..f237e2a38a 100644 --- a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs @@ -31,7 +31,7 @@ public class ICMPPacket : IPPacket /// /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Packet data. /// Thrown if packetData is invalid. @@ -60,14 +60,14 @@ internal static void ICMPHandler(byte[] packetData) } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal ICMPPacket() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. internal ICMPPacket(byte[] rawData) @@ -89,7 +89,7 @@ protected override void InitFields() } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Source address. /// Destination address. @@ -192,14 +192,14 @@ internal class ICMPEchoRequest : ICMPPacket protected ushort icmpSequence; /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal ICMPEchoRequest() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. internal ICMPEchoRequest(byte[] rawData) @@ -258,14 +258,14 @@ internal class ICMPEchoReply : ICMPPacket protected ushort icmpSequence; /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal ICMPEchoReply() : base() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. internal ICMPEchoReply(byte[] rawData) @@ -286,7 +286,7 @@ protected override void InitFields() } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// ICMP echo request. /// Thrown if RawData is invalid or null. diff --git a/source/Cosmos.System2/Network/IPv4/IPPacket.cs b/source/Cosmos.System2/Network/IPv4/IPPacket.cs index f5d6350dcb..c568950017 100644 --- a/source/Cosmos.System2/Network/IPv4/IPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/IPPacket.cs @@ -70,14 +70,14 @@ internal static void IPv4Handler(byte[] packetData) public static ushort NextIPFragmentID => sNextFragmentID++; /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal IPPacket() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. public IPPacket(byte[] rawData) @@ -108,7 +108,7 @@ protected override void InitFields() } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Data length. /// Protocol. @@ -120,7 +120,7 @@ protected IPPacket(ushort dataLength, byte protocol, Address source, Address des { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Data length. /// Protocol. @@ -133,7 +133,7 @@ protected IPPacket(ushort dataLength, byte protocol, Address source, Address des { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Source MAC address. /// Destination MAC address. diff --git a/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs b/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs index a948401310..a8404ef5f9 100644 --- a/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs +++ b/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs @@ -75,7 +75,7 @@ public enum EntryStatus public Address nextHop; /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Network device. /// IP packet. diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs index cca779d8e9..64a3ba3fd3 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs @@ -54,14 +54,14 @@ internal static void UDPHandler(byte[] packetData) } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal UDPPacket() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Raw data. public UDPPacket(byte[] rawData) @@ -84,7 +84,7 @@ public UDPPacket(Address source, Address dest, UInt16 srcport, UInt16 destport, } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Source address. /// Destination address. diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs index 4702cda710..6bd463d32f 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs @@ -65,7 +65,7 @@ internal static UdpClient Client(ushort destPort) } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Thrown on fatal error (contact support). /// Thrown if UdpClient with localPort 0 exists. @@ -74,7 +74,7 @@ public UdpClient() { } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Local port. /// Thrown on fatal error (contact support). @@ -91,7 +91,7 @@ public UdpClient(int localPort) } /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// /// Destination address. /// Destination port. diff --git a/source/Cosmos.System2/Network/NetworkStack.cs b/source/Cosmos.System2/Network/NetworkStack.cs index 747914b79b..f69acb00eb 100644 --- a/source/Cosmos.System2/Network/NetworkStack.cs +++ b/source/Cosmos.System2/Network/NetworkStack.cs @@ -24,7 +24,7 @@ namespace Cosmos.System.Network public static class NetworkStack { /// - /// Debugger inctanse of the "System" ring, with the "NetworkStack" tag. + /// Debugger instance of the "System" ring, with the "NetworkStack" tag. /// public static Debugger debugger = new Debugger("System", "NetworkStack"); diff --git a/source/Cosmos.System2/Text/CP437Encoding.cs b/source/Cosmos.System2/Text/CP437Encoding.cs index c4e0a285a7..c0901bca9e 100644 --- a/source/Cosmos.System2/Text/CP437Encoding.cs +++ b/source/Cosmos.System2/Text/CP437Encoding.cs @@ -9,12 +9,12 @@ namespace Cosmos.System.ExtendedASCII internal class CP437Enconding : SingleByteEncoding { /// - /// Debugger inctanse of the "System" ring with the "CP437 Encoding" tag. + /// Debugger instance of the "System" ring with the "CP437 Encoding" tag. /// private static Debugger myDebugger = new Debugger("System", "CP437 Encoding"); /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal CP437Enconding() { diff --git a/source/Cosmos.System2/Text/CP858Encoding.cs b/source/Cosmos.System2/Text/CP858Encoding.cs index df04b5db2e..1e7c7ae6aa 100644 --- a/source/Cosmos.System2/Text/CP858Encoding.cs +++ b/source/Cosmos.System2/Text/CP858Encoding.cs @@ -9,12 +9,12 @@ namespace Cosmos.System.ExtendedASCII internal class CP858Enconding : SingleByteEncoding { /// - /// Debugger inctanse of the "System" ring with the "CP858 Encoding" tag. + /// Debugger instance of the "System" ring with the "CP858 Encoding" tag. /// private static Debugger myDebugger = new Debugger("System", "CP858 Encoding"); /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal CP858Enconding() { diff --git a/source/Cosmos.System2/Text/CosmosEncodingProvider.cs b/source/Cosmos.System2/Text/CosmosEncodingProvider.cs index bea5d7b88d..00be478c63 100644 --- a/source/Cosmos.System2/Text/CosmosEncodingProvider.cs +++ b/source/Cosmos.System2/Text/CosmosEncodingProvider.cs @@ -14,12 +14,12 @@ public class CosmosEncodingProvider : EncodingProvider /// private static readonly EncodingProvider s_singleton = new CosmosEncodingProvider(); /// - /// Debugger inctanse of the "System" ring with the "CosmosEncodingProvider" tag. + /// Debugger instance of the "System" ring with the "CosmosEncodingProvider" tag. /// private static Debugger myDebugger = new Debugger("System", "CosmosEncodingProvider"); /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// internal CosmosEncodingProvider() { } diff --git a/source/Cosmos.System2/Text/EncodingTable.cs b/source/Cosmos.System2/Text/EncodingTable.cs index 3cde185b02..5530f4dc6e 100644 --- a/source/Cosmos.System2/Text/EncodingTable.cs +++ b/source/Cosmos.System2/Text/EncodingTable.cs @@ -14,12 +14,12 @@ namespace Cosmos.System.ExtendedASCII internal static class EncodingTable { /// - /// Debugger inctanse of the "System" ring with the "EncodingTable" tag. + /// Debugger instance of the "System" ring with the "EncodingTable" tag. /// private static Debugger mDebugger = new Debugger("System", "EncodingTable"); /// - /// Create new inctanse of the class. + /// Create new instance of the class. /// static EncodingTable() { @@ -44,7 +44,7 @@ private struct values public Encoding encoding; /// - /// Create new inctanse of the struct. + /// Create new instance of the struct. /// /// Description. /// Encoding. diff --git a/source/Cosmos.System2/Text/SingleByteEncoding.cs b/source/Cosmos.System2/Text/SingleByteEncoding.cs index 3cfc5d577b..0eba7d4083 100644 --- a/source/Cosmos.System2/Text/SingleByteEncoding.cs +++ b/source/Cosmos.System2/Text/SingleByteEncoding.cs @@ -11,7 +11,7 @@ namespace Cosmos.System.ExtendedASCII internal class SingleByteEncoding : Encoding { /// - /// Debugger inctanse of the "System" ring with the "SingleByteEncoding" tag. + /// Debugger instance of the "System" ring with the "SingleByteEncoding" tag. /// private static Debugger mDebugger = new Debugger("System", "SingleByteEncoding"); From a0a2d3af994b0eeb0859e8a6d9f98e89f6c97354 Mon Sep 17 00:00:00 2001 From: Quajak Date: Thu, 21 Jan 2021 09:50:01 +0100 Subject: [PATCH 040/314] Update issue templates Removed duplicate issue template and remove template for questions since they should be asked in discussions and not issues. --- .github/ISSUE_TEMPLATE/feature_request.md | 22 --------------- .../ISSUE_TEMPLATE/installation-problem.md | 28 ------------------- 2 files changed, 50 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md delete mode 100644 .github/ISSUE_TEMPLATE/installation-problem.md diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 5c6c65b4d3..0000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for Cosmos -title: '' -labels: Question -assignees: '' - ---- - -Have you checked for similar suggestions? - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/installation-problem.md b/.github/ISSUE_TEMPLATE/installation-problem.md deleted file mode 100644 index daceee95c6..0000000000 --- a/.github/ISSUE_TEMPLATE/installation-problem.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: Installation Problem -about: Create a report to help us improve -title: '' -labels: 'Area: Installer' -assignees: '' - ---- - -**Describe the problem** -A clear and concise description of where the installation is going wrong/what error messages you got. - -**Steps of installation up to now** -What steps of the installation have you done up to now: - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Logs** -Please post the entire log given by Cosmos. For long logs please use pastebin. - -**Setup (please complete the following information):** - - Cosmos Version (Userkit/Devkit) - - Are you using an admin account? - - VS Version if applicable - -**Additional context** -Add any other context about the problem here. From 584568bceb1439e23b1a328f240a9e6c0b6ec850 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 21 Jan 2021 15:54:33 +0100 Subject: [PATCH 041/314] Change Remove function use for instead foreach and Equals instead string compar --- source/Cosmos.System2/Network/Config/DNSConfig.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/source/Cosmos.System2/Network/Config/DNSConfig.cs b/source/Cosmos.System2/Network/Config/DNSConfig.cs index 9f74ecbfe8..9fd9b44d62 100644 --- a/source/Cosmos.System2/Network/Config/DNSConfig.cs +++ b/source/Cosmos.System2/Network/Config/DNSConfig.cs @@ -37,15 +37,13 @@ public static void Add(Address nameserver) /// public static void Remove(Address nameserver) { - int counter = 0; - - foreach (var ns in DNSNameservers) + for (int i = 0; i < DNSNameservers.Count; i++) { - if (ns.address.ToString() == nameserver.address.ToString()) + if (DNSNameservers[i].address.Equals(nameserver)) { - DNSNameservers.RemoveAt(counter); + DNSNameservers.RemoveAt(i); + return; } - counter++; } } From eaf05f4c57516c96d6f93342c2a050b03d9bb95e Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 21 Jan 2021 16:37:33 +0100 Subject: [PATCH 042/314] Rename Client to GetClient + some code clean + Add rewrite --- source/Cosmos.HAL2/Network/MACAddress.cs | 26 ++++++++++++------- source/Cosmos.System2/Network/ARP/ARPCache.cs | 8 ++---- .../Network/Config/DNSConfig.cs | 4 +-- .../Cosmos.System2/Network/IPV4/ICMPClient.cs | 2 +- .../Network/IPV4/UDP/DNS/DNSPacket.cs | 2 +- .../Cosmos.System2/Network/IPv4/ICMPPacket.cs | 2 +- .../Network/IPv4/UDP/UDPPacket.cs | 2 +- .../Network/IPv4/UDP/UdpClient.cs | 2 +- 8 files changed, 26 insertions(+), 22 deletions(-) diff --git a/source/Cosmos.HAL2/Network/MACAddress.cs b/source/Cosmos.HAL2/Network/MACAddress.cs index 073e82917c..73b50b1677 100644 --- a/source/Cosmos.HAL2/Network/MACAddress.cs +++ b/source/Cosmos.HAL2/Network/MACAddress.cs @@ -33,7 +33,9 @@ static MACAddress() public MACAddress(byte[] address) { if (address == null || address.Length != 6) + { throw new ArgumentException("MACAddress is null or has wrong length", "address"); + } bytes[0] = address[0]; bytes[1] = address[1]; @@ -52,7 +54,9 @@ public MACAddress(byte[] address) public MACAddress(byte[] buffer, int offset) { if (buffer == null || buffer.Length < (offset + 6)) + { throw new ArgumentException("buffer does not contain enough data starting at offset", "buffer"); + } bytes[0] = buffer[offset]; bytes[1] = buffer[offset + 1]; @@ -95,7 +99,9 @@ public int CompareTo(object obj) return 0; } else + { throw new ArgumentException("obj is not a MACAddress", "obj"); + } } public override bool Equals(object obj) @@ -112,17 +118,19 @@ public override bool Equals(object obj) bytes[5] == other.bytes[5]; } else + { throw new ArgumentException("obj is not a MACAddress", "obj"); + } } public override int GetHashCode() { - return (GetType().AssemblyQualifiedName + "|" + this.ToString()).GetHashCode(); + return (GetType().AssemblyQualifiedName + "|" + ToString()).GetHashCode(); } - public UInt64 ToNumber() + public ulong ToNumber() { - return (UInt64)((bytes[0] << 40) | (bytes[1] << 32) | (bytes[2] << 24) | (bytes[3] << 16) | + return (ulong)((bytes[0] << 40) | (bytes[1] << 32) | (bytes[2] << 24) | (bytes[3] << 16) | (bytes[4] << 8) | (bytes[5] << 0)); } @@ -133,23 +141,23 @@ private static void PutByte(char[] aChars, int aIndex, byte aByte) aChars[aIndex + 1] = xChars[aByte & 0xF]; } - public UInt32 to32BitNumber() + public uint To32BitNumber() { - return (UInt32)((bytes[0] << 40) | (bytes[1] << 32) | (bytes[2] << 24) | (bytes[3] << 16) | + return (uint)((bytes[0] << 40) | (bytes[1] << 32) | (bytes[2] << 24) | (bytes[3] << 16) | (bytes[4] << 8) | (bytes[5] << 0)); } - private UInt32 hash; + private uint hash; /// /// Hash value for this mac. Used to uniquely identify each mac /// - public UInt32 Hash + public uint Hash { get { if (hash == 0) { - hash = to32BitNumber(); + hash = To32BitNumber(); } return hash; @@ -171,7 +179,7 @@ public override string ToString() PutByte(xChars, 12, bytes[4]); xChars[14] = ':'; PutByte(xChars, 15, bytes[5]); - return new String(xChars); + return new string(xChars); } } } diff --git a/source/Cosmos.System2/Network/ARP/ARPCache.cs b/source/Cosmos.System2/Network/ARP/ARPCache.cs index b963d1c259..1d09564f6d 100644 --- a/source/Cosmos.System2/Network/ARP/ARPCache.cs +++ b/source/Cosmos.System2/Network/ARP/ARPCache.cs @@ -19,7 +19,7 @@ internal static class ARPCache /// /// Cache. /// - private static Dictionary cache; + public static Dictionary cache; /// /// Ensure cache exists. @@ -55,11 +55,7 @@ internal static bool Contains(IPv4.Address ipAddress) internal static void Update(IPv4.Address ipAddress, MACAddress macAddress) { ensureCacheExists(); - if (ipAddress == null) - { - global::System.Console.Write(""); - } - UInt32 ip_hash = ipAddress.Hash; + uint ip_hash = ipAddress.Hash; if (ip_hash == 0) { return; diff --git a/source/Cosmos.System2/Network/Config/DNSConfig.cs b/source/Cosmos.System2/Network/Config/DNSConfig.cs index 9fd9b44d62..7967b580f5 100644 --- a/source/Cosmos.System2/Network/Config/DNSConfig.cs +++ b/source/Cosmos.System2/Network/Config/DNSConfig.cs @@ -21,9 +21,9 @@ public class DNSConfig /// public static void Add(Address nameserver) { - foreach (var ns in DNSNameservers) + for (int i = 0; i < DNSNameservers.Count; i++) { - if (ns.address.ToString() == nameserver.address.ToString()) + if (DNSNameservers[i].address.Equals(nameserver)) { return; } diff --git a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs index c95f0dbd5c..fcc348cf92 100644 --- a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs @@ -47,7 +47,7 @@ static ICMPClient() /// /// IP Hash. /// ICMPClient - internal static ICMPClient Client(uint iphash) + internal static ICMPClient GetClient(uint iphash) { if (clients.ContainsKey(iphash) == true) { diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs index 2cff9a0aff..2f8aba0536 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs @@ -61,7 +61,7 @@ internal static void DNSHandler(byte[] packetData) { DNSPacket dns_packet = new DNSPacket(packetData); - DnsClient receiver = (DnsClient)UdpClient.Client(dns_packet.DestinationPort); + DnsClient receiver = (DnsClient)UdpClient.GetClient(dns_packet.DestinationPort); if (receiver != null) { receiver.receiveData(dns_packet); diff --git a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs index f237e2a38a..0e5d5cedf6 100644 --- a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs @@ -42,7 +42,7 @@ internal static void ICMPHandler(byte[] packetData) switch (icmp_packet.ICMP_Type) { case 0: - ICMPClient receiver = ICMPClient.Client(icmp_packet.SourceIP.Hash); + ICMPClient receiver = ICMPClient.GetClient(icmp_packet.SourceIP.Hash); if (receiver != null) { receiver.receiveData(icmp_packet); diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs index 64a3ba3fd3..a77dc2bbb1 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs @@ -46,7 +46,7 @@ internal static void UDPHandler(byte[] packetData) return; } - UdpClient receiver = UdpClient.Client(udp_packet.DestinationPort); + UdpClient receiver = UdpClient.GetClient(udp_packet.DestinationPort); if (receiver != null) { receiver.receiveData(udp_packet); diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs index 6bd463d32f..dd9e459cd0 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs @@ -54,7 +54,7 @@ static UdpClient() /// /// Destination port. /// UdpClient - internal static UdpClient Client(ushort destPort) + internal static UdpClient GetClient(ushort destPort) { if (clients.ContainsKey((uint)destPort) == true) { From a2ba53d610d932903fbb407a6ec62e90a38f972d Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 21 Jan 2021 16:49:48 +0100 Subject: [PATCH 043/314] Change name --- .../Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs | 2 +- source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs index 2f8aba0536..2e705d1196 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs @@ -138,7 +138,7 @@ protected override void InitFields() /// /// Data /// Data offset - public string parseName(byte[] RawData, ref int index) + public string ParseName(byte[] RawData, ref int index) { StringBuilder url = new StringBuilder(); diff --git a/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs b/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs index a8404ef5f9..8eaa97982e 100644 --- a/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs +++ b/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs @@ -103,7 +103,7 @@ public BufferEntry(NetworkDevice nic, IPPacket packet) /// /// Ensure queue exists. /// - private static void ensureQueueExists() + private static void EnsureQueueExists() { if (queue == null) { @@ -117,7 +117,7 @@ private static void ensureQueueExists() /// IP packet. internal static void AddPacket(IPPacket packet) { - ensureQueueExists(); + EnsureQueueExists(); NetworkDevice nic = IPConfig.FindInterface(packet.SourceIP); packet.SourceMAC = nic.MACAddress; queue.Add(new BufferEntry(nic, packet)); @@ -130,7 +130,7 @@ internal static void AddPacket(IPPacket packet) /// Network Interface Controller. internal static void AddPacket(IPPacket packet, NetworkDevice device) { - ensureQueueExists(); + EnsureQueueExists(); packet.SourceMAC = device.MACAddress; queue.Add(new BufferEntry(device, packet)); } @@ -143,7 +143,7 @@ internal static void AddPacket(IPPacket packet, NetworkDevice device) /// Thrown if RawData length is bigger than Int32.MaxValue. internal static void Send() { - ensureQueueExists(); + EnsureQueueExists(); int _deltaT = 0; int second = 0; @@ -249,7 +249,7 @@ internal static void Send() /// Thrown if arp_reply.SenderIP is not a IPv4Address. internal static void ARPCache_Update(ARPReply_Ethernet arp_reply) { - ensureQueueExists(); + EnsureQueueExists(); //foreach (BufferEntry entry in queue) for (int e = 0; e < queue.Count; e++) { From cd6ac526393cee169b4ca7389267103fe503b3ea Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 21 Jan 2021 17:29:45 +0100 Subject: [PATCH 044/314] Add IDisposable for UDP, ICMP and DNS client --- .../Cosmos.System2/Network/IPV4/ICMPClient.cs | 10 +++++++++- .../Network/IPV4/UDP/DNS/DNSPacket.cs | 2 +- .../Network/IPv4/UDP/UdpClient.cs | 20 +++++++++++++------ 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs index fcc348cf92..df55e9788b 100644 --- a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs @@ -16,7 +16,7 @@ namespace Cosmos.System.Network.IPv4 /// /// ICMPClient class. Used to manage the ICMP connection to a client. /// - public class ICMPClient + public class ICMPClient : IDisposable { /// /// Clients dictionary. @@ -139,5 +139,13 @@ public void receiveData(ICMPPacket packet) { rxBuffer.Enqueue(packet); } + + /// + /// Close Client + /// + public void Dispose() + { + Close(); + } } } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs index 2e705d1196..2214282b10 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs @@ -317,7 +317,7 @@ protected override void InitFields() for (int i = 0; i < Questions; i++) { DNSQuery query = new DNSQuery(); - query.Name = parseName(RawData, ref index); + query.Name = ParseName(RawData, ref index); query.Type = (ushort)((RawData[index + 0] << 8) | RawData[index + 1]); query.Class = (ushort)((RawData[index + 2] << 8) | RawData[index + 3]); Queries.Add(query); diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs index dd9e459cd0..8e56230278 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs @@ -15,7 +15,7 @@ namespace Cosmos.System.Network.IPv4.UDP /// /// UdpClient class. Used to manage the UDP connection to a client. /// - public class UdpClient + public class UdpClient : IDisposable { /// /// Clients dictionary. @@ -25,15 +25,15 @@ public class UdpClient /// /// Local port. /// - protected Int32 localPort; + protected int localPort; /// /// Destination address. /// - protected IPv4.Address destination; + protected Address destination; /// /// Destination port. /// - protected Int32 destinationPort; + protected int destinationPort; /// /// RX buffer queue. @@ -175,7 +175,7 @@ public byte[] NonBlockingReceive(ref EndPoint source) return null; } - UDPPacket packet = new UDPPacket(rxBuffer.Dequeue().RawData); + var packet = new UDPPacket(rxBuffer.Dequeue().RawData); source.address = packet.SourceIP; source.port = packet.SourcePort; @@ -192,7 +192,7 @@ public byte[] Receive(ref EndPoint source) { while (rxBuffer.Count < 1) ; - UDPPacket packet = new UDPPacket(rxBuffer.Dequeue().RawData); + var packet = new UDPPacket(rxBuffer.Dequeue().RawData); source.address = packet.SourceIP; source.port = packet.SourcePort; @@ -209,5 +209,13 @@ internal void receiveData(UDPPacket packet) { rxBuffer.Enqueue(packet); } + + /// + /// Close Client + /// + public void Dispose() + { + Close(); + } } } From 854264457e4a1a946b43973bc0124eadab92576c Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 21 Jan 2021 17:34:04 +0100 Subject: [PATCH 045/314] Change typo + throw exeption --- source/Cosmos.System2/Network/IPV4/ICMPClient.cs | 2 +- source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs | 4 ++-- source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs | 2 +- source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs | 2 +- source/Cosmos.System2/Network/IPv4/ICMPPacket.cs | 2 +- source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs | 2 +- source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs index df55e9788b..293906b713 100644 --- a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/ICMPClient.cs @@ -135,7 +135,7 @@ public int Receive(ref EndPoint source, int timeout = 5000) /// Packet to receive. /// Thrown on fatal error (contact support). /// Thrown on IO error. - public void receiveData(ICMPPacket packet) + public void ReceiveData(ICMPPacket packet) { rxBuffer.Enqueue(packet); } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs index e1deba718f..29bc341cbd 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs @@ -68,7 +68,7 @@ public void Close() /// Packet to receive. /// Thrown on fatal error (contact support). /// Thrown on IO error. - internal void receiveData(DHCPPacket packet) + internal void ReceiveData(DHCPPacket packet) { rxBuffer.Enqueue(packet); } @@ -198,7 +198,7 @@ private void Apply(DHCPAck packet, bool message = false) packet.Client.ToString() == null || packet.Client.ToString() == null) { - Global.mDebugger.Send("Parsing DHCP ACK Packet failed, can't apply network configuration."); + throw new Exception("Parsing DHCP ACK Packet failed, can't apply network configuration."); } else { diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs index 9ec9ae2576..e559742f5b 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs @@ -56,7 +56,7 @@ public static void DHCPHandler(byte[] packetData) DHCPClient receiver = DHCPClient.currentClient; if (receiver != null) { - receiver.receiveData(dhcp_packet); + receiver.ReceiveData(dhcp_packet); } } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs index 2214282b10..bb1b98664c 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs @@ -64,7 +64,7 @@ internal static void DNSHandler(byte[] packetData) DnsClient receiver = (DnsClient)UdpClient.GetClient(dns_packet.DestinationPort); if (receiver != null) { - receiver.receiveData(dns_packet); + receiver.ReceiveData(dns_packet); } } diff --git a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs index 0e5d5cedf6..bd703e48e2 100644 --- a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs @@ -45,7 +45,7 @@ internal static void ICMPHandler(byte[] packetData) ICMPClient receiver = ICMPClient.GetClient(icmp_packet.SourceIP.Hash); if (receiver != null) { - receiver.receiveData(icmp_packet); + receiver.ReceiveData(icmp_packet); } Global.mDebugger.Send("Received ICMP Echo reply from " + icmp_packet.SourceIP.ToString()); break; diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs index a77dc2bbb1..de9861a8ca 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs @@ -49,7 +49,7 @@ internal static void UDPHandler(byte[] packetData) UdpClient receiver = UdpClient.GetClient(udp_packet.DestinationPort); if (receiver != null) { - receiver.receiveData(udp_packet); + receiver.ReceiveData(udp_packet); } } diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs index 8e56230278..46c24ab240 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs @@ -205,7 +205,7 @@ public byte[] Receive(ref EndPoint source) /// Packet to receive. /// Thrown on fatal error (contact support). /// Thrown on IO error. - internal void receiveData(UDPPacket packet) + internal void ReceiveData(UDPPacket packet) { rxBuffer.Enqueue(packet); } From c01d4b9f6aa944bf8ae3ec2b3e65fc85a014ad1f Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 21 Jan 2021 18:31:10 +0100 Subject: [PATCH 046/314] Inhereit DHCPClient from UDPClient + remove static Client + Add more tests --- Tests/Kernels/NetworkTest/Kernel.cs | 34 +++++++++---- .../Cosmos.System2/Network/EthernetPacket.cs | 2 +- .../Network/IPV4/UDP/DHCP/DHCPClient.cs | 48 ++++--------------- .../Network/IPV4/UDP/DHCP/DHCPPacket.cs | 4 +- 4 files changed, 35 insertions(+), 53 deletions(-) diff --git a/Tests/Kernels/NetworkTest/Kernel.cs b/Tests/Kernels/NetworkTest/Kernel.cs index e9d17cd967..55133de8bc 100644 --- a/Tests/Kernels/NetworkTest/Kernel.cs +++ b/Tests/Kernels/NetworkTest/Kernel.cs @@ -1,4 +1,5 @@ using Cosmos.HAL; +using Cosmos.System.Network; using Cosmos.System.Network.ARP; using Cosmos.System.Network.Config; using Cosmos.System.Network.IPv4; @@ -21,19 +22,22 @@ protected override void BeforeRun() protected override void Run() { - /** - * Since DNS and DHCP are inherited and will call parent classes at creation. UDP, IP and EthernetFrame don't need tests - **/ + /** Ethernet Packet Parsing Test **/ + byte[] ethernetPacketData = new byte[] + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x0C, 0x29, 0xD5, 0xDB, 0x9D, 0x08, 0x00 + }; + EthernetPacket ethernetPacket = new EthernetPacket(ethernetPacketData); + Equals(ethernetPacketData, ethernetPacket.RawData); - /** DNS Packet Parsing Test **/ - byte[] dnsPacketData = new byte[] + /** IP Packet Parsing Test **/ + byte[] ipPacketData = new byte[] { - 0xB8, 0xD9, 0x4D, 0xC1, 0xA5, 0xFC, 0x98, 0xFA, 0x9B, 0xD4, 0xEB, 0x29, 0x08, 0x00, 0x45, 0x00, 0x00, 0x38, 0xC3, 0x1C, 0x00, 0x00, 0x80, 0x11, 0x00, - 0x00, 0xC0, 0xA8, 0x01, 0x46, 0xC0, 0xA8, 0x01, 0xFE, 0xF0, 0x66, 0x00, 0x35, 0x00, 0x24, 0x84, 0xCA, 0xD6, 0x80, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x69, 0x74, 0x74, 0x65, 0x72, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x01, 0x00, 0x01 + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x0C, 0x29, 0xD5, 0xDB, 0x9D, 0x08, 0x00, 0x45, 0x00, 0x01, 0x16, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x39, + 0xD8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF }; - DNSPacket dnsPacket = new DNSPacket(dnsPacketData); - Equals(dnsPacketData, dnsPacket.RawData); + IPPacket ipPacket = new IPPacket(ipPacketData); + Equals(ipPacketData, ipPacket.RawData); /** UDP Packet Parsing Test **/ byte[] udpPacketData = new byte[] @@ -44,6 +48,16 @@ protected override void Run() UDPPacket udpPacket = new UDPPacket(udpPacketData); Equals(udpPacketData, udpPacket.RawData); + /** DNS Packet Parsing Test **/ + byte[] dnsPacketData = new byte[] + { + 0xB8, 0xD9, 0x4D, 0xC1, 0xA5, 0xFC, 0x98, 0xFA, 0x9B, 0xD4, 0xEB, 0x29, 0x08, 0x00, 0x45, 0x00, 0x00, 0x38, 0xC3, 0x1C, 0x00, 0x00, 0x80, 0x11, 0x00, + 0x00, 0xC0, 0xA8, 0x01, 0x46, 0xC0, 0xA8, 0x01, 0xFE, 0xF0, 0x66, 0x00, 0x35, 0x00, 0x24, 0x84, 0xCA, 0xD6, 0x80, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x69, 0x74, 0x74, 0x65, 0x72, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x01, 0x00, 0x01 + }; + DNSPacket dnsPacket = new DNSPacket(dnsPacketData); + Equals(dnsPacketData, dnsPacket.RawData); + /** DHCP Packet Parsing Test **/ byte[] dhcpPacketData = new byte[] { diff --git a/source/Cosmos.System2/Network/EthernetPacket.cs b/source/Cosmos.System2/Network/EthernetPacket.cs index 5016ea4f2e..876df7c358 100644 --- a/source/Cosmos.System2/Network/EthernetPacket.cs +++ b/source/Cosmos.System2/Network/EthernetPacket.cs @@ -36,7 +36,7 @@ protected EthernetPacket() /// Create new instance of the class, with specified raw data. /// /// Raw data. - protected EthernetPacket(byte[] rawData) + public EthernetPacket(byte[] rawData) { RawData = rawData; InitFields(); diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs index 29bc341cbd..bb53499814 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs @@ -16,18 +16,8 @@ namespace Cosmos.System.Network.IPv4.UDP.DHCP /// /// DHCPClient class. Used to manage the DHCP connection to a server. /// - public class DHCPClient + public class DHCPClient : UdpClient { - /// - /// Current DHCPClient - /// - public static DHCPClient currentClient; - - // - /// RX buffer queue. - /// - protected Queue rxBuffer; - // /// Is DHCP ascked check variable /// @@ -43,34 +33,12 @@ public static Address DHCPServerAddress(NetworkDevice networkDevice) } /// - /// Create new instance of the class. + /// Create new instance of the class. /// /// Thrown on fatal error (contact support). - /// Thrown if UdpClient with localPort 0 exists. - public DHCPClient() - { - rxBuffer = new Queue(8); - currentClient = this; - } - - /// - /// Close connection. - /// - /// Thrown on fatal error (contact support). - public void Close() - { - currentClient = null; - } - - /// - /// Receive data from packet. - /// - /// Packet to receive. - /// Thrown on fatal error (contact support). - /// Thrown on IO error. - internal void ReceiveData(DHCPPacket packet) + /// Thrown if UdpClient with localPort 53 exists. + public DHCPClient() : base(68) { - rxBuffer.Enqueue(packet); } /// @@ -90,14 +58,14 @@ private int Receive(int timeout = 5000) { return -1; } - if (_deltaT != Cosmos.HAL.RTC.Second) + if (_deltaT != RTC.Second) { second++; - _deltaT = Cosmos.HAL.RTC.Second; + _deltaT = RTC.Second; } } - var packet = rxBuffer.Dequeue(); + var packet = new DHCPPacket(rxBuffer.Dequeue().RawData); if (packet.MessageType == 2) //Boot Reply { @@ -107,7 +75,7 @@ private int Receive(int timeout = 5000) } else if (packet.RawData[284] == 0x05 || packet.RawData[284] == 0x06) //ACK or NAK DHCP packet received { - DHCPAck ack = new DHCPAck(packet.RawData); + var ack = new DHCPAck(packet.RawData); if (asked) { Apply(ack, true); diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs index e559742f5b..12550fb6aa 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs @@ -51,9 +51,9 @@ public class DHCPPacket : UDPPacket /// Thrown on IO error. public static void DHCPHandler(byte[] packetData) { - DHCPPacket dhcp_packet = new DHCPPacket(packetData); + var dhcp_packet = new DHCPPacket(packetData); - DHCPClient receiver = DHCPClient.currentClient; + var receiver = UdpClient.GetClient(dhcp_packet.DestinationPort); if (receiver != null) { receiver.ReceiveData(dhcp_packet); From f6bf35209e272a0a51744f59162565f4289aeffb Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 21 Jan 2021 18:36:37 +0100 Subject: [PATCH 047/314] using in article --- Docs/articles/Kernel/Network.md | 75 ++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index b2ddc44359..7202c29dff 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -20,59 +20,68 @@ IPConfig.Enable(nic, new Address(192, 168, 1, 69), new Address(255, 255, 255, 0) ``` ### Dynamically set IPv4 Config through DHCP ```csharp -var xClient = new DHCPClient(); +using(var xClient = new DHCPClient()) +{ + /** Send a DHCP Discover packet **/ + //This will automatically set the IP config after DHCP response + xClient.SendDiscoverPacket(); -/** Send a DHCP Discover packet **/ -//This will automatically set the IP config after DHCP response -xClient.SendDiscoverPacket(); + /** Send a DHCP Release packet **/ + xClient.SendReleasePacket(); //will tell the DHCP server to delete the address -/** Send a DHCP Release packet **/ -xClient.SendReleasePacket(); //will tell the DHCP server to delete the address - -xClient.Close(); + xClient.Close(); //don't forget to close! +} ``` ## 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 -var xClient = new UdpClient(4242); -xClient.Connect(new Address(192, 168, 1, 70), 4242); +using(var xClient = new UdpClient(4242)) +{ + xClient.Connect(new Address(192, 168, 1, 70), 4242); -/** Send data **/ -xClient.Send(Encoding.ASCII.GetBytes(message)); + /** Send data **/ + xClient.Send(Encoding.ASCII.GetBytes(message)); -/** Receive data **/ -var endpoint = new EndPoint(Address.Zero, 0); -xClient.Receive(ref endpoint); //set endpoint to remote machine IP:port -xClient.NonBlockingReceive(ref endpoint); //retrieve receive buffer without waiting + /** Receive data **/ + var endpoint = new EndPoint(Address.Zero, 0); + xClient.Receive(ref endpoint); //set endpoint to remote machine IP:port + xClient.NonBlockingReceive(ref endpoint); //retrieve receive buffer without waiting -xClient.Close(); //don't forget to close! + xClient.Close(); +} ``` ## ICMP For ICMP, we will only 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 -var xClient = new ICMPClient(); -xClient.Connect(new Address(192, 168, 1, 254)); +using(var xClient = new ICMPClient()) +{ + xClient.Connect(new Address(192, 168, 1, 254)); + + /** Send ICMP Echo **/ + xClient.SendEcho(); -/** Send ICMP Echo **/ -xClient.SendEcho(); + /** Receive ICMP Response **/ + int time = xClient.Receive(ref endpoint); //return elapsed time / timeout if no response -/** Receive ICMP Response **/ -int time = xClient.Receive(ref endpoint); //return elapsed time / timeout if no response + xClient.Close(); +} -xClient.Close(); //don't forget to close! ``` ## DNS DNS can be used to get an IP address from a Domain Name string. For now DNS can only ask for one domain name at the same time. ```csharp -var xClient = new DnsClient(); -xClient.Connect(new Address(192, 168, 1, 254)); //DNS Server address - -/** Send DNS ask for a single domain name **/ -xClient.SendAsk("github.com"); - -/** Receive DNS Response **/ -Address destination = xClient.Receive(); //can set a timeout value -xClient.Close(); +using(var xClient = new DnsClient()) +{ + xClient.Connect(new Address(192, 168, 1, 254)); //DNS Server address + + /** Send DNS ask for a single domain name **/ + xClient.SendAsk("github.com"); + + /** Receive DNS Response **/ + Address destination = xClient.Receive(); //can set a timeout value + + xClient.Close(); +} ``` From 2d67dd81e287ee2bcbe1d28838f78535aa22345c Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 21 Jan 2021 18:36:44 +0100 Subject: [PATCH 048/314] using in article From 85dd420fb6519052788cfd0ed6cafef12bb40eec Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 21 Jan 2021 18:50:03 +0100 Subject: [PATCH 049/314] ICMPPacket clean + remove useless initfields methods --- .../Network/IPV4/UDP/DHCP/DHCPDiscover.cs | 6 -- .../Network/IPV4/UDP/DHCP/DHCPRelease.cs | 10 --- .../Network/IPV4/UDP/DHCP/DHCPRequest.cs | 10 --- .../Network/IPV4/UDP/DNS/DNSPacket.cs | 9 -- .../Cosmos.System2/Network/IPv4/ICMPPacket.cs | 88 +++++++++---------- 5 files changed, 43 insertions(+), 80 deletions(-) diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs index 7409100275..e4cf7b82d7 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs @@ -46,11 +46,5 @@ internal DHCPDiscover(MACAddress mac_src) : base(mac_src, 10) //discover packet RawData[291] = 0xff; //ENDMARK } - - protected override void InitFields() - { - base.InitFields(); - } - } } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs index e35dd0a9e6..ef1d2b9bc2 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs @@ -61,15 +61,5 @@ internal DHCPRelease(Address client, Address server, MACAddress source) : base(c RawData[300] = 0xff; //ENDMARK } - - /// - /// Init DHCPRelease fields. - /// - /// Thrown if RawData is invalid or null. - protected override void InitFields() - { - base.InitFields(); - } - } } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs index 9d39c41634..a98b538413 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs @@ -70,15 +70,5 @@ internal DHCPRequest(MACAddress mac_src, Address RequestedAddress, Address DHCPS RawData[303] = 0xff; //ENDMARK } - - /// - /// Init DHCPRequest fields. - /// - /// Thrown if RawData is invalid or null. - protected override void InitFields() - { - base.InitFields(); - } - } } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs index bb1b98664c..3d3a7a5e16 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs @@ -264,15 +264,6 @@ public DNSPacketAsk(Address source, Address dest, string url) RawData[this.DataOffset + 20 + b + 3] = 0x00; RawData[this.DataOffset + 20 + b + 4] = 0x01; } - - /// - /// Init DNSPacketAsk fields. - /// - /// Thrown if RawData is invalid or null. - protected override void InitFields() - { - base.InitFields(); - } } /// diff --git a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs index bd703e48e2..61dafad05f 100644 --- a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs @@ -38,11 +38,11 @@ public class ICMPPacket : IPPacket internal static void ICMPHandler(byte[] packetData) { Global.mDebugger.Send("ICMP Handler called"); - ICMPPacket icmp_packet = new ICMPPacket(packetData); - switch (icmp_packet.ICMP_Type) + var icmp_packet = new ICMPPacket(packetData); + switch (icmp_packet.ICMPType) { case 0: - ICMPClient receiver = ICMPClient.GetClient(icmp_packet.SourceIP.Hash); + var receiver = ICMPClient.GetClient(icmp_packet.SourceIP.Hash); if (receiver != null) { receiver.ReceiveData(icmp_packet); @@ -50,8 +50,8 @@ internal static void ICMPHandler(byte[] packetData) Global.mDebugger.Send("Received ICMP Echo reply from " + icmp_packet.SourceIP.ToString()); break; case 8: - ICMPEchoRequest request = new ICMPEchoRequest(packetData); - ICMPEchoReply reply = new ICMPEchoReply(request); + var request = new ICMPEchoRequest(packetData); + var reply = new ICMPEchoReply(request); Global.mDebugger.Send("Sending ICMP Echo reply to " + reply.DestinationIP.ToString()); OutgoingBuffer.AddPacket(reply); NetworkStack.Update(); @@ -131,31 +131,22 @@ protected ushort CalcICMPCRC(ushort length) /// /// Get ICMP type. /// - internal byte ICMP_Type - { - get { return icmpType; } - } + internal byte ICMPType => icmpType; + /// /// Get ICMP code. /// - internal byte ICMP_Code - { - get { return icmpCode; } - } + internal byte ICMPCode => icmpCode; + /// /// Get ICMP CRC. /// - internal ushort ICMP_CRC - { - get { return icmpCRC; } - } + internal ushort ICMPCRC => icmpCRC; + /// /// Get ICMP data length. /// - internal ushort ICMP_DataLength - { - get { return (ushort)(DataLength - 8); } - } + internal ushort ICMPDataLength => (ushort)(DataLength - 8); /// /// Get ICMP data. @@ -163,9 +154,9 @@ internal ushort ICMP_DataLength /// byte array value. internal byte[] GetICMPData() { - byte[] data = new byte[ICMP_DataLength]; + byte[] data = new byte[ICMPDataLength]; - for (int b = 0; b < ICMP_DataLength; b++) + for (int b = 0; b < ICMPDataLength; b++) { data[b] = RawData[DataOffset + 8 + b]; } @@ -207,37 +198,49 @@ internal ICMPEchoRequest(byte[] rawData) { } + /// + /// Create new instance of the class. + /// + /// Source address. + /// Destination address. + /// ID. + /// Sequence. + /// Thrown if RawData is invalid or null. internal ICMPEchoRequest(Address source, Address dest, ushort id, ushort sequence) : base(source, dest, 8, 0, id, sequence, 40) { - for (int b = 8; b < ICMP_DataLength; b++) + for (int b = 8; b < ICMPDataLength; b++) { RawData[DataOffset + b] = (byte)b; } RawData[DataOffset + 2] = 0x00; RawData[DataOffset + 3] = 0x00; - icmpCRC = CalcICMPCRC((ushort)(ICMP_DataLength + 8)); + icmpCRC = CalcICMPCRC((ushort)(ICMPDataLength + 8)); RawData[DataOffset + 2] = (byte)((icmpCRC >> 8) & 0xFF); RawData[DataOffset + 3] = (byte)((icmpCRC >> 0) & 0xFF); } + /// + /// Init ICMPPacket fields.1 + /// + /// Thrown if RawData is invalid or null. protected override void InitFields() { - //Sys.Console.WriteLine("ICMPEchoRequest.InitFields() called;"); base.InitFields(); icmpID = (ushort)((RawData[DataOffset + 4] << 8) | RawData[DataOffset + 5]); icmpSequence = (ushort)((RawData[DataOffset + 6] << 8) | RawData[DataOffset + 7]); } - internal ushort ICMP_ID - { - get { return icmpID; } - } - internal ushort ICMP_Sequence - { - get { return icmpSequence; } - } + /// + /// Get ICMP ID. + /// + internal ushort ICMPID => icmpID; + + /// + /// Get ICMP Sequence. + /// + internal ushort ICMPSequence => icmpSequence; /// /// To string. @@ -291,16 +294,16 @@ protected override void InitFields() /// ICMP echo request. /// Thrown if RawData is invalid or null. internal ICMPEchoReply(ICMPEchoRequest request) - : base(request.DestinationIP, request.SourceIP, 0, 0, request.ICMP_ID, request.ICMP_Sequence, (ushort)(request.ICMP_DataLength)) + : base(request.DestinationIP, request.SourceIP, 0, 0, request.ICMPID, request.ICMPSequence, (ushort)(request.ICMPDataLength)) { - for (int b = 0; b < ICMP_DataLength; b++) + for (int b = 0; b < ICMPDataLength; b++) { RawData[DataOffset + 8 + b] = request.RawData[DataOffset + 8 + b]; } RawData[DataOffset + 2] = 0x00; RawData[DataOffset + 3] = 0x00; - icmpCRC = CalcICMPCRC((ushort)(ICMP_DataLength + 8)); + icmpCRC = CalcICMPCRC((ushort)(ICMPDataLength + 8)); RawData[DataOffset + 2] = (byte)((icmpCRC >> 8) & 0xFF); RawData[DataOffset + 3] = (byte)((icmpCRC >> 0) & 0xFF); } @@ -308,17 +311,12 @@ internal ICMPEchoReply(ICMPEchoRequest request) /// /// Get ICMP ID. /// - internal ushort ICMP_ID - { - get { return icmpID; } - } + internal ushort ICMPID => icmpID; + /// /// Get ICMP sequence. /// - internal ushort ICMP_Sequence - { - get { return icmpSequence; } - } + internal ushort ICMPSequence => icmpSequence; /// /// To string. From eaa5470e2601ef4eb680c55d58eadf28bd7b815f Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 22 Jan 2021 10:55:32 +0100 Subject: [PATCH 050/314] Client creation tests --- Tests/Kernels/NetworkTest/Kernel.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Tests/Kernels/NetworkTest/Kernel.cs b/Tests/Kernels/NetworkTest/Kernel.cs index 55133de8bc..8bd01cf85e 100644 --- a/Tests/Kernels/NetworkTest/Kernel.cs +++ b/Tests/Kernels/NetworkTest/Kernel.cs @@ -22,6 +22,10 @@ protected override void BeforeRun() protected override void Run() { + /** + * Packet creation and parsing tests + **/ + /** Ethernet Packet Parsing Test **/ byte[] ethernetPacketData = new byte[] { @@ -91,6 +95,21 @@ protected override void Run() Equals(arpPacketData, arpPacket.RawData); TestController.Completed(); + + /** + * Clients tests + **/ + var dhcpCLient = new DHCPClient(); + dhcpCLient.Close(); + + var dnsClient = new DnsClient(); + dnsClient.Close(); + + var udpClient = new UdpClient(); + udpClient.Close(); + + var icmpClient = new ICMPClient(); + icmpClient.Close(); } } } From 210a5cc3e6cd391bdaa41c7d4d9d290ce7a06db9 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 22 Jan 2021 12:41:17 +0100 Subject: [PATCH 051/314] Update Network.md --- Docs/articles/Kernel/Network.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index 7202c29dff..18c9ba8f78 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -26,9 +26,6 @@ using(var xClient = new DHCPClient()) //This will automatically set the IP config after DHCP response xClient.SendDiscoverPacket(); - /** Send a DHCP Release packet **/ - xClient.SendReleasePacket(); //will tell the DHCP server to delete the address - xClient.Close(); //don't forget to close! } ``` From f98690cb747903a6294aab4b6cdb21a91539e194 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 22 Jan 2021 14:25:25 +0100 Subject: [PATCH 052/314] Make UDPClient global variables internal or private + code clean --- source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs | 8 ++++---- source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs | 4 ++-- source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs index bb53499814..94dd711eaa 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs @@ -21,7 +21,7 @@ public class DHCPClient : UdpClient // /// Is DHCP ascked check variable /// - protected bool asked = false; + private bool asked = false; /// /// Get the IP address of the DHCP server @@ -98,7 +98,7 @@ public void SendReleasePacket() foreach (NetworkDevice networkDevice in NetworkDevice.Devices) { Address source = IPConfig.FindNetwork(DHCPServerAddress(networkDevice)); - DHCPRelease dhcp_release = new DHCPRelease(source, DHCPServerAddress(networkDevice), networkDevice.MACAddress); + var dhcp_release = new DHCPRelease(source, DHCPServerAddress(networkDevice), networkDevice.MACAddress); OutgoingBuffer.AddPacket(dhcp_release); NetworkStack.Update(); @@ -121,7 +121,7 @@ public void SendDiscoverPacket() { IPConfig.Enable(networkDevice, new Address(0, 0, 0, 0), new Address(0, 0, 0, 0), new Address(0, 0, 0, 0)); - DHCPDiscover dhcp_discover = new DHCPDiscover(networkDevice.MACAddress); + var dhcp_discover = new DHCPDiscover(networkDevice.MACAddress); OutgoingBuffer.AddPacket(dhcp_discover); NetworkStack.Update(); @@ -138,7 +138,7 @@ private void SendRequestPacket(Address RequestedAddress, Address DHCPServerAddre { foreach (NetworkDevice networkDevice in NetworkDevice.Devices) { - DHCPRequest dhcp_request = new DHCPRequest(networkDevice.MACAddress, RequestedAddress, DHCPServerAddress); + var dhcp_request = new DHCPRequest(networkDevice.MACAddress, RequestedAddress, DHCPServerAddress); OutgoingBuffer.AddPacket(dhcp_request); NetworkStack.Update(); } diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs index dec08b9bc2..58dca96a84 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs @@ -50,7 +50,7 @@ public void SendAsk(string url) queryurl = url; - DNSPacketAsk askpacket = new DNSPacketAsk(source, destination, url); + var askpacket = new DNSPacketAsk(source, destination, url); OutgoingBuffer.AddPacket(askpacket); @@ -81,7 +81,7 @@ public Address Receive(int timeout = 5000) } } - DNSPacketAnswer packet = new DNSPacketAnswer(rxBuffer.Dequeue().RawData); + var packet = new DNSPacketAnswer(rxBuffer.Dequeue().RawData); if ((ushort)(packet.DNSFlags & 0x0F) == (ushort)ReplyCode.OK) { diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs index 46c24ab240..8aa440df10 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs @@ -25,20 +25,20 @@ public class UdpClient : IDisposable /// /// Local port. /// - protected int localPort; + private int localPort; /// /// Destination address. /// - protected Address destination; + internal Address destination; /// /// Destination port. /// - protected int destinationPort; + private int destinationPort; /// /// RX buffer queue. /// - protected Queue rxBuffer; + internal Queue rxBuffer; /// /// Assign clients dictionary. From 0ee21466cd9d2afb2eba47282fec470e0f999d94 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 22 Jan 2021 14:31:15 +0100 Subject: [PATCH 053/314] Return time value for Discover packet --- .../Network/IPV4/UDP/DHCP/DHCPClient.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs index 94dd711eaa..b712a28e9f 100644 --- a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs +++ b/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs @@ -71,7 +71,7 @@ private int Receive(int timeout = 5000) { if (packet.RawData[284] == 0x02) //Offer packet received { - SendRequestPacket(packet.Client, packet.Server); + return SendRequestPacket(packet.Client, packet.Server); } else if (packet.RawData[284] == 0x05 || packet.RawData[284] == 0x06) //ACK or NAK DHCP packet received { @@ -113,7 +113,8 @@ public void SendReleasePacket() /// /// Send a packet to find the DHCP server and tell that we want a new IP address /// - public void SendDiscoverPacket() + /// time value (-1 = timeout) + public int SendDiscoverPacket() { NetworkStack.RemoveAllConfigIP(); @@ -128,13 +129,14 @@ public void SendDiscoverPacket() asked = true; } - Receive(); + return Receive(); } /// /// Send a request to apply the new IP configuration /// - private void SendRequestPacket(Address RequestedAddress, Address DHCPServerAddress) + /// time value (-1 = timeout) + private int SendRequestPacket(Address RequestedAddress, Address DHCPServerAddress) { foreach (NetworkDevice networkDevice in NetworkDevice.Devices) { @@ -142,7 +144,7 @@ private void SendRequestPacket(Address RequestedAddress, Address DHCPServerAddre OutgoingBuffer.AddPacket(dhcp_request); NetworkStack.Update(); } - Receive(); + return Receive(); } /* From a9a3f6401bddf043c970b42c1cbb487ae10efb31 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 22 Jan 2021 14:49:53 +0100 Subject: [PATCH 054/314] Update Network.md --- Docs/articles/Kernel/Network.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index 18c9ba8f78..cb7abf44b4 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -1,8 +1,8 @@ # Network -In this article we will discuss about Networking on Cosmos, how to use the Network Stack, send and received packets. For now, available protocols are **ARP**, **IPv4**, **UDP**, **ICMP**, **DHCP** and **DNS** but the team is also working on TCP. +In this article we will discuss about Networking on Cosmos, how to use the Network Stack, send and received packets. For now, available protocols are **ARP**, **IPv4**, **UDP**, **ICMP**, **DHCP** and **DNS** but the team is also working on TCP. Note that Cosmos devkit must be installed for this article. -All protocols here don't necessary support every feature described by their RFC and may have some bugs or architecture issues, if you find something abnormal please [submit an issue](http://https://github.com/CosmosOS/Cosmos/issues/new/choose "repository") on our repository. +All protocols here don't necessary support every feature described by their RFC and may have some bugs or architecture issues, if you find bugs or something abnormal please [submit an issue](http://https://github.com/CosmosOS/Cosmos/issues/new/choose "repository") on our repository. 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(). @@ -82,3 +82,8 @@ using(var xClient = new DnsClient()) xClient.Close(); } ``` +## Utils +## Get local IP +```csharp +Console.WriteLine(NetworkConfig.CurrentConfig.Value.IPAddress.ToString()); +``` From bfa982104c88c3d453198dbc5c637918c328e576 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 5 Feb 2021 13:34:56 +0100 Subject: [PATCH 055/314] Raname IPv4 folder Temp --- source/Cosmos.System2/Network/{IPv4 => Temp}/Address.cs | 0 source/Cosmos.System2/Network/{IPv4 => Temp}/EndPoint.cs | 0 source/Cosmos.System2/Network/{IPV4 => Temp}/ICMPClient.cs | 0 source/Cosmos.System2/Network/{IPv4 => Temp}/ICMPPacket.cs | 0 source/Cosmos.System2/Network/{IPv4 => Temp}/IPPacket.cs | 0 source/Cosmos.System2/Network/{IPv4 => Temp}/OutgoingBuffer.cs | 0 source/Cosmos.System2/Network/{IPV4 => Temp}/UDP/DHCP/DHCPAck.cs | 0 .../Cosmos.System2/Network/{IPV4 => Temp}/UDP/DHCP/DHCPClient.cs | 0 .../Network/{IPV4 => Temp}/UDP/DHCP/DHCPDiscover.cs | 0 .../Cosmos.System2/Network/{IPV4 => Temp}/UDP/DHCP/DHCPPacket.cs | 0 .../Cosmos.System2/Network/{IPV4 => Temp}/UDP/DHCP/DHCPRelease.cs | 0 .../Cosmos.System2/Network/{IPV4 => Temp}/UDP/DHCP/DHCPRequest.cs | 0 source/Cosmos.System2/Network/{IPV4 => Temp}/UDP/DNS/DNSClient.cs | 0 source/Cosmos.System2/Network/{IPV4 => Temp}/UDP/DNS/DNSPacket.cs | 0 source/Cosmos.System2/Network/{IPv4 => Temp}/UDP/UDPPacket.cs | 0 source/Cosmos.System2/Network/{IPv4 => Temp}/UDP/UdpClient.cs | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename source/Cosmos.System2/Network/{IPv4 => Temp}/Address.cs (100%) rename source/Cosmos.System2/Network/{IPv4 => Temp}/EndPoint.cs (100%) rename source/Cosmos.System2/Network/{IPV4 => Temp}/ICMPClient.cs (100%) rename source/Cosmos.System2/Network/{IPv4 => Temp}/ICMPPacket.cs (100%) rename source/Cosmos.System2/Network/{IPv4 => Temp}/IPPacket.cs (100%) rename source/Cosmos.System2/Network/{IPv4 => Temp}/OutgoingBuffer.cs (100%) rename source/Cosmos.System2/Network/{IPV4 => Temp}/UDP/DHCP/DHCPAck.cs (100%) rename source/Cosmos.System2/Network/{IPV4 => Temp}/UDP/DHCP/DHCPClient.cs (100%) rename source/Cosmos.System2/Network/{IPV4 => Temp}/UDP/DHCP/DHCPDiscover.cs (100%) rename source/Cosmos.System2/Network/{IPV4 => Temp}/UDP/DHCP/DHCPPacket.cs (100%) rename source/Cosmos.System2/Network/{IPV4 => Temp}/UDP/DHCP/DHCPRelease.cs (100%) rename source/Cosmos.System2/Network/{IPV4 => Temp}/UDP/DHCP/DHCPRequest.cs (100%) rename source/Cosmos.System2/Network/{IPV4 => Temp}/UDP/DNS/DNSClient.cs (100%) rename source/Cosmos.System2/Network/{IPV4 => Temp}/UDP/DNS/DNSPacket.cs (100%) rename source/Cosmos.System2/Network/{IPv4 => Temp}/UDP/UDPPacket.cs (100%) rename source/Cosmos.System2/Network/{IPv4 => Temp}/UDP/UdpClient.cs (100%) diff --git a/source/Cosmos.System2/Network/IPv4/Address.cs b/source/Cosmos.System2/Network/Temp/Address.cs similarity index 100% rename from source/Cosmos.System2/Network/IPv4/Address.cs rename to source/Cosmos.System2/Network/Temp/Address.cs diff --git a/source/Cosmos.System2/Network/IPv4/EndPoint.cs b/source/Cosmos.System2/Network/Temp/EndPoint.cs similarity index 100% rename from source/Cosmos.System2/Network/IPv4/EndPoint.cs rename to source/Cosmos.System2/Network/Temp/EndPoint.cs diff --git a/source/Cosmos.System2/Network/IPV4/ICMPClient.cs b/source/Cosmos.System2/Network/Temp/ICMPClient.cs similarity index 100% rename from source/Cosmos.System2/Network/IPV4/ICMPClient.cs rename to source/Cosmos.System2/Network/Temp/ICMPClient.cs diff --git a/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs b/source/Cosmos.System2/Network/Temp/ICMPPacket.cs similarity index 100% rename from source/Cosmos.System2/Network/IPv4/ICMPPacket.cs rename to source/Cosmos.System2/Network/Temp/ICMPPacket.cs diff --git a/source/Cosmos.System2/Network/IPv4/IPPacket.cs b/source/Cosmos.System2/Network/Temp/IPPacket.cs similarity index 100% rename from source/Cosmos.System2/Network/IPv4/IPPacket.cs rename to source/Cosmos.System2/Network/Temp/IPPacket.cs diff --git a/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs b/source/Cosmos.System2/Network/Temp/OutgoingBuffer.cs similarity index 100% rename from source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs rename to source/Cosmos.System2/Network/Temp/OutgoingBuffer.cs diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs b/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPAck.cs similarity index 100% rename from source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPAck.cs rename to source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPAck.cs diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs b/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPClient.cs similarity index 100% rename from source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPClient.cs rename to source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPClient.cs diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs b/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPDiscover.cs similarity index 100% rename from source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPDiscover.cs rename to source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPDiscover.cs diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs b/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPPacket.cs similarity index 100% rename from source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPPacket.cs rename to source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPPacket.cs diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs b/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPRelease.cs similarity index 100% rename from source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRelease.cs rename to source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPRelease.cs diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs b/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPRequest.cs similarity index 100% rename from source/Cosmos.System2/Network/IPV4/UDP/DHCP/DHCPRequest.cs rename to source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPRequest.cs diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs b/source/Cosmos.System2/Network/Temp/UDP/DNS/DNSClient.cs similarity index 100% rename from source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSClient.cs rename to source/Cosmos.System2/Network/Temp/UDP/DNS/DNSClient.cs diff --git a/source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/Temp/UDP/DNS/DNSPacket.cs similarity index 100% rename from source/Cosmos.System2/Network/IPV4/UDP/DNS/DNSPacket.cs rename to source/Cosmos.System2/Network/Temp/UDP/DNS/DNSPacket.cs diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs b/source/Cosmos.System2/Network/Temp/UDP/UDPPacket.cs similarity index 100% rename from source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs rename to source/Cosmos.System2/Network/Temp/UDP/UDPPacket.cs diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/Temp/UDP/UdpClient.cs similarity index 100% rename from source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs rename to source/Cosmos.System2/Network/Temp/UDP/UdpClient.cs From dbe694c1c52aee488693416332dc836f607f5080 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 5 Feb 2021 13:35:29 +0100 Subject: [PATCH 056/314] Rename back --- source/Cosmos.System2/Network/{Temp => IPv4}/Address.cs | 0 source/Cosmos.System2/Network/{Temp => IPv4}/EndPoint.cs | 0 source/Cosmos.System2/Network/{Temp => IPv4}/ICMPClient.cs | 0 source/Cosmos.System2/Network/{Temp => IPv4}/ICMPPacket.cs | 0 source/Cosmos.System2/Network/{Temp => IPv4}/IPPacket.cs | 0 source/Cosmos.System2/Network/{Temp => IPv4}/OutgoingBuffer.cs | 0 source/Cosmos.System2/Network/{Temp => IPv4}/UDP/DHCP/DHCPAck.cs | 0 .../Cosmos.System2/Network/{Temp => IPv4}/UDP/DHCP/DHCPClient.cs | 0 .../Network/{Temp => IPv4}/UDP/DHCP/DHCPDiscover.cs | 0 .../Cosmos.System2/Network/{Temp => IPv4}/UDP/DHCP/DHCPPacket.cs | 0 .../Cosmos.System2/Network/{Temp => IPv4}/UDP/DHCP/DHCPRelease.cs | 0 .../Cosmos.System2/Network/{Temp => IPv4}/UDP/DHCP/DHCPRequest.cs | 0 source/Cosmos.System2/Network/{Temp => IPv4}/UDP/DNS/DNSClient.cs | 0 source/Cosmos.System2/Network/{Temp => IPv4}/UDP/DNS/DNSPacket.cs | 0 source/Cosmos.System2/Network/{Temp => IPv4}/UDP/UDPPacket.cs | 0 source/Cosmos.System2/Network/{Temp => IPv4}/UDP/UdpClient.cs | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename source/Cosmos.System2/Network/{Temp => IPv4}/Address.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/EndPoint.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/ICMPClient.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/ICMPPacket.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/IPPacket.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/OutgoingBuffer.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/UDP/DHCP/DHCPAck.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/UDP/DHCP/DHCPClient.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/UDP/DHCP/DHCPDiscover.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/UDP/DHCP/DHCPPacket.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/UDP/DHCP/DHCPRelease.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/UDP/DHCP/DHCPRequest.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/UDP/DNS/DNSClient.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/UDP/DNS/DNSPacket.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/UDP/UDPPacket.cs (100%) rename source/Cosmos.System2/Network/{Temp => IPv4}/UDP/UdpClient.cs (100%) diff --git a/source/Cosmos.System2/Network/Temp/Address.cs b/source/Cosmos.System2/Network/IPv4/Address.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/Address.cs rename to source/Cosmos.System2/Network/IPv4/Address.cs diff --git a/source/Cosmos.System2/Network/Temp/EndPoint.cs b/source/Cosmos.System2/Network/IPv4/EndPoint.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/EndPoint.cs rename to source/Cosmos.System2/Network/IPv4/EndPoint.cs diff --git a/source/Cosmos.System2/Network/Temp/ICMPClient.cs b/source/Cosmos.System2/Network/IPv4/ICMPClient.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/ICMPClient.cs rename to source/Cosmos.System2/Network/IPv4/ICMPClient.cs diff --git a/source/Cosmos.System2/Network/Temp/ICMPPacket.cs b/source/Cosmos.System2/Network/IPv4/ICMPPacket.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/ICMPPacket.cs rename to source/Cosmos.System2/Network/IPv4/ICMPPacket.cs diff --git a/source/Cosmos.System2/Network/Temp/IPPacket.cs b/source/Cosmos.System2/Network/IPv4/IPPacket.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/IPPacket.cs rename to source/Cosmos.System2/Network/IPv4/IPPacket.cs diff --git a/source/Cosmos.System2/Network/Temp/OutgoingBuffer.cs b/source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/OutgoingBuffer.cs rename to source/Cosmos.System2/Network/IPv4/OutgoingBuffer.cs diff --git a/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPAck.cs b/source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPAck.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPAck.cs rename to source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPAck.cs diff --git a/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPClient.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPClient.cs rename to source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPClient.cs diff --git a/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPDiscover.cs b/source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPDiscover.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPDiscover.cs rename to source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPDiscover.cs diff --git a/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPPacket.cs b/source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPPacket.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPPacket.cs rename to source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPPacket.cs diff --git a/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPRelease.cs b/source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPRelease.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPRelease.cs rename to source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPRelease.cs diff --git a/source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPRequest.cs b/source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPRequest.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/UDP/DHCP/DHCPRequest.cs rename to source/Cosmos.System2/Network/IPv4/UDP/DHCP/DHCPRequest.cs diff --git a/source/Cosmos.System2/Network/Temp/UDP/DNS/DNSClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/DNS/DNSClient.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/UDP/DNS/DNSClient.cs rename to source/Cosmos.System2/Network/IPv4/UDP/DNS/DNSClient.cs diff --git a/source/Cosmos.System2/Network/Temp/UDP/DNS/DNSPacket.cs b/source/Cosmos.System2/Network/IPv4/UDP/DNS/DNSPacket.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/UDP/DNS/DNSPacket.cs rename to source/Cosmos.System2/Network/IPv4/UDP/DNS/DNSPacket.cs diff --git a/source/Cosmos.System2/Network/Temp/UDP/UDPPacket.cs b/source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/UDP/UDPPacket.cs rename to source/Cosmos.System2/Network/IPv4/UDP/UDPPacket.cs diff --git a/source/Cosmos.System2/Network/Temp/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs similarity index 100% rename from source/Cosmos.System2/Network/Temp/UDP/UdpClient.cs rename to source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs From 3e732dbaa3a6dc2984625d643817b776efbe73d4 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 5 Feb 2021 13:46:28 +0100 Subject: [PATCH 057/314] Add TCP Client + basic TCP packet --- .../Network/IPv4/TCP/TCPClient.cs | 203 +++++++++++++++ .../Network/IPv4/TCP/TCPPacket.cs | 241 ++++++++++++++++++ 2 files changed, 444 insertions(+) create mode 100644 source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs create mode 100644 source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs new file mode 100644 index 0000000000..fb9b3b191b --- /dev/null +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -0,0 +1,203 @@ +/* +* PROJECT: Aura Operating System Development +* CONTENT: TCP Client +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Cosmos.System.Network.IPv4.TCP +{ + /// + /// TCPClient class. Used to manage the TCP connection to a client. + /// + public class TcpClient : IDisposable + { + /// + /// Clients dictionary. + /// + private static Dictionary clients; + + /// + /// Local port. + /// + private int localPort; + /// + /// Destination address. + /// + internal Address destination; + /// + /// Destination port. + /// + private int destinationPort; + + /// + /// RX buffer queue. + /// + internal Queue rxBuffer; + + /// + /// Assign clients dictionary. + /// + /// Thrown on fatal error (contact support). + static TcpClient() + { + clients = new Dictionary(); + } + + /// + /// Get client. + /// + /// Destination port. + /// TcpClient + internal static TcpClient GetClient(ushort destPort) + { + if (clients.ContainsKey((uint)destPort) == true) + { + return clients[(uint)destPort]; + } + + return null; + } + + /// + /// Create new instance of the class. + /// + /// Thrown on fatal error (contact support). + /// Thrown if TcpClient with localPort 0 exists. + public TcpClient() + : this(0) + { } + + /// + /// Create new instance of the class. + /// + /// Local port. + /// Thrown on fatal error (contact support). + /// Thrown if localPort already exists. + public TcpClient(int localPort) + { + rxBuffer = new Queue(8); + + this.localPort = localPort; + if (localPort > 0) + { + clients.Add((uint)localPort, this); + } + } + + /// + /// Create new instance of the class. + /// + /// Destination address. + /// Destination port. + /// Thrown on fatal error (contact support). + /// Thrown if TcpClient with localPort 0 exists. + public TcpClient(Address dest, int destPort) + : this(0) + { + destination = dest; + destinationPort = destPort; + } + + /// + /// Connect to client. + /// + /// Destination address. + /// Destination port. + public void Connect(Address dest, int destPort) + { + destination = dest; + destinationPort = destPort; + } + + /// + /// Close connection. + /// + /// Thrown on fatal error (contact support). + public void Close() + { + if (clients.ContainsKey((uint)localPort) == true) + { + clients.Remove((uint)localPort); + } + } + + /// + /// Send data to client. + /// + /// Data array to send. + /// Thrown if destination is null or destinationPort is 0. + /// Thrown on fatal error (contact support). + /// Thrown if data array length is greater than Int32.MaxValue. + /// Thrown on IO error. + public void Send(byte[] data) + { + if ((destination == null) || (destinationPort == 0)) + { + throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); + } + + Send(data, destination, destinationPort); + NetworkStack.Update(); + } + + /// + /// Send data. + /// + /// Data array. + /// Destination address. + /// Destination port. + /// Thrown on fatal error (contact support). + /// Thrown if data array length is greater than Int32.MaxValue. + /// Thrown on IO error. + public void Send(byte[] data, Address dest, int destPort) + { + throw new NotImplementedException(); + } + + /// + /// Receive data from end point. + /// + /// Source end point. + /// byte array value. + /// Thrown on fatal error (contact support). + public byte[] NonBlockingReceive(ref EndPoint source) + { + throw new NotImplementedException(); + } + + /// + /// Receive data from end point. + /// + /// Source end point. + /// byte array value. + /// Thrown on fatal error (contact support). + public byte[] Receive(ref EndPoint source) + { + throw new NotImplementedException(); + } + + /// + /// Receive data from packet. + /// + /// Packet to receive. + /// Thrown on fatal error (contact support). + /// Thrown on IO error. + internal void ReceiveData(TCPPacket packet) + { + rxBuffer.Enqueue(packet); + } + + /// + /// Close Client + /// + public void Dispose() + { + Close(); + } + } +} diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs new file mode 100644 index 0000000000..0c02243406 --- /dev/null +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -0,0 +1,241 @@ +/* +* PROJECT: Aura Operating System Development +* CONTENT: TCP Packet +* PROGRAMMERS: Valentin Charbonnier +* Port of Cosmos Code. +*/ + +using Cosmos.HAL; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Cosmos.System.Network.IPv4.TCP +{ + + /// + /// DHCP Option + /// + public class TCPOption + { + public byte Kind { get; set; } + public byte Length { get; set; } + public byte[] Data { get; set; } + } + + public class TCPPacket : IPPacket + { + protected ushort sourcePort; + protected ushort destinationPort; + protected ushort tcpLen; + protected ulong sequenceNumber; + protected ulong ackNumber; + protected int headerLenght; + protected int flags; + protected int wsValue; + protected int checksum; + protected int urgentPointer; + + protected List options = null; + + public bool SYN; + public bool ACK; + public bool FIN; + public bool PSH; + public bool RST; + + protected ushort optionLen; + + internal static void TCPHandler(byte[] packetData) + { + var packet = new TCPPacket(packetData); + + Global.mDebugger.Send("[Received] TCP packet from " + packet.SourceIP.ToString() + ":" + packet.SourcePort.ToString()); + + var receiver = TcpClient.GetClient(packet.DestinationPort); + if (receiver != null) + { + receiver.ReceiveData(packet); + } + } + + /// + /// Work around to make VMT scanner include the initFields method + /// + public static void VMTInclude() + { + new TCPPacket(); + } + + internal TCPPacket() + : base() + { } + + internal TCPPacket(byte[] rawData) + : base(rawData) + { } + + public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, + ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, ushort Flags, + ushort WSValue, ushort UrgentPointer, ushort len) + : base((ushort)(20 + len), 6, source, dest, 0x40) + { + optionLen = len; + + //ports + RawData[DataOffset + 0] = (byte)((sourcePort >> 8) & 0xFF); + RawData[DataOffset + 1] = (byte)((srcPort >> 0) & 0xFF); + + RawData[DataOffset + 2] = (byte)((destPort >> 8) & 0xFF); + RawData[DataOffset + 3] = (byte)((destPort >> 0) & 0xFF); + + //sequencenumber + RawData[DataOffset + 4] = (byte)((sequencenumber >> 24) & 0xFF); + RawData[DataOffset + 5] = (byte)((sequencenumber >> 16) & 0xFF); + RawData[DataOffset + 6] = (byte)((sequencenumber >> 8) & 0xFF); + RawData[DataOffset + 7] = (byte)((sequencenumber >> 0) & 0xFF); + + //Acknowledgment number + RawData[DataOffset + 8] = (byte)((acknowledgmentnb >> 24) & 0xFF); + RawData[DataOffset + 9] = (byte)((acknowledgmentnb >> 16) & 0xFF); + RawData[DataOffset + 10] = (byte)((acknowledgmentnb >> 8) & 0xFF); + RawData[DataOffset + 11] = (byte)((acknowledgmentnb >> 0) & 0xFF); + + //Header lenght + RawData[DataOffset + 12] = (byte)((Headerlenght >> 0) & 0xFF); + + //Flags + RawData[DataOffset + 13] = (byte)((Flags >> 0) & 0xFF); + + //Window size value + RawData[DataOffset + 14] = (byte)((WSValue >> 8) & 0xFF); + RawData[DataOffset + 15] = (byte)((WSValue >> 0) & 0xFF); + + //Checksum + RawData[DataOffset + 16] = 0x00; + RawData[DataOffset + 17] = 0x00; + + //Urgent Pointer + RawData[DataOffset + 18] = (byte)((UrgentPointer >> 8) & 0xFF); + RawData[DataOffset + 19] = (byte)((UrgentPointer >> 0) & 0xFF); + + InitFields(); + } + + protected override void InitFields() + { + base.InitFields(); + sourcePort = (ushort)((RawData[DataOffset] << 8) | RawData[DataOffset + 1]); + destinationPort = (ushort)((RawData[DataOffset + 2] << 8) | RawData[DataOffset + 3]); + sequenceNumber = (uint)((RawData[DataOffset + 4] << 24) | (RawData[DataOffset + 5] << 16) | (RawData[DataOffset + 6] << 8) | RawData[DataOffset + 7]); + ackNumber = (uint)((RawData[DataOffset + 8] << 24) | (RawData[DataOffset + 9] << 16) | (RawData[DataOffset + 10] << 8) | RawData[DataOffset + 11]); + headerLenght = RawData[DataOffset + 12]; + flags = RawData[DataOffset + 13]; + wsValue = (ushort)((RawData[DataOffset + 14] << 8) | RawData[DataOffset + 15]); + checksum = (ushort)((RawData[DataOffset + 16] << 8) | RawData[DataOffset + 17]); + urgentPointer = (ushort)((RawData[DataOffset + 18] << 8) | RawData[DataOffset + 19]); + + SYN = (RawData[47] & (1 << 1)) != 0; + ACK = (RawData[47] & (1 << 4)) != 0; + FIN = (RawData[47] & (1 << 0)) != 0; + PSH = (RawData[47] & (1 << 3)) != 0; + RST = (RawData[47] & (1 << 2)) != 0; + + //options + if (RawData[DataOffset + 20] != 0) + { + options = new List(); + + for (int i = 0; i < RawData.Length - (DataOffset + 20); i++) + { + var option = new TCPOption(); + option.Kind = RawData[DataOffset + 20 + i]; + + if (option.Kind != 1) //NOP + { + option.Length = RawData[DataOffset + 20 + i + 1]; + + if (option.Length != 2) + { + option.Data = new byte[option.Length - 2]; + for (int j = 0; j < option.Length - 2; j++) + { + option.Data[j] = RawData[DataOffset + 20 + i + 2 + j]; + } + } + + options.Add(option); + + i += option.Length - 1; + } + } + } + } + + internal ushort DestinationPort + { + get { return destinationPort; } + } + internal ushort SourcePort + { + get { return sourcePort; } + } + internal ulong SequenceNumber + { + get { return sequenceNumber; } + } + + public override string ToString() + { + return "TCP Packet Src=" + SourceIP + ":" + sourcePort + ", Dest=" + DestinationIP + ":" + destinationPort; + } + } + + public class TCPacketSyn : TCPPacket + { + /// + /// Work around to make VMT scanner include the initFields method + /// + public static void VMTInclude() + { + new TCPacketSyn(); + } + + internal TCPacketSyn() + : base() + { } + + public TCPacketSyn(Address Source, Address Destination, ushort SourcePort, + ushort DestinationPort, ulong SequenceNumber, ulong ACKNumber, + ushort Flags, ushort WSValue, List options, ushort optionslen) + : base(Source, Destination, SourcePort, DestinationPort, SequenceNumber, + ACKNumber, 0x50, Flags, WSValue, 0x0000, optionslen) + { + int counter = 0; + foreach (var option in options) + { + RawData[DataOffset + 20 + counter] = option.Kind; + + if (option.Kind != 1) //NOP + { + RawData[DataOffset + 20 + counter + 1] = option.Length; + + if (option.Length != 2) + { + for (int j = 0; j < option.Length - 2; j++) + { + RawData[DataOffset + 20 + counter + 2 + j] = option.Data[j]; + } + } + } + + counter += option.Length; + } + } + + protected override void InitFields() + { + base.InitFields(); + } + } +} From cb2f803600258a5d94c762064284ce6682463a0c Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 5 Feb 2021 13:55:09 +0100 Subject: [PATCH 058/314] Add TCP to IP handler --- source/Cosmos.System2/Network/IPv4/IPPacket.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/Cosmos.System2/Network/IPv4/IPPacket.cs b/source/Cosmos.System2/Network/IPv4/IPPacket.cs index c568950017..03a624905c 100644 --- a/source/Cosmos.System2/Network/IPv4/IPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/IPPacket.cs @@ -9,6 +9,7 @@ using Cosmos.HAL; using Cosmos.HAL.Network; using Cosmos.System.Network.ARP; +using Cosmos.System.Network.IPv4.TCP; using Cosmos.System.Network.IPv4.UDP; using Cosmos.System.Network.IPv4.UDP.DHCP; @@ -51,7 +52,7 @@ internal static void IPv4Handler(byte[] packetData) ICMPPacket.ICMPHandler(packetData); break; case 6: - //TCPPacket.TCPHandler(packetData); + TCPPacket.TCPHandler(packetData); break; case 17: UDPPacket.UDPHandler(packetData); From 92cbe7f9ce96fa22146341fd81cfd326ba7eb825 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 18 Feb 2021 18:45:54 +0100 Subject: [PATCH 059/314] TCP Work --- .../Network/IPv4/TCP/TCPClient.cs | 27 ++++++++++++++++++- .../Network/IPv4/TCP/TCPPacket.cs | 17 ++++++++++++ .../Network/IPv4/UDP/UdpClient.cs | 2 +- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index fb9b3b191b..021b12335d 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Text; +using Cosmos.System.Network.Config; namespace Cosmos.System.Network.IPv4.TCP { @@ -112,6 +113,22 @@ public void Connect(Address dest, int destPort) { destination = dest; destinationPort = destPort; + + Address source = IPConfig.FindNetwork(dest); + + //TODO: Generate sequence number + //TODO: Dynamic header len + // Flags=0x02 -> Syn + var packet = new TCPPacket(source, dest, (ushort)localPort, (ushort)destPort, 3455719727, 0, 20 + 12, 0x02, 0xFAF0, 0, 12); + + byte[] options = new byte[] + { + 0x02, 0x04, 0x05, 0xB4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, 0x04, 0x02 + }; + + packet.AddOption(options); + + OutgoingBuffer.AddPacket(packet); } /// @@ -156,7 +173,9 @@ public void Send(byte[] data) /// Thrown on IO error. public void Send(byte[] data, Address dest, int destPort) { - throw new NotImplementedException(); + Address source = IPConfig.FindNetwork(dest); + var packet = new TCPPacket(); + OutgoingBuffer.AddPacket(packet); } /// @@ -189,6 +208,12 @@ public byte[] Receive(ref EndPoint source) /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { + Global.mDebugger.Send("Flags=" + packet.Flags); + + if (packet.Flags == 0x12) // SYN/ACK + { + + } rxBuffer.Enqueue(packet); } diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 0c02243406..dffcf4cb72 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -172,6 +172,23 @@ protected override void InitFields() } } + internal void AddOption(TCPOption option) + { + throw new NotImplementedException(); + } + + internal void AddOption(byte[] raw) + { + if (raw.Length > optionLen) + { + throw new Exception("Raw option is larger than max value."); + } + for (int i = 0; i < raw.Length; i++) + { + RawData[DataOffset + 20 + i] = raw[i]; + } + } + internal ushort DestinationPort { get { return destinationPort; } diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs index 8aa440df10..1d350d4c42 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs @@ -158,7 +158,7 @@ public void Send(byte[] data) public void Send(byte[] data, Address dest, int destPort) { Address source = IPConfig.FindNetwork(dest); - UDPPacket packet = new UDPPacket(source, dest, (ushort)localPort, (ushort)destPort, data); + var packet = new UDPPacket(source, dest, (ushort)localPort, (ushort)destPort, data); OutgoingBuffer.AddPacket(packet); } From ea9a5492dbcbc3124375beae82684079e535b897 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 18 Feb 2021 18:49:21 +0100 Subject: [PATCH 060/314] Do not hardcore values --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 021b12335d..b8c65fae29 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -116,16 +116,15 @@ public void Connect(Address dest, int destPort) Address source = IPConfig.FindNetwork(dest); - //TODO: Generate sequence number - //TODO: Dynamic header len - // Flags=0x02 -> Syn - var packet = new TCPPacket(source, dest, (ushort)localPort, (ushort)destPort, 3455719727, 0, 20 + 12, 0x02, 0xFAF0, 0, 12); - byte[] options = new byte[] { 0x02, 0x04, 0x05, 0xB4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, 0x04, 0x02 }; + //TODO: Generate sequence number + // Flags=0x02 -> Syn + var packet = new TCPPacket(source, dest, (ushort)localPort, (ushort)destPort, 3455719727, 0, (ushort)(20 + options.Length), 0x02, 0xFAF0, 0, (ushort)options.Length); + packet.AddOption(options); OutgoingBuffer.AddPacket(packet); From 004f910db08b3f103e0d40d5c06a85d24c533d59 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 18 Feb 2021 19:01:08 +0100 Subject: [PATCH 061/314] Forgot to update network stack --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index b8c65fae29..d28f8a3a7a 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -128,6 +128,7 @@ public void Connect(Address dest, int destPort) packet.AddOption(options); OutgoingBuffer.AddPacket(packet); + NetworkStack.Update(); } /// From f15761dcd623cd9f0061b049f71190c3634345d8 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 18 Feb 2021 19:05:08 +0100 Subject: [PATCH 062/314] Add tcpClient test --- Tests/Kernels/NetworkTest/Kernel.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tests/Kernels/NetworkTest/Kernel.cs b/Tests/Kernels/NetworkTest/Kernel.cs index 8bd01cf85e..21f137582b 100644 --- a/Tests/Kernels/NetworkTest/Kernel.cs +++ b/Tests/Kernels/NetworkTest/Kernel.cs @@ -107,6 +107,9 @@ protected override void Run() var udpClient = new UdpClient(); udpClient.Close(); + + var tcpClient = new TcpClient(); + tcpClient.Close(); var icmpClient = new ICMPClient(); icmpClient.Close(); From f4b6d796ae5ff4fe6ed5648f6db185a05f33c6ac Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 18 Feb 2021 21:26:53 +0100 Subject: [PATCH 063/314] Add checksum calculation --- .../Network/IPv4/TCP/TCPClient.cs | 41 +++++++-- .../Network/IPv4/TCP/TCPPacket.cs | 84 +++++++++++++++++-- 2 files changed, 110 insertions(+), 15 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index d28f8a3a7a..73bbff19be 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Text; +using Cosmos.HAL; using Cosmos.System.Network.Config; namespace Cosmos.System.Network.IPv4.TCP @@ -109,7 +110,7 @@ public TcpClient(Address dest, int destPort) /// /// Destination address. /// Destination port. - public void Connect(Address dest, int destPort) + public void Connect(Address dest, int destPort, int timeout = 5000) { destination = dest; destinationPort = destPort; @@ -129,6 +130,38 @@ public void Connect(Address dest, int destPort) OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); + + WaitForConnectionResponse(timeout); + } + + private void WaitForConnectionResponse(int timeout) + { + int second = 0; + int _deltaT = 0; + + while (rxBuffer.Count < 1) + { + if (second > (timeout / 1000)) + { + return; + } + if (_deltaT != RTC.Second) + { + second++; + _deltaT = RTC.Second; + } + } + + var packet = new TCPPacket(rxBuffer.Dequeue().RawData); + + Global.mDebugger.Send("Flags=" + packet.Flags); + + if (packet.Flags == 0x12) // SYN/ACK + { + + } + + //send ACK } /// @@ -208,12 +241,6 @@ public byte[] Receive(ref EndPoint source) /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { - Global.mDebugger.Send("Flags=" + packet.Flags); - - if (packet.Flags == 0x12) // SYN/ACK - { - - } rxBuffer.Enqueue(packet); } diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index dffcf4cb72..5aa82295e6 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -27,7 +27,7 @@ public class TCPPacket : IPPacket { protected ushort sourcePort; protected ushort destinationPort; - protected ushort tcpLen; + protected ushort optionLen; protected ulong sequenceNumber; protected ulong ackNumber; protected int headerLenght; @@ -44,7 +44,7 @@ public class TCPPacket : IPPacket public bool PSH; public bool RST; - protected ushort optionLen; + internal static void TCPHandler(byte[] packetData) { @@ -83,7 +83,7 @@ public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, optionLen = len; //ports - RawData[DataOffset + 0] = (byte)((sourcePort >> 8) & 0xFF); + RawData[DataOffset + 0] = (byte)((srcPort >> 8) & 0xFF); RawData[DataOffset + 1] = (byte)((srcPort >> 0) & 0xFF); RawData[DataOffset + 2] = (byte)((destPort >> 8) & 0xFF); @@ -102,7 +102,7 @@ public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, RawData[DataOffset + 11] = (byte)((acknowledgmentnb >> 0) & 0xFF); //Header lenght - RawData[DataOffset + 12] = (byte)((Headerlenght >> 0) & 0xFF); + RawData[DataOffset + 12] = (byte)(((Headerlenght >> 0) & 0xFF) * 4); //Flags RawData[DataOffset + 13] = (byte)((Flags >> 0) & 0xFF); @@ -111,14 +111,19 @@ public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, RawData[DataOffset + 14] = (byte)((WSValue >> 8) & 0xFF); RawData[DataOffset + 15] = (byte)((WSValue >> 0) & 0xFF); - //Checksum - RawData[DataOffset + 16] = 0x00; - RawData[DataOffset + 17] = 0x00; - //Urgent Pointer RawData[DataOffset + 18] = (byte)((UrgentPointer >> 8) & 0xFF); RawData[DataOffset + 19] = (byte)((UrgentPointer >> 0) & 0xFF); + byte[] header = MakeHeader(source.address, dest.address, (ushort)(20 + len), srcPort, destPort, + sequencenumber, acknowledgmentnb, Headerlenght, Flags, WSValue, UrgentPointer); + + ushort calculatedcrc = CalcOcCRC(header, 0, header.Length); + + //Checksum + RawData[DataOffset + 16] = (byte)((calculatedcrc >> 8) & 0xFF); + RawData[DataOffset + 17] = (byte)((calculatedcrc >> 0) & 0xFF); + InitFields(); } @@ -189,6 +194,69 @@ internal void AddOption(byte[] raw) } } + internal byte[] MakeHeader(byte[] sourceIP, byte[] destIP, ushort tcpLen, + ushort sourcePort, ushort destPort, ulong sequencenumber, ulong acknowledgmentnb, + int Headerlenght, int Flags, int WSValue, int UrgentPointer) + { + byte[] header = new byte[30 + RawData.Length - (DataOffset + 20)]; + + header[0] = sourceIP[0]; + header[1] = sourceIP[1]; + header[2] = sourceIP[2]; + header[3] = sourceIP[3]; + + header[4] = destIP[0]; + header[5] = destIP[1]; + header[6] = destIP[2]; + header[7] = destIP[3]; + + header[8] = 0x00; + + header[9] = 0x06; + + header[10] = (byte)((tcpLen >> 8) & 0xFF); + header[11] = (byte)((tcpLen >> 0) & 0xFF); + + header[12] = (byte)((sourcePort >> 8) & 0xFF); + header[13] = (byte)((sourcePort >> 0) & 0xFF); + + header[14] = (byte)((destPort >> 8) & 0xFF); + header[15] = (byte)((destPort >> 0) & 0xFF); + + //sequencenumber + header[16] = (byte)((sequencenumber >> 24) & 0xFF); + header[17] = (byte)((sequencenumber >> 16) & 0xFF); + header[18] = (byte)((sequencenumber >> 8) & 0xFF); + header[19] = (byte)((sequencenumber >> 0) & 0xFF); + + //Acknowledgment number + header[20] = (byte)((acknowledgmentnb >> 24) & 0xFF); + header[21] = (byte)((acknowledgmentnb >> 16) & 0xFF); + header[22] = (byte)((acknowledgmentnb >> 8) & 0xFF); + header[23] = (byte)((acknowledgmentnb >> 0) & 0xFF); + + //Header lenght + header[24] = (byte)((Headerlenght >> 0) & 0xFF); + + //Flags + header[25] = (byte)((Flags >> 0) & 0xFF); + + //Window size value + header[26] = (byte)((WSValue >> 8) & 0xFF); + header[27] = (byte)((WSValue >> 0) & 0xFF); + + //Urgent Pointer + header[28] = (byte)((UrgentPointer >> 8) & 0xFF); + header[29] = (byte)((UrgentPointer >> 0) & 0xFF); + + for (int i = 0; i < RawData.Length - (DataOffset + 20); i++) + { + header[30 + i] = RawData[DataOffset + 20 + i]; + } + + return header; + } + internal ushort DestinationPort { get { return destinationPort; } From b668abee6c59e1ccb3884a639291ebd58279ca5e Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 19 Feb 2021 11:33:34 +0100 Subject: [PATCH 064/314] TCP Header changes --- .../Network/IPv4/TCP/TCPPacket.cs | 79 +++++++------------ 1 file changed, 28 insertions(+), 51 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 5aa82295e6..89f3dd7670 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -111,12 +111,15 @@ public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, RawData[DataOffset + 14] = (byte)((WSValue >> 8) & 0xFF); RawData[DataOffset + 15] = (byte)((WSValue >> 0) & 0xFF); + //Checksum + RawData[DataOffset + 16] = 0; + RawData[DataOffset + 17] = 0; + //Urgent Pointer RawData[DataOffset + 18] = (byte)((UrgentPointer >> 8) & 0xFF); RawData[DataOffset + 19] = (byte)((UrgentPointer >> 0) & 0xFF); - byte[] header = MakeHeader(source.address, dest.address, (ushort)(20 + len), srcPort, destPort, - sequencenumber, acknowledgmentnb, Headerlenght, Flags, WSValue, UrgentPointer); + byte[] header = MakeHeader(); ushort calculatedcrc = CalcOcCRC(header, 0, header.Length); @@ -146,7 +149,7 @@ protected override void InitFields() PSH = (RawData[47] & (1 << 3)) != 0; RST = (RawData[47] & (1 << 2)) != 0; - //options + //options parsing if (RawData[DataOffset + 20] != 0) { options = new List(); @@ -194,64 +197,38 @@ internal void AddOption(byte[] raw) } } - internal byte[] MakeHeader(byte[] sourceIP, byte[] destIP, ushort tcpLen, - ushort sourcePort, ushort destPort, ulong sequencenumber, ulong acknowledgmentnb, - int Headerlenght, int Flags, int WSValue, int UrgentPointer) + /// + /// Make TCP Header for CRC Computation + /// + /// byte array value. + internal byte[] MakeHeader() { - byte[] header = new byte[30 + RawData.Length - (DataOffset + 20)]; - - header[0] = sourceIP[0]; - header[1] = sourceIP[1]; - header[2] = sourceIP[2]; - header[3] = sourceIP[3]; + /* Pseudo Header */ + byte[] header = new byte[12 + (RawData.Length - DataOffset)]; - header[4] = destIP[0]; - header[5] = destIP[1]; - header[6] = destIP[2]; - header[7] = destIP[3]; + //Addresses + for (int b = 0; b < 4; b++) + { + RawData[0 + b] = SourceIP.address[b]; + RawData[4 + b] = DestinationIP.address[b]; + } + //Reserved header[8] = 0x00; + //Protocol (TCP) header[9] = 0x06; - header[10] = (byte)((tcpLen >> 8) & 0xFF); - header[11] = (byte)((tcpLen >> 0) & 0xFF); - - header[12] = (byte)((sourcePort >> 8) & 0xFF); - header[13] = (byte)((sourcePort >> 0) & 0xFF); - - header[14] = (byte)((destPort >> 8) & 0xFF); - header[15] = (byte)((destPort >> 0) & 0xFF); - - //sequencenumber - header[16] = (byte)((sequencenumber >> 24) & 0xFF); - header[17] = (byte)((sequencenumber >> 16) & 0xFF); - header[18] = (byte)((sequencenumber >> 8) & 0xFF); - header[19] = (byte)((sequencenumber >> 0) & 0xFF); - - //Acknowledgment number - header[20] = (byte)((acknowledgmentnb >> 24) & 0xFF); - header[21] = (byte)((acknowledgmentnb >> 16) & 0xFF); - header[22] = (byte)((acknowledgmentnb >> 8) & 0xFF); - header[23] = (byte)((acknowledgmentnb >> 0) & 0xFF); - - //Header lenght - header[24] = (byte)((Headerlenght >> 0) & 0xFF); + ushort tcplen = (ushort)(RawData.Length - DataOffset); - //Flags - header[25] = (byte)((Flags >> 0) & 0xFF); - - //Window size value - header[26] = (byte)((WSValue >> 8) & 0xFF); - header[27] = (byte)((WSValue >> 0) & 0xFF); - - //Urgent Pointer - header[28] = (byte)((UrgentPointer >> 8) & 0xFF); - header[29] = (byte)((UrgentPointer >> 0) & 0xFF); + //TCP Length + header[10] = (byte)((tcplen >> 8) & 0xFF); + header[11] = (byte)((tcplen >> 0) & 0xFF); - for (int i = 0; i < RawData.Length - (DataOffset + 20); i++) + //TCP Packet + for (int i = 0; i < RawData.Length - DataOffset; i++) { - header[30 + i] = RawData[DataOffset + 20 + i]; + header[12 + i] = RawData[DataLength + i]; } return header; From ab61bebb0094824e1eba6aa21e3a4a7cec293190 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 19 Feb 2021 15:08:14 +0100 Subject: [PATCH 065/314] Checksum calculation + Random sequence number --- .../Network/IPv4/TCP/TCPClient.cs | 11 ++++-- .../Network/IPv4/TCP/TCPPacket.cs | 38 +++++++++++++------ 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 73bbff19be..6b705d37c5 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -117,16 +117,19 @@ public void Connect(Address dest, int destPort, int timeout = 5000) Address source = IPConfig.FindNetwork(dest); + global::System.Console.WriteLine(source.ToString()); + byte[] options = new byte[] { 0x02, 0x04, 0x05, 0xB4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, 0x04, 0x02 }; - //TODO: Generate sequence number - // Flags=0x02 -> Syn - var packet = new TCPPacket(source, dest, (ushort)localPort, (ushort)destPort, 3455719727, 0, (ushort)(20 + options.Length), 0x02, 0xFAF0, 0, (ushort)options.Length); + //Generate Random Sequence Number + var rnd = new Random(); + ulong sequencenumber = (ulong)((rnd.Next(0, Int32.MaxValue)) << 32) | (ulong)(rnd.Next(0, Int32.MaxValue)); - packet.AddOption(options); + // Flags=0x02 -> Syn + var packet = new TCPPacket(source, dest, (ushort)localPort, (ushort)destPort, sequencenumber, 0, (ushort)(20 + options.Length), 0x02, 0xFAF0, 0, (ushort)options.Length, options); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 89f3dd7670..d1d08381fc 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -75,10 +75,28 @@ internal TCPPacket(byte[] rawData) : base(rawData) { } + public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, + ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, ushort Flags, + ushort WSValue, ushort UrgentPointer, ushort len, byte[] options) + : base((ushort)(20 + len), 6, source, dest, 0x40) + { + AddRawOption(options); + MakePacket(source, dest, srcPort, destPort, sequencenumber, + acknowledgmentnb, Headerlenght, Flags, WSValue, UrgentPointer, len); + } + public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, ushort Flags, ushort WSValue, ushort UrgentPointer, ushort len) : base((ushort)(20 + len), 6, source, dest, 0x40) + { + MakePacket(source, dest, srcPort, destPort, sequencenumber, + acknowledgmentnb, Headerlenght, Flags, WSValue, UrgentPointer, len); + } + + private void MakePacket(Address source, Address dest, ushort srcPort, ushort destPort, + ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, ushort Flags, + ushort WSValue, ushort UrgentPointer, ushort len) { optionLen = len; @@ -119,15 +137,15 @@ public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, RawData[DataOffset + 18] = (byte)((UrgentPointer >> 8) & 0xFF); RawData[DataOffset + 19] = (byte)((UrgentPointer >> 0) & 0xFF); - byte[] header = MakeHeader(); + InitFields(); + //Checksum computation + byte[] header = MakeHeader(); ushort calculatedcrc = CalcOcCRC(header, 0, header.Length); //Checksum RawData[DataOffset + 16] = (byte)((calculatedcrc >> 8) & 0xFF); RawData[DataOffset + 17] = (byte)((calculatedcrc >> 0) & 0xFF); - - InitFields(); } protected override void InitFields() @@ -185,12 +203,8 @@ internal void AddOption(TCPOption option) throw new NotImplementedException(); } - internal void AddOption(byte[] raw) + internal void AddRawOption(byte[] raw) { - if (raw.Length > optionLen) - { - throw new Exception("Raw option is larger than max value."); - } for (int i = 0; i < raw.Length; i++) { RawData[DataOffset + 20 + i] = raw[i]; @@ -209,8 +223,8 @@ internal byte[] MakeHeader() //Addresses for (int b = 0; b < 4; b++) { - RawData[0 + b] = SourceIP.address[b]; - RawData[4 + b] = DestinationIP.address[b]; + header[0 + b] = SourceIP.address[b]; + header[4 + b] = DestinationIP.address[b]; } //Reserved @@ -225,10 +239,10 @@ internal byte[] MakeHeader() header[10] = (byte)((tcplen >> 8) & 0xFF); header[11] = (byte)((tcplen >> 0) & 0xFF); - //TCP Packet + /** TCP Packet **/ for (int i = 0; i < RawData.Length - DataOffset; i++) { - header[12 + i] = RawData[DataLength + i]; + header[12 + i] = RawData[DataOffset + i]; } return header; From 5cc7dde71179bd1143c33081f4a12f1e8eb9b8ce Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 19 Feb 2021 16:30:36 +0100 Subject: [PATCH 066/314] Add TCP using --- Tests/Kernels/NetworkTest/Kernel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Kernels/NetworkTest/Kernel.cs b/Tests/Kernels/NetworkTest/Kernel.cs index 21f137582b..197904fb74 100644 --- a/Tests/Kernels/NetworkTest/Kernel.cs +++ b/Tests/Kernels/NetworkTest/Kernel.cs @@ -3,6 +3,7 @@ using Cosmos.System.Network.ARP; using Cosmos.System.Network.Config; using Cosmos.System.Network.IPv4; +using Cosmos.System.Network.IPv4.TCP; using Cosmos.System.Network.IPv4.UDP; using Cosmos.System.Network.IPv4.UDP.DHCP; using Cosmos.System.Network.IPv4.UDP.DNS; From f3c3aeb1d32a3faa58c3aaac92043549843ade37 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 19 Feb 2021 21:11:06 +0100 Subject: [PATCH 067/314] Send ACK response after connection --- .../Network/IPv4/TCP/TCPClient.cs | 27 +++++++++++++++---- .../Network/IPv4/TCP/TCPPacket.cs | 13 +++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 6b705d37c5..570cee12c2 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -28,6 +28,10 @@ public class TcpClient : IDisposable /// private int localPort; /// + /// Source address. + /// + internal Address source; + /// /// Destination address. /// internal Address destination; @@ -41,6 +45,11 @@ public class TcpClient : IDisposable /// internal Queue rxBuffer; + /// + /// Connection status. + /// + internal bool Connected = false; + /// /// Assign clients dictionary. /// @@ -115,7 +124,7 @@ public void Connect(Address dest, int destPort, int timeout = 5000) destination = dest; destinationPort = destPort; - Address source = IPConfig.FindNetwork(dest); + source = IPConfig.FindNetwork(dest); global::System.Console.WriteLine(source.ToString()); @@ -157,14 +166,22 @@ private void WaitForConnectionResponse(int timeout) var packet = new TCPPacket(rxBuffer.Dequeue().RawData); - Global.mDebugger.Send("Flags=" + packet.Flags); - if (packet.Flags == 0x12) // SYN/ACK { - + SendAck(packet); } + } + + private void SendAck(TCPPacket responsepacket) + { + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)localPort, responsepacket.AckNumber, responsepacket.SequenceNumber + 1, 20, 0x10, 0xFAF0, 0, 0); + + OutgoingBuffer.AddPacket(packet); + NetworkStack.Update(); + + Global.mDebugger.Send("TCP Connection established!"); - //send ACK + Connected = true; } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index d1d08381fc..f60521e54d 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -85,6 +85,15 @@ public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, acknowledgmentnb, Headerlenght, Flags, WSValue, UrgentPointer, len); } + public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, + ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, ushort Flags, + ushort WSValue, ushort UrgentPointer) + : base(20, 6, source, dest, 0x40) + { + MakePacket(source, dest, srcPort, destPort, sequencenumber, + acknowledgmentnb, Headerlenght, Flags, WSValue, UrgentPointer, 0); + } + public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, ushort Flags, ushort WSValue, ushort UrgentPointer, ushort len) @@ -256,6 +265,10 @@ internal ushort SourcePort { get { return sourcePort; } } + internal ulong AckNumber + { + get { return ackNumber; } + } internal ulong SequenceNumber { get { return sequenceNumber; } From e25394e01d0cbc94f6ad52fef53b0e3577ce7166 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 19 Feb 2021 21:50:20 +0100 Subject: [PATCH 068/314] TCP work --- .../Network/IPv4/TCP/TCPClient.cs | 30 +++++++++++-------- .../Network/IPv4/TCP/TCPPacket.cs | 8 ++--- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 570cee12c2..f8eb93c1fe 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -119,15 +119,13 @@ public TcpClient(Address dest, int destPort) /// /// Destination address. /// Destination port. - public void Connect(Address dest, int destPort, int timeout = 5000) + public bool Connect(Address dest, int destPort, int timeout = 5000) { destination = dest; destinationPort = destPort; source = IPConfig.FindNetwork(dest); - global::System.Console.WriteLine(source.ToString()); - byte[] options = new byte[] { 0x02, 0x04, 0x05, 0xB4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, 0x04, 0x02 @@ -138,15 +136,15 @@ public void Connect(Address dest, int destPort, int timeout = 5000) ulong sequencenumber = (ulong)((rnd.Next(0, Int32.MaxValue)) << 32) | (ulong)(rnd.Next(0, Int32.MaxValue)); // Flags=0x02 -> Syn - var packet = new TCPPacket(source, dest, (ushort)localPort, (ushort)destPort, sequencenumber, 0, (ushort)(20 + options.Length), 0x02, 0xFAF0, 0, (ushort)options.Length, options); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destPort, sequencenumber, 0, (ushort)(20 + options.Length), 0x02, 0xFAF0, 0, (ushort)options.Length, options); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - WaitForConnectionResponse(timeout); + return WaitForConnectionResponse(timeout); } - private void WaitForConnectionResponse(int timeout) + private bool WaitForConnectionResponse(int timeout) { int second = 0; int _deltaT = 0; @@ -155,7 +153,7 @@ private void WaitForConnectionResponse(int timeout) { if (second > (timeout / 1000)) { - return; + return false; } if (_deltaT != RTC.Second) { @@ -164,24 +162,30 @@ private void WaitForConnectionResponse(int timeout) } } - var packet = new TCPPacket(rxBuffer.Dequeue().RawData); + var packet = rxBuffer.Dequeue(); if (packet.Flags == 0x12) // SYN/ACK { SendAck(packet); + + Global.mDebugger.Send("TCP Connection established!"); + + Connected = true; + + return true; + } + else + { + return false; } } private void SendAck(TCPPacket responsepacket) { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)localPort, responsepacket.AckNumber, responsepacket.SequenceNumber + 1, 20, 0x10, 0xFAF0, 0, 0); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)localPort, responsepacket.AckNumber, responsepacket.SequenceNumber + 1, 20, 0x10, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - - Global.mDebugger.Send("TCP Connection established!"); - - Connected = true; } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index f60521e54d..f840317898 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -226,29 +226,25 @@ internal void AddRawOption(byte[] raw) /// byte array value. internal byte[] MakeHeader() { - /* Pseudo Header */ byte[] header = new byte[12 + (RawData.Length - DataOffset)]; + /* Pseudo Header */ //Addresses for (int b = 0; b < 4; b++) { header[0 + b] = SourceIP.address[b]; header[4 + b] = DestinationIP.address[b]; } - //Reserved header[8] = 0x00; - //Protocol (TCP) header[9] = 0x06; - ushort tcplen = (ushort)(RawData.Length - DataOffset); - //TCP Length header[10] = (byte)((tcplen >> 8) & 0xFF); header[11] = (byte)((tcplen >> 0) & 0xFF); - /** TCP Packet **/ + /* TCP Packet */ for (int i = 0; i < RawData.Length - DataOffset; i++) { header[12 + i] = RawData[DataOffset + i]; From 85e1e257579315137970de08f90a295182f686ce Mon Sep 17 00:00:00 2001 From: KM198912 <55886806+KM198912@users.noreply.github.com> Date: Fri, 9 Apr 2021 17:19:36 +0200 Subject: [PATCH 069/314] Update VMWareSVGAII.cs Fix SVGA to avoid a Index out of Bounds crash that happened due to a double memory write. With this we disable the Driver before writing new values to the FIFO and initiating the memory again, before we initiated the memory regardless if it was already set or not and sent garbage to the FIFO causing it to crash. Also introduce the ability to switch between Graphics And Text mode. --- source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs b/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs index 9f0df3dd16..1600a4306f 100644 --- a/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs +++ b/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs @@ -517,6 +517,8 @@ protected void InitializeFIFO() /// Depth. public void SetMode(uint width, uint height, uint depth = 32) { + //Disable the Driver before writing new values and initiating it again to avoid a memory exception + Disable(); // Depth is color depth in bytes. this.depth = (depth / 8); this.width = width; @@ -753,6 +755,11 @@ public void DefineCursor() WriteToFifo(0xFFFFFF); WaitForFifo(); } + //Allow to enable the Driver again after it has been disable (switch between text and graphics mode currently this is SVGA only) + public void Enable() + { + WriteRegister(Register.Enable, 1); + } public void Disable() { From a7a99d5b137cb80b6d8b15820c527db3ba5328a9 Mon Sep 17 00:00:00 2001 From: KM198912 <55886806+KM198912@users.noreply.github.com> Date: Fri, 9 Apr 2021 17:27:46 +0200 Subject: [PATCH 070/314] Update VMWareSVGAII.cs MAke SetMode use Enable() and fix a small typo --- source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs b/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs index 1600a4306f..dcbb67c163 100644 --- a/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs +++ b/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs @@ -526,7 +526,7 @@ public void SetMode(uint width, uint height, uint depth = 32) WriteRegister(Register.Width, width); WriteRegister(Register.Height, height); WriteRegister(Register.BitsPerPixel, depth); - WriteRegister(Register.Enable, 1); + Enable(); InitializeFIFO(); } @@ -755,7 +755,7 @@ public void DefineCursor() WriteToFifo(0xFFFFFF); WaitForFifo(); } - //Allow to enable the Driver again after it has been disable (switch between text and graphics mode currently this is SVGA only) + //Allow to enable the Driver again after it has been disabled (switch between text and graphics mode currently this is SVGA only) public void Enable() { WriteRegister(Register.Enable, 1); From baffb4386e636b7b14cedad29c68c635dd88fe1f Mon Sep 17 00:00:00 2001 From: KM198912 <55886806+KM198912@users.noreply.github.com> Date: Fri, 9 Apr 2021 17:29:40 +0200 Subject: [PATCH 071/314] Update VMWareSVGAII.cs --- source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs b/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs index dcbb67c163..eaf45a23b1 100644 --- a/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs +++ b/source/Cosmos.HAL2/Drivers/PCI/Video/VMWareSVGAII.cs @@ -756,11 +756,16 @@ public void DefineCursor() WaitForFifo(); } //Allow to enable the Driver again after it has been disabled (switch between text and graphics mode currently this is SVGA only) + /// + /// Enable the SVGA Driver , only needed after Disable() has been called + /// public void Enable() { WriteRegister(Register.Enable, 1); } - + /// + /// Disable the SVGA Driver , return to text mode + /// public void Disable() { WriteRegister(Register.Enable, 0); From 2754feae2ae5b410b44aa6ac0d4acb80fb28b86a Mon Sep 17 00:00:00 2001 From: Quajak Date: Sun, 11 Apr 2021 10:56:12 +0200 Subject: [PATCH 072/314] Increased output randomness of Next(min, max) --- source/Cosmos.System2_Plugs/System/RandomImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.System2_Plugs/System/RandomImpl.cs b/source/Cosmos.System2_Plugs/System/RandomImpl.cs index e4658bca60..d35bfb5298 100644 --- a/source/Cosmos.System2_Plugs/System/RandomImpl.cs +++ b/source/Cosmos.System2_Plugs/System/RandomImpl.cs @@ -35,7 +35,7 @@ public static int Next(Random aThis, int minValue, int maxValue) uint diff = (uint)(maxValue - minValue); if (diff <= 1) return minValue; - return (int)((uint)(GetUniform() * diff) + minValue); + return Next() % diff + minValue; } public static void NextBytes(Random aThis, byte[] buffer) From 6e980e73c63c9d0b8941d60419e6ca415973bcf7 Mon Sep 17 00:00:00 2001 From: Quajak Date: Mon, 12 Apr 2021 14:19:49 +0200 Subject: [PATCH 073/314] Try fix build problems by changing image used --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 5b0497dd2e..755c478329 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ version: 0.20150918.{build} -image: Visual Studio 2019 Preview +image: Visual Studio 2019 configuration: Debug-CI platform: Any CPU shallow_clone: true From b1fc0a3a77c8455068c96893def46e1c2bad7364 Mon Sep 17 00:00:00 2001 From: Quajak Date: Mon, 12 Apr 2021 14:28:26 +0200 Subject: [PATCH 074/314] Missed the argument --- source/Cosmos.System2_Plugs/System/RandomImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.System2_Plugs/System/RandomImpl.cs b/source/Cosmos.System2_Plugs/System/RandomImpl.cs index d35bfb5298..1b8d24ec77 100644 --- a/source/Cosmos.System2_Plugs/System/RandomImpl.cs +++ b/source/Cosmos.System2_Plugs/System/RandomImpl.cs @@ -35,7 +35,7 @@ public static int Next(Random aThis, int minValue, int maxValue) uint diff = (uint)(maxValue - minValue); if (diff <= 1) return minValue; - return Next() % diff + minValue; + return Next(aThis) % diff + minValue; } public static void NextBytes(Random aThis, byte[] buffer) From b3a7d00ef7395317d84ce33917c0f866f0c98b92 Mon Sep 17 00:00:00 2001 From: Quajak Date: Mon, 12 Apr 2021 14:34:47 +0200 Subject: [PATCH 075/314] Fixed types --- source/Cosmos.System2_Plugs/System/RandomImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.System2_Plugs/System/RandomImpl.cs b/source/Cosmos.System2_Plugs/System/RandomImpl.cs index 1b8d24ec77..bc259b38f7 100644 --- a/source/Cosmos.System2_Plugs/System/RandomImpl.cs +++ b/source/Cosmos.System2_Plugs/System/RandomImpl.cs @@ -32,7 +32,7 @@ public static int Next(Random aThis) public static int Next(Random aThis, int minValue, int maxValue) { - uint diff = (uint)(maxValue - minValue); + int diff = maxValue - minValue; if (diff <= 1) return minValue; return Next(aThis) % diff + minValue; From 940da184fcb36bb6b50b4b8b419f45f948755521 Mon Sep 17 00:00:00 2001 From: Quajak Date: Wed, 14 Apr 2021 15:29:22 +0200 Subject: [PATCH 076/314] Improved message clarity --- Setup/Cosmos.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Setup/Cosmos.iss b/Setup/Cosmos.iss index 3da2499422..75ed8c4d01 100644 --- a/Setup/Cosmos.iss +++ b/Setup/Cosmos.iss @@ -71,7 +71,7 @@ LicenseFile=LICENSE.txt DisableDirPage=no [Messages] -SelectDirDesc=If the user installing the Cosmos User Kit is not the admin. Please choose the corresponding AppData/Roaming directory. +SelectDirDesc=If the user installing the Cosmos User Kit is not the admin, please choose the users AppData/Roaming directory [Dirs] Name: {app}; Flags: uninsalwaysuninstall From 73c2af63b981c67c4857b401cf779bb756c9d7d7 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 21 Apr 2021 16:55:42 +0200 Subject: [PATCH 077/314] Use TCP Flag for TCP check instead of IP Flag + Remove useless class --- .../Network/IPv4/TCP/TCPClient.cs | 52 ++++++++++-------- .../Network/IPv4/TCP/TCPPacket.cs | 54 ++----------------- 2 files changed, 34 insertions(+), 72 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index f8eb93c1fe..5d19012865 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -13,6 +13,17 @@ namespace Cosmos.System.Network.IPv4.TCP { + /// + /// TCP Connection status + /// + public enum Status + { + OPENED, + OPENING, //SYN sent or received + CLOSED, + CLOSING //FIN sent or received + } + /// /// TCPClient class. Used to manage the TCP connection to a client. /// @@ -48,7 +59,7 @@ public class TcpClient : IDisposable /// /// Connection status. /// - internal bool Connected = false; + internal Status status = Status.CLOSED; /// /// Assign clients dictionary. @@ -141,15 +152,17 @@ public bool Connect(Address dest, int destPort, int timeout = 5000) OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - return WaitForConnectionResponse(timeout); + status = Status.OPENING; + + return Wait(timeout); } - private bool WaitForConnectionResponse(int timeout) + private bool Wait(int timeout) { int second = 0; int _deltaT = 0; - while (rxBuffer.Count < 1) + while (status != Status.OPENED) // SYN/ACK { if (second > (timeout / 1000)) { @@ -161,23 +174,7 @@ private bool WaitForConnectionResponse(int timeout) _deltaT = RTC.Second; } } - - var packet = rxBuffer.Dequeue(); - - if (packet.Flags == 0x12) // SYN/ACK - { - SendAck(packet); - - Global.mDebugger.Send("TCP Connection established!"); - - Connected = true; - - return true; - } - else - { - return false; - } + return true; } private void SendAck(TCPPacket responsepacket) @@ -265,7 +262,18 @@ public byte[] Receive(ref EndPoint source) /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { - rxBuffer.Enqueue(packet); + if (status == Status.OPENING && packet.TCPFlags == 0x12) //SYN/ACK + { + status = Status.OPENED; + + Global.mDebugger.Send("TCP Connection established!"); + + SendAck(packet); + } + else + { + rxBuffer.Enqueue(packet); + } } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index f840317898..1770da56c5 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -44,8 +44,6 @@ public class TCPPacket : IPPacket public bool PSH; public bool RST; - - internal static void TCPHandler(byte[] packetData) { var packet = new TCPPacket(packetData); @@ -269,58 +267,14 @@ internal ulong SequenceNumber { get { return sequenceNumber; } } - - public override string ToString() - { - return "TCP Packet Src=" + SourceIP + ":" + sourcePort + ", Dest=" + DestinationIP + ":" + destinationPort; - } - } - - public class TCPacketSyn : TCPPacket - { - /// - /// Work around to make VMT scanner include the initFields method - /// - public static void VMTInclude() - { - new TCPacketSyn(); - } - - internal TCPacketSyn() - : base() - { } - - public TCPacketSyn(Address Source, Address Destination, ushort SourcePort, - ushort DestinationPort, ulong SequenceNumber, ulong ACKNumber, - ushort Flags, ushort WSValue, List options, ushort optionslen) - : base(Source, Destination, SourcePort, DestinationPort, SequenceNumber, - ACKNumber, 0x50, Flags, WSValue, 0x0000, optionslen) + internal int TCPFlags { - int counter = 0; - foreach (var option in options) - { - RawData[DataOffset + 20 + counter] = option.Kind; - - if (option.Kind != 1) //NOP - { - RawData[DataOffset + 20 + counter + 1] = option.Length; - - if (option.Length != 2) - { - for (int j = 0; j < option.Length - 2; j++) - { - RawData[DataOffset + 20 + counter + 2 + j] = option.Data[j]; - } - } - } - - counter += option.Length; - } + get { return flags; } } - protected override void InitFields() + public override string ToString() { - base.InitFields(); + return "TCP Packet Src=" + SourceIP + ":" + sourcePort + ", Dest=" + DestinationIP + ":" + destinationPort; } } } From 5a0802ec3ad582de527f46158ba2218ef69e27a5 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 23 Apr 2021 13:20:55 +0200 Subject: [PATCH 078/314] Code clean --- .../Network/IPv4/TCP/TCPClient.cs | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 5d19012865..4ba2c1fb90 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -59,7 +59,7 @@ public class TcpClient : IDisposable /// /// Connection status. /// - internal Status status = Status.CLOSED; + internal Status Status; /// /// Assign clients dictionary. @@ -103,6 +103,7 @@ public TcpClient() public TcpClient(int localPort) { rxBuffer = new Queue(8); + Status = Status.CLOSED; this.localPort = localPort; if (localPort > 0) @@ -152,37 +153,9 @@ public bool Connect(Address dest, int destPort, int timeout = 5000) OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - status = Status.OPENING; + Status = Status.OPENING; - return Wait(timeout); - } - - private bool Wait(int timeout) - { - int second = 0; - int _deltaT = 0; - - while (status != Status.OPENED) // SYN/ACK - { - if (second > (timeout / 1000)) - { - return false; - } - if (_deltaT != RTC.Second) - { - second++; - _deltaT = RTC.Second; - } - } - return true; - } - - private void SendAck(TCPPacket responsepacket) - { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)localPort, responsepacket.AckNumber, responsepacket.SequenceNumber + 1, 20, 0x10, 0xFAF0, 0); - - OutgoingBuffer.AddPacket(packet); - NetworkStack.Update(); + return WaitStatus(Status.OPENED, timeout); } /// @@ -262,9 +235,9 @@ public byte[] Receive(ref EndPoint source) /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { - if (status == Status.OPENING && packet.TCPFlags == 0x12) //SYN/ACK + if (Status == Status.OPENING && packet.TCPFlags == 0x12) //SYN/ACK { - status = Status.OPENED; + Status = Status.OPENED; Global.mDebugger.Send("TCP Connection established!"); @@ -283,5 +256,32 @@ public void Dispose() { Close(); } + + private bool WaitStatus(Status status, int timeout) + { + int second = 0; + int _deltaT = 0; + + while (Status != status) + { + if (second > (timeout / 1000)) + { + return false; + } + if (_deltaT != RTC.Second) + { + second++; + _deltaT = RTC.Second; + } + } + return true; + } + + private void SendAck(TCPPacket responsepacket) + { + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, responsepacket.AckNumber, responsepacket.SequenceNumber + 1, 20, 0x10, 0xFAF0, 0); + OutgoingBuffer.AddPacket(packet); + NetworkStack.Update(); + } } } From 343f0476084b4781bc9114aeb28bbb71b9dfb059 Mon Sep 17 00:00:00 2001 From: Quajak Date: Fri, 23 Apr 2021 14:56:05 +0200 Subject: [PATCH 079/314] Add link to discord --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index eceb80016a..071eefeb7b 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,5 @@ Cosmos is an operating system "construction kit". Build your own OS using manage For instructions on how to install and use Cosmos, please visit the [Cosmos website](http://www.gocosmos.org). For documentation and technical information, see the [Cosmos Documentation](https://cosmosos.github.io). + +We also have a [Discord Server](https://discord.com/invite/kwtBwv6jhD)! From 2569da7238bd73bece909cba2931e1f7d1c3bb46 Mon Sep 17 00:00:00 2001 From: Quajak Date: Fri, 23 Apr 2021 15:06:26 +0200 Subject: [PATCH 080/314] Expand upon issues and discussios --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 071eefeb7b..2f9a30ba1f 100644 --- a/README.md +++ b/README.md @@ -8,4 +8,6 @@ For instructions on how to install and use Cosmos, please visit the [Cosmos webs For documentation and technical information, see the [Cosmos Documentation](https://cosmosos.github.io). +If you have questions about how to use Cosmos, want to show off what you have made or have general questions, go check out [Github Discussions] (https://github.com/CosmosOS/Cosmos/discussions). If you think you found a bug in Cosmos, please check exising [issues](https://github.com/CosmosOS/Cosmos/issues) first before opening a new one. + We also have a [Discord Server](https://discord.com/invite/kwtBwv6jhD)! From a471243e24a8da15c54980ba36610597baeb604b Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 23 Apr 2021 17:09:37 +0200 Subject: [PATCH 081/314] NRE fix if no option --- source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 1770da56c5..7df93ec93e 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -175,6 +175,10 @@ protected override void InitFields() RST = (RawData[47] & (1 << 2)) != 0; //options parsing + if (RawData.Length <= DataOffset + 20) + { + return; + } if (RawData[DataOffset + 20] != 0) { options = new List(); From 10db39061c240b22c17c56e386971a8a1b527e1b Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Sun, 25 Apr 2021 09:03:48 -0400 Subject: [PATCH 082/314] Add RTL8139 updated driver --- .../Drivers/PCI/Network/RTL8139.cs | 271 ++++++++---------- source/Cosmos.HAL2/Network/NetworkInit.cs | 13 + 2 files changed, 134 insertions(+), 150 deletions(-) diff --git a/source/Cosmos.HAL2/Drivers/PCI/Network/RTL8139.cs b/source/Cosmos.HAL2/Drivers/PCI/Network/RTL8139.cs index 86683fa844..d517cac28e 100644 --- a/source/Cosmos.HAL2/Drivers/PCI/Network/RTL8139.cs +++ b/source/Cosmos.HAL2/Drivers/PCI/Network/RTL8139.cs @@ -1,265 +1,250 @@ -/* +using Cosmos.Core; +using Cosmos.HAL.Network; using System; using System.Collections.Generic; -using System.Text; -using Cosmos.Hardware2; -using Cosmos.Hardware2.Network; -using Cosmos.Kernel; -using Cosmos.Kernel.ManagedMemory; +using static Cosmos.Core.INTs; namespace Cosmos.HAL.Drivers.PCI.Network { public class RTL8139 : NetworkDevice { protected PCIDevice pciCard; - protected AddressSpace io; protected MACAddress mac; protected bool mInitDone; - - protected ManagedMemorySpace rxBuffer; + protected ManagedMemoryBlock rxBuffer; protected int rxBufferOffset; protected UInt16 capr; - protected Queue mRecvBuffer; protected Queue mTransmitBuffer; private int mNextTXDesc; - const UInt16 RxBufferSize = 32768; + private uint Base; public RTL8139(PCIDevice device) { - if (device == null) { + if (device == null) + { throw new ArgumentException("PCI Device is null. Unable to get Realtek 8139 card"); } pciCard = device; - + Base = device.BaseAddressBar[0].BaseAddress; // We are handling this device pciCard.Claimed = true; - // Setup interrupt handling - //Interrupts.IRQ11 += HandleNetworkInterrupt; - //Interrupts.AddIRQHandler(device.InterruptLine, HandleNetworkInterrupt); - + INTs.SetIrqHandler(device.InterruptLine, HandleNetworkInterrupt); // Get IO Address from PCI Bus - io = pciCard.GetAddressSpace(0); - // Enable the card pciCard.EnableDevice(); - // Turn on the card - io.Write8(0x52, 0x01); - + OutB(Base + 0x52, 0x01); //Do a software reset SoftwareReset(); - // Get the MAC Address byte[] eeprom_mac = new byte[6]; for (uint b = 0; b < 6; b++) { - eeprom_mac[b] = io.Read8(b); + eeprom_mac[b] = Inb(Base + b); } - this.mac = new MACAddress(eeprom_mac); - // Get a receive buffer and assign it to the card - rxBuffer = new ManagedMemorySpace(RxBufferSize + 2048 + 16, 4); - + rxBuffer = new ManagedMemoryBlock(RxBufferSize + 2048 + 16, 4); RBStartRegister = rxBuffer.Offset; - // Setup receive Configuration RecvConfigRegister = 0xF381; // Setup Transmit Configuration TransmitConfigRegister = 0x3000300; - // Setup Interrupts IntMaskRegister = 0x7F; IntStatusRegister = 0xFFFF; - // Setup our Receive and Transmit Queues mRecvBuffer = new Queue(); mTransmitBuffer = new Queue(); } + private static byte Inb(uint port) + { + return new IOPort((ushort)port).Byte; + } + private static void OutB(uint port, byte val) + { + new IOPort((ushort)port).Byte = val; + } - public static void InitDriver() + private static ushort Inb16(uint port) + { + return new IOPort((ushort)port).Word; + } + private static void Out16(uint port, ushort val) { - Device.AddDriverInit(FindAll); + new IOPort((ushort)port).Word = val; } - public static void FindAll() + private static uint Inb32(uint port) + { + return new IOPort((ushort)port).DWord; + } + private static void Out32(uint port, uint val) { - Console.WriteLine("Scanning for Realtek 8139 cards..."); - for(int i = 0; i < PCIBus.Devices.Length; i++) + new IOPort((ushort)port).DWord = val; + } + public static List FindAll() + { + //Console.WriteLine("Scanning for Realtek 8139 cards..."); + + List cards = new List(); + foreach (var xDevice in HAL.PCI.Devices) { - var xDevice = PCIBus.Devices[i]; - //DebugWriteLine("VendorID: " + device.VendorID + " - DeviceID: " + device.DeviceID); if ((xDevice.VendorID == 0x10EC) && (xDevice.DeviceID == 0x8139) && (xDevice.Claimed == false)) { RTL8139 nic = new RTL8139(xDevice); - NetworkDevice.Add(nic); + cards.Add(nic); } } + return cards; + } + protected void HandleNetworkInterrupt(ref IRQContext aContext) + { + UInt16 cur_status = IntStatusRegister; + //Console.WriteLine("RTL8139 Interrupt: ISR=" + cur_status.ToString()); + if ((cur_status & 0x01) != 0) + { + while ((CommandRegister & 0x01) == 0) + { + //UInt32 packetHeader = BitConverter.ToUInt32(rxBuffer, rxBufferOffset + capr); + UInt32 packetHeader = rxBuffer.Read32(capr); + UInt16 packetLen = (UInt16)(packetHeader >> 16); + if ((packetHeader & 0x3E) != 0x00) + { + CommandRegister = 0x04; // TX Only; + capr = CurBufferAddressRegister; + CommandRegister = 0x0C; // RX and TX Enabled + } + else if ((packetHeader & 0x01) == 0x01) + { + ReadRawData(packetLen); + } + CurAddressPointerReadRegister = (UInt16)(capr - 0x10); + } + } + if ((cur_status & 0x10) != 0) + { + CurAddressPointerReadRegister = (UInt16)(CurBufferAddressRegister - 0x10); + cur_status = (UInt16)(cur_status | 0x01); + } + IntStatusRegister = cur_status; } - - //protected void HandleNetworkInterrupt(ref IRQContext aContext) - //{ - // UInt16 cur_status = IntStatusRegister; - - // //Console.WriteLine("RTL8139 Interrupt: ISR=" + cur_status.ToString()); - // if ((cur_status & 0x01) != 0) - // { - // while ((CommandRegister & 0x01) == 0) - // { - // //UInt32 packetHeader = BitConverter.ToUInt32(rxBuffer, rxBufferOffset + capr); - // UInt32 packetHeader = rxBuffer.Read32(capr); - // UInt16 packetLen = (UInt16)(packetHeader >> 16); - // if ((packetHeader & 0x3E) != 0x00) - // { - // CommandRegister = 0x04; // TX Only; - // capr = CurBufferAddressRegister; - // CommandRegister = 0x0C; // RX and TX Enabled - // } - // else if ((packetHeader & 0x01) == 0x01) - // { - // ReadRawData(packetLen); - // } - - // CurAddressPointerReadRegister = (UInt16)(capr - 0x10); - // } - // } - // if ((cur_status & 0x10) != 0) - // { - // CurAddressPointerReadRegister = (UInt16)(CurBufferAddressRegister - 0x10); - // cur_status = (UInt16)(cur_status | 0x01); - // } - - // IntStatusRegister = cur_status; - //} - #region Register Access protected UInt32 RBStartRegister { - get { return io.Read32(0x30); } - set { io.Write32(0x30, value); } + get { return Inb32(Base + 0x30); } + set { Out32(Base + 0x30, value); } } internal UInt32 RecvConfigRegister { - get { return io.Read32(0x44); } - set { io.Write32(0x44, value); } + get { return Inb32(Base + 0x44); } + set { Out32(Base + 0x44, value); } } internal UInt16 CurAddressPointerReadRegister { - get { return io.Read16(0x38); } - set { io.Write16(0x38, value); } + get { return Inb16(Base + 0x38); } + set { Out16(Base + 0x38, value); } } internal UInt16 CurBufferAddressRegister { - get { return io.Read16(0x3A); } - set { io.Write16(0x3A, value); } + get { return Inb16(Base + 0x3A); } + set { Out16(Base + 0x3A, value); } } - internal UInt16 IntMaskRegister { - get { return io.Read16(0x3C); } - set { io.Write16(0x3C, value); } + get { return Inb16(Base + 0x3C); } + set { Out16(Base + 0x3C, value); } } internal UInt16 IntStatusRegister { - get { return io.Read16(0x3E); } - set { io.Write16(0x3E, value); } + get { return Inb16(Base + 0x3E); } + set { Out16(Base + 0x3E, value); } } - internal byte CommandRegister { - get { return io.Read8(0x37); } - set { io.Write8(0x37, value); } + get { return Inb(Base + 0x37); } + set { OutB(Base + 0x37, value); } } protected byte MediaStatusRegister { - get { return io.Read8(0x58); } - set { io.Write8(0x58, value); } + get { return Inb(Base + 0x58); } + set { OutB(Base + 0x58, value); } } - protected byte Config1Register { - get { return io.Read8(0x52); } - set { io.Write8(0x52, value); } + get { return Inb(Base + 0x52); } + set { OutB(Base + 0x52, value); } } - internal UInt32 TransmitConfigRegister { - get { return io.Read32(0x40); } - set { io.Write32(0x40, value); } + get { return Inb32(Base + 0x40); } + set { Out32(Base + 0x40, value); } } - internal UInt32 TransmitAddress1Register { - get { return io.Read32(0x20); } - set { io.Write32(0x20, value); } + get { return Inb32(Base + 0x20); } + set { Out32(Base + 0x20, value); } } internal UInt32 TransmitAddress2Register { - get { return io.Read32(0x24); } - set { io.Write32(0x24, value); } + get { return Inb32(Base + 0x24); } + set { Out32(Base + 0x24, value); } } internal UInt32 TransmitAddress3Register { - get { return io.Read32(0x28); } - set { io.Write32(0x28, value); } + get { return Inb32(Base + 0x28); } + set { Out32(Base + 0x28, value); } } internal UInt32 TransmitAddress4Register { - get { return io.Read32(0x2C); } - set { io.Write32(0x2C, value); } + get { return Inb32(Base + 0x2C); } + set { Out32(Base + 0x2C, value); } } internal UInt32 TransmitDescriptor1Register { - get { return io.Read32(0x10); } - set { io.Write32(0x10, value); } + get { return Inb32(Base + 0x10); } + set { Out32(Base + 0x10, value); } } internal UInt32 TransmitDescriptor2Register { - get { return io.Read32(0x14); } - set { io.Write32(0x14, value); } + get { return Inb32(Base + 0x14); } + set { Out32(Base + 0x14, value); } } internal UInt32 TransmitDescriptor3Register { - get { return io.Read32(0x18); } - set { io.Write32(0x18, value); } + get { return Inb32(Base + 0x18); } + set { Out32(Base + 0x18, value); } } internal UInt32 TransmitDescriptor4Register { - get { return io.Read32(0x1C); } - set { io.Write32(0x1C, value); } + get { return Inb32(Base + 0x1C); } + set { Out32(Base + 0x1C, value); } } #endregion - protected bool CmdBufferEmpty { get { return ((CommandRegister & 0x01) == 0x01); } } - #region Network Device Implementation public override MACAddress MACAddress { get { return this.mac; } } - public override bool Enable() { // Enable Receiving and Transmitting of data CommandRegister = 0x0C; - while (this.Ready == false) { } - - return base.Enable(); + return true; } - public override bool Ready { get { return ((Config1Register & 0x20) == 0); } } - public override bool QueueBytes(byte[] buffer, int offset, int length) { byte[] data = new byte[length]; @@ -267,60 +252,51 @@ public override bool QueueBytes(byte[] buffer, int offset, int length) { data[b] = buffer[b + offset]; } - - Console.WriteLine("Try sending"); - + //Console.WriteLine("Try sending"); if (SendBytes(ref data) == false) { - Console.WriteLine("Queuing"); + //Console.WriteLine("Queuing"); mTransmitBuffer.Enqueue(data); } - return true; } - public override bool ReceiveBytes(byte[] buffer, int offset, int max) { throw new NotImplementedException(); } - public override byte[] ReceivePacket() { if (mRecvBuffer.Count < 1) { return null; } - byte[] data = mRecvBuffer.Dequeue(); return data; } - public override int BytesAvailable() { if (mRecvBuffer.Count < 1) { return 0; } - return mRecvBuffer.Peek().Length; } - public override bool IsSendBufferFull() { return false; } - public override bool IsReceiveBufferFull() { return false; } - public override string Name { get { return "Realtek 8139 Chipset NIC"; } } - #endregion + public override CardType CardType => CardType.Ethernet; + + #endregion #region Helper Functions private void ReadRawData(UInt16 packetLen) { @@ -339,24 +315,20 @@ private void ReadRawData(UInt16 packetLen) if (mRecvBuffer == null) { } - mRecvBuffer.Enqueue(recv_data); } - capr += (UInt16)((packetLen + 4 + 3) & 0xFFFFFFFC); if (capr > RxBufferSize) { capr -= RxBufferSize; } } - protected void SoftwareReset() { CommandRegister = 0x10; while ((CommandRegister & 0x10) != 0) { } } - protected bool SendBytes(ref byte[] aData) { int txd = mNextTXDesc++; @@ -364,11 +336,10 @@ protected bool SendBytes(ref byte[] aData) { mNextTXDesc = 0; } - - ManagedMemorySpace txBuffer; + ManagedMemoryBlock txBuffer; if (aData.Length < 64) { - txBuffer = new ManagedMemorySpace(64); + txBuffer = new ManagedMemoryBlock(64); for (uint b = 0; b < aData.Length; b++) { txBuffer[b] = aData[b]; @@ -376,9 +347,12 @@ protected bool SendBytes(ref byte[] aData) } else { - txBuffer = new ManagedMemorySpace(aData); + txBuffer = new ManagedMemoryBlock((uint)aData.Length); + for (uint i = 0; i < aData.Length; i++) + { + txBuffer[i] = aData[i]; + } } - switch (txd) { case 0: @@ -400,11 +374,8 @@ protected bool SendBytes(ref byte[] aData) default: return false; } - return true; } - #endregion } } -*/ \ No newline at end of file diff --git a/source/Cosmos.HAL2/Network/NetworkInit.cs b/source/Cosmos.HAL2/Network/NetworkInit.cs index 44e827aaec..b6796a9ca0 100644 --- a/source/Cosmos.HAL2/Network/NetworkInit.cs +++ b/source/Cosmos.HAL2/Network/NetworkInit.cs @@ -40,7 +40,20 @@ public static void Init() } #endregion + #region RTL8139 + if (device.VendorID == 0x10EC && device.DeviceID == 0x8139) + { + var RTL8139Device = new RTL8139(device); + + RTL8139Device.NameID = ("eth" + NetworkDeviceID); + + RTL8139Device.Enable(); + + NetworkDeviceID++; + } + + #endregion } } From 50eaedb60b9e530647b1f124993cc2954749cb72 Mon Sep 17 00:00:00 2001 From: Charles Betros Date: Sun, 25 Apr 2021 09:29:59 -0500 Subject: [PATCH 083/314] Create stale.yml --- .github/workflows/stale.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000000..b671fc094c --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,19 @@ +name: Mark stale issues and pull requests + +on: + schedule: + - cron: "30 1 * * *" + +jobs: + stale: + + runs-on: ubuntu-latest + + steps: + - uses: actions/stale@v3 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'Stale issue message' + stale-pr-message: 'Stale pull request message' + stale-issue-label: 'no-issue-activity' + stale-pr-label: 'no-pr-activity' From 86c58519e8399d3f32973bdb511e9b835c1ff608 Mon Sep 17 00:00:00 2001 From: Quajak Date: Mon, 26 Apr 2021 08:42:30 +0200 Subject: [PATCH 084/314] Dont mark issues with up for grabs label as stale --- .github/workflows/stale.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index b671fc094c..f7fcf7251b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,7 +13,8 @@ jobs: - uses: actions/stale@v3 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - stale-issue-message: 'Stale issue message' - stale-pr-message: 'Stale pull request message' + stale-issue-message: 'As this issue has received no new activity, it has been marked as stale' + stale-pr-message: 'As this pull request has received no new activity, it has been marked as stale' stale-issue-label: 'no-issue-activity' stale-pr-label: 'no-pr-activity' + exempt-issue-labels: 'Up for Grabs' From 0168c82ab7ccbd1cdddd90e1225d29bb199529d1 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 26 Apr 2021 15:09:08 +0200 Subject: [PATCH 085/314] Add FIN in + FIN out --- .../Network/IPv4/TCP/TCPClient.cs | 58 ++++++++++++++++--- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 4ba2c1fb90..ce8682c49a 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -61,6 +61,9 @@ public class TcpClient : IDisposable /// internal Status Status; + internal ulong LastACK; + internal ulong LastSEQ; + /// /// Assign clients dictionary. /// @@ -162,12 +165,27 @@ public bool Connect(Address dest, int destPort, int timeout = 5000) /// Close connection. /// /// Thrown on fatal error (contact support). - public void Close() + public bool Close() { if (clients.ContainsKey((uint)localPort) == true) { clients.Remove((uint)localPort); } + + if (Status == Status.OPENED) + { + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, 20, 0x11, 0xFAF0, 0); + OutgoingBuffer.AddPacket(packet); + NetworkStack.Update(); + + Status = Status.CLOSING; + + return WaitStatus(Status.CLOSED, 5000); + } + else + { + return true; + } } /// @@ -235,17 +253,38 @@ public byte[] Receive(ref EndPoint source) /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { - if (Status == Status.OPENING && packet.TCPFlags == 0x12) //SYN/ACK + LastACK = packet.AckNumber; + LastSEQ = packet.SequenceNumber; + + if (packet.RST) { - Status = Status.OPENED; + Status = Status.CLOSED; - Global.mDebugger.Send("TCP Connection established!"); + throw new Exception("TCP Connection Reseted!"); + } + else if (Status == Status.OPENED && packet.FIN) + { + Status = Status.CLOSING; + + SendAck(); + + //TODO: Send FIN Packet + } + else if (Status == Status.CLOSING && packet.FIN && packet.ACK) + { + Status = Status.CLOSED; - SendAck(packet); + SendAck(); + } + else if (Status == Status.OPENING && packet.SYN && packet.ACK) + { + Status = Status.OPENED; + + SendAck(); } else { - rxBuffer.Enqueue(packet); + throw new Exception("Unknown error on received TCP packet."); } } @@ -277,9 +316,12 @@ private bool WaitStatus(Status status, int timeout) return true; } - private void SendAck(TCPPacket responsepacket) + private void SendAck() { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, responsepacket.AckNumber, responsepacket.SequenceNumber + 1, 20, 0x10, 0xFAF0, 0); + LastACK = LastSEQ + 1; + LastSEQ = LastACK; + + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, 20, 0x10, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); } From 6950baa55e3008b39970969d16edfd1fcc187442 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 26 Apr 2021 16:28:39 +0200 Subject: [PATCH 086/314] FIN Fixes - Remove LastACK + LastSEQ for every packet - Fix LastSEQ overwitten by new LastACK --- .../Network/IPv4/TCP/TCPClient.cs | 17 +++++++++-------- .../Network/IPv4/TCP/TCPPacket.cs | 8 ++++---- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index ce8682c49a..4d03819863 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -61,8 +61,8 @@ public class TcpClient : IDisposable /// internal Status Status; - internal ulong LastACK; - internal ulong LastSEQ; + internal uint LastACK; + internal uint LastSEQ; /// /// Assign clients dictionary. @@ -253,9 +253,6 @@ public byte[] Receive(ref EndPoint source) /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { - LastACK = packet.AckNumber; - LastSEQ = packet.SequenceNumber; - if (packet.RST) { Status = Status.CLOSED; @@ -280,6 +277,9 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.OPENED; + LastACK = packet.AckNumber; + LastSEQ = packet.SequenceNumber; + SendAck(); } else @@ -318,10 +318,11 @@ private bool WaitStatus(Status status, int timeout) private void SendAck() { - LastACK = LastSEQ + 1; - LastSEQ = LastACK; + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastACK, LastSEQ + 1, 20, 0x10, 0xFAF0, 0); + + LastACK = packet.AckNumber; + LastSEQ = packet.SequenceNumber; - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, 20, 0x10, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); } diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 7df93ec93e..417efdda40 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -28,8 +28,8 @@ public class TCPPacket : IPPacket protected ushort sourcePort; protected ushort destinationPort; protected ushort optionLen; - protected ulong sequenceNumber; - protected ulong ackNumber; + protected uint sequenceNumber; + protected uint ackNumber; protected int headerLenght; protected int flags; protected int wsValue; @@ -263,11 +263,11 @@ internal ushort SourcePort { get { return sourcePort; } } - internal ulong AckNumber + internal uint AckNumber { get { return ackNumber; } } - internal ulong SequenceNumber + internal uint SequenceNumber { get { return sequenceNumber; } } From 10f39c758a78f72b9a1dc622347bd63fd3001366 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 26 Apr 2021 16:56:49 +0200 Subject: [PATCH 087/314] ACK fix after FIN / ACK in --- .../Network/IPv4/TCP/TCPClient.cs | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 4d03819863..33dd692ee1 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -61,7 +61,14 @@ public class TcpClient : IDisposable /// internal Status Status; + /// + /// Last Connection Acknowledgement number. + /// internal uint LastACK; + + /// + /// Last Connection Sequence number. + /// internal uint LastSEQ; /// @@ -263,6 +270,10 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.CLOSING; + var tmp = LastACK; + LastACK = LastSEQ; + LastSEQ = tmp + 1; + SendAck(); //TODO: Send FIN Packet @@ -277,8 +288,8 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.OPENED; - LastACK = packet.AckNumber; - LastSEQ = packet.SequenceNumber; + LastACK = packet.SequenceNumber; + LastSEQ = packet.AckNumber + 1; SendAck(); } @@ -296,6 +307,9 @@ public void Dispose() Close(); } + /// + /// Wait for new TCP connection status. + /// private bool WaitStatus(Status status, int timeout) { int second = 0; @@ -316,9 +330,12 @@ private bool WaitStatus(Status status, int timeout) return true; } + /// + /// Send acknowledgement packet + /// private void SendAck() { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastACK, LastSEQ + 1, 20, 0x10, 0xFAF0, 0); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, 20, 0x10, 0xFAF0, 0); LastACK = packet.AckNumber; LastSEQ = packet.SequenceNumber; From 58caba1b9c88f24e0a5c2933a74f4a23c1b8a1cf Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 26 Apr 2021 17:02:38 +0200 Subject: [PATCH 088/314] Code clean --- .../Network/IPv4/TCP/TCPClient.cs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 33dd692ee1..fac82e9653 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -270,11 +270,7 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.CLOSING; - var tmp = LastACK; - LastACK = LastSEQ; - LastSEQ = tmp + 1; - - SendAck(); + SendAck(LastACK, LastSEQ + 1); //TODO: Send FIN Packet } @@ -282,16 +278,13 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.CLOSED; - SendAck(); + SendAck(LastSEQ, LastACK); } else if (Status == Status.OPENING && packet.SYN && packet.ACK) { Status = Status.OPENED; - LastACK = packet.SequenceNumber; - LastSEQ = packet.AckNumber + 1; - - SendAck(); + SendAck(LastACK, LastSEQ + 1); } else { @@ -333,9 +326,9 @@ private bool WaitStatus(Status status, int timeout) /// /// Send acknowledgement packet /// - private void SendAck() + private void SendAck(uint lastSEQ, uint lastACK) { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, 20, 0x10, 0xFAF0, 0); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, lastSEQ, lastACK, 20, 0x10, 0xFAF0, 0); LastACK = packet.AckNumber; LastSEQ = packet.SequenceNumber; From 50f5d4f757c735fa894e30f99639893d9b135d84 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 26 Apr 2021 17:07:52 +0200 Subject: [PATCH 089/314] Forgot to set last values at first connection --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index fac82e9653..1e9a48294d 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -284,6 +284,9 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.OPENED; + LastACK = packet.AckNumber; + LastSEQ = packet.SequenceNumber; + SendAck(LastACK, LastSEQ + 1); } else From 90d0ed1b29fc53efb96142a8c22d7b0ce0621180 Mon Sep 17 00:00:00 2001 From: sketchedgrey <67015228+sketchedgrey@users.noreply.github.com> Date: Mon, 26 Apr 2021 12:05:13 -0400 Subject: [PATCH 090/314] Update Kernel.fs --- .../Cosmos.Templates.Kernel/content/Kernel-FSharp/Kernel.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Templates/Cosmos.Templates.Kernel/content/Kernel-FSharp/Kernel.fs b/source/Templates/Cosmos.Templates.Kernel/content/Kernel-FSharp/Kernel.fs index 9b5a66ccc6..0ad851aa7b 100644 --- a/source/Templates/Cosmos.Templates.Kernel/content/Kernel-FSharp/Kernel.fs +++ b/source/Templates/Cosmos.Templates.Kernel/content/Kernel-FSharp/Kernel.fs @@ -6,6 +6,7 @@ type Kernel() = inherit Cosmos.System.Kernel() override u.BeforeRun() = (Console.WriteLine("Cosmos booted successfully. Type a line of text to get it echoed back.");) override u.Run() = + //OS code here Console.Write("Input: "); let input = Console.ReadLine(); Console.Write("Text typed: "); From 9e27e5a99417a8b40e18c69ffb477d8f0b82a3cb Mon Sep 17 00:00:00 2001 From: sketchedgrey <67015228+sketchedgrey@users.noreply.github.com> Date: Mon, 26 Apr 2021 12:06:09 -0400 Subject: [PATCH 091/314] Update Kernel.vb --- .../Cosmos.Templates.Kernel/content/Kernel-VisualBasic/Kernel.vb | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Templates/Cosmos.Templates.Kernel/content/Kernel-VisualBasic/Kernel.vb b/source/Templates/Cosmos.Templates.Kernel/content/Kernel-VisualBasic/Kernel.vb index 5e70a4dc33..646561f521 100644 --- a/source/Templates/Cosmos.Templates.Kernel/content/Kernel-VisualBasic/Kernel.vb +++ b/source/Templates/Cosmos.Templates.Kernel/content/Kernel-VisualBasic/Kernel.vb @@ -12,6 +12,7 @@ Namespace CosmosKernel End Sub Protected Overrides Sub Run() + 'OS code here Console.Write("Input: ") Dim input = Console.ReadLine() Console.Write("Text typed: ") From 44f2940ff518da7365a9f21fa20081484745d1d7 Mon Sep 17 00:00:00 2001 From: sketchedgrey <67015228+sketchedgrey@users.noreply.github.com> Date: Mon, 26 Apr 2021 12:12:15 -0400 Subject: [PATCH 092/314] Update GettingStarted.md --- Docs/articles/GettingStarted.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Docs/articles/GettingStarted.md b/Docs/articles/GettingStarted.md index d5f5cd6ec1..2d5fc07213 100644 --- a/Docs/articles/GettingStarted.md +++ b/Docs/articles/GettingStarted.md @@ -27,8 +27,8 @@ so overwhelming like the dev kit. This article focuses on the user kit. ## Writing your first Operating System -Create a new project as you would any C# project, but select Cosmos as the -project type. +Create a new project as you would any C# project, but select Cosmos Kernel +(Previously CosmosBoot; same functionality) as the project type. ![](images/SNAG-0000.png) From 10f842794efcab3426facab54a0b62205f31f370 Mon Sep 17 00:00:00 2001 From: sketchedgrey <67015228+sketchedgrey@users.noreply.github.com> Date: Mon, 26 Apr 2021 12:14:07 -0400 Subject: [PATCH 093/314] Update Kernel.cs --- .../Cosmos.Templates.Kernel/content/Kernel-CSharp/Kernel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Templates/Cosmos.Templates.Kernel/content/Kernel-CSharp/Kernel.cs b/source/Templates/Cosmos.Templates.Kernel/content/Kernel-CSharp/Kernel.cs index a63db855e7..19fee75eb9 100644 --- a/source/Templates/Cosmos.Templates.Kernel/content/Kernel-CSharp/Kernel.cs +++ b/source/Templates/Cosmos.Templates.Kernel/content/Kernel-CSharp/Kernel.cs @@ -14,6 +14,7 @@ protected override void BeforeRun() protected override void Run() { + //OS code here, the code here echoes input. Replace with your own functions. Console.Write("Input: "); var input = Console.ReadLine(); Console.Write("Text typed: "); From 03de1e65ff96da4e06580a7dac0a3ce045b57965 Mon Sep 17 00:00:00 2001 From: sketchedgrey <67015228+sketchedgrey@users.noreply.github.com> Date: Mon, 26 Apr 2021 12:25:30 -0400 Subject: [PATCH 094/314] Update Kernel.fs --- .../Cosmos.Templates.Kernel/content/Kernel-FSharp/Kernel.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Templates/Cosmos.Templates.Kernel/content/Kernel-FSharp/Kernel.fs b/source/Templates/Cosmos.Templates.Kernel/content/Kernel-FSharp/Kernel.fs index 0ad851aa7b..f5284efbca 100644 --- a/source/Templates/Cosmos.Templates.Kernel/content/Kernel-FSharp/Kernel.fs +++ b/source/Templates/Cosmos.Templates.Kernel/content/Kernel-FSharp/Kernel.fs @@ -6,7 +6,7 @@ type Kernel() = inherit Cosmos.System.Kernel() override u.BeforeRun() = (Console.WriteLine("Cosmos booted successfully. Type a line of text to get it echoed back.");) override u.Run() = - //OS code here + //OS code here, current code echoes input. Replace with your own functions. Console.Write("Input: "); let input = Console.ReadLine(); Console.Write("Text typed: "); From 2d7c504bad098a28aabc258b468397f014eadcf8 Mon Sep 17 00:00:00 2001 From: sketchedgrey <67015228+sketchedgrey@users.noreply.github.com> Date: Mon, 26 Apr 2021 12:25:52 -0400 Subject: [PATCH 095/314] Update Kernel.vb --- .../content/Kernel-VisualBasic/Kernel.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Templates/Cosmos.Templates.Kernel/content/Kernel-VisualBasic/Kernel.vb b/source/Templates/Cosmos.Templates.Kernel/content/Kernel-VisualBasic/Kernel.vb index 646561f521..81b28550ea 100644 --- a/source/Templates/Cosmos.Templates.Kernel/content/Kernel-VisualBasic/Kernel.vb +++ b/source/Templates/Cosmos.Templates.Kernel/content/Kernel-VisualBasic/Kernel.vb @@ -12,7 +12,7 @@ Namespace CosmosKernel End Sub Protected Overrides Sub Run() - 'OS code here + 'OS code here, current code echoes input. Replace with your own functions. Console.Write("Input: ") Dim input = Console.ReadLine() Console.Write("Text typed: ") From 4bc96076235c5b896b23859b84dd875c0b914f31 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 27 Apr 2021 15:39:59 +0200 Subject: [PATCH 096/314] TCP FIN / ACK in fix --- .../Network/IPv4/TCP/TCPClient.cs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 1e9a48294d..e2647c0979 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -174,11 +174,6 @@ public bool Connect(Address dest, int destPort, int timeout = 5000) /// Thrown on fatal error (contact support). public bool Close() { - if (clients.ContainsKey((uint)localPort) == true) - { - clients.Remove((uint)localPort); - } - if (Status == Status.OPENED) { var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, 20, 0x11, 0xFAF0, 0); @@ -187,12 +182,18 @@ public bool Close() Status = Status.CLOSING; - return WaitStatus(Status.CLOSED, 5000); + if (WaitStatus(Status.CLOSED, 5000) == false) + { + return false; + } } - else + + if (clients.ContainsKey((uint)localPort) == true) { - return true; + clients.Remove((uint)localPort); } + + return true; } /// @@ -289,10 +290,6 @@ internal void ReceiveData(TCPPacket packet) SendAck(LastACK, LastSEQ + 1); } - else - { - throw new Exception("Unknown error on received TCP packet."); - } } /// From e50a38e9d257067149e62695c6437754fa625562 Mon Sep 17 00:00:00 2001 From: Quajak Date: Wed, 28 Apr 2021 09:08:25 +0200 Subject: [PATCH 097/314] Expand list of exempt labels --- .github/workflows/stale.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f7fcf7251b..59852f5ec3 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,4 +17,5 @@ jobs: stale-pr-message: 'As this pull request has received no new activity, it has been marked as stale' stale-issue-label: 'no-issue-activity' stale-pr-label: 'no-pr-activity' - exempt-issue-labels: 'Up for Grabs' + exempt-issue-labels: 'Up for Grabs,Blocked' + exempt-pr-labels: 'Work in progress' From a1df0452ba3a0dca8e9f2bb30bd94b2c6f987fed Mon Sep 17 00:00:00 2001 From: KM198912 <55886806+KM198912@users.noreply.github.com> Date: Wed, 28 Apr 2021 13:37:51 +0200 Subject: [PATCH 098/314] Update PS2Controller.cs Same PR as before just fixing up with master --- source/Cosmos.HAL2/PS2Controller.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/Cosmos.HAL2/PS2Controller.cs b/source/Cosmos.HAL2/PS2Controller.cs index ab450a56e7..00b6511bd9 100644 --- a/source/Cosmos.HAL2/PS2Controller.cs +++ b/source/Cosmos.HAL2/PS2Controller.cs @@ -198,11 +198,8 @@ private void IdentifyDevice(byte aPort, out Device aDevice) */ else if (xFirstByte == 0xAB && ReadDataWithTimeout(ref xSecondByte)) { - // TODO: replace xTest with (xSecondByte == 0x41 || xSecondByte == 0xC1) - // when the stack corruption detection works better for complex conditions - var xTest = (xSecondByte == 0x41 || xSecondByte == 0xC1); - if (xTest && aPort == 1) + if ((xSecondByte == 0x41 || xSecondByte == 0xC1) && aPort == 1) { var xDevice = new PS2Keyboard(aPort); xDevice.Initialize(); @@ -239,7 +236,10 @@ private void IdentifyDevice(byte aPort, out Device aDevice) mDebugger.SendInternal("(PS/2 Controller) Device detection failed:"); mDebugger.SendInternal("First Byte: " + xFirstByte); mDebugger.SendInternal("Second Byte: " + xSecondByte); - throw new Exception("(PS/2 Controller) PS/2 device not supported"); + Console.WriteLine("(PS/2 Controller) Device detection failed."); + Console.WriteLine("This is usually Fine for USB to PS / 2 Emulation"); + Console.WriteLine("Press any key to Resume (Good Luck)"); + Console.ReadLine(); } } else From 91d40e90d925eb41b35e3d315cbdb283f88f6be1 Mon Sep 17 00:00:00 2001 From: KM198912 <55886806+KM198912@users.noreply.github.com> Date: Wed, 28 Apr 2021 15:16:17 +0200 Subject: [PATCH 099/314] Update PS2Controller.cs --- source/Cosmos.HAL2/PS2Controller.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/Cosmos.HAL2/PS2Controller.cs b/source/Cosmos.HAL2/PS2Controller.cs index 00b6511bd9..6c7702e979 100644 --- a/source/Cosmos.HAL2/PS2Controller.cs +++ b/source/Cosmos.HAL2/PS2Controller.cs @@ -198,8 +198,11 @@ private void IdentifyDevice(byte aPort, out Device aDevice) */ else if (xFirstByte == 0xAB && ReadDataWithTimeout(ref xSecondByte)) { + // TODO: replace xTest with (xSecondByte == 0x41 || xSecondByte == 0xC1) + // when the stack corruption detection works better for complex conditions + var xTest = (xSecondByte == 0x41 || xSecondByte == 0xC1); - if ((xSecondByte == 0x41 || xSecondByte == 0xC1) && aPort == 1) + if (xTest && aPort == 1) { var xDevice = new PS2Keyboard(aPort); xDevice.Initialize(); From 234ca75945e6d58c8f9f4b21e65528ed30f2cae3 Mon Sep 17 00:00:00 2001 From: Quajak Date: Thu, 29 Apr 2021 22:29:09 +0200 Subject: [PATCH 100/314] Improved stale action Added additional label and exempt all milestone/assigned issues/prs --- .github/workflows/stale.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 59852f5ec3..e823b432b5 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,5 +17,7 @@ jobs: stale-pr-message: 'As this pull request has received no new activity, it has been marked as stale' stale-issue-label: 'no-issue-activity' stale-pr-label: 'no-pr-activity' - exempt-issue-labels: 'Up for Grabs,Blocked' + exempt-issue-labels: 'Up for Grabs,Blocked,PR submitted' exempt-pr-labels: 'Work in progress' + exempt-all-milestones: true + exempt-all-assignees: true From f30d9e94c38ae19443617c3debf619f6c10d1d97 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 30 Apr 2021 16:51:43 +0200 Subject: [PATCH 101/314] Update seq / ack nb after received FIN / ACK --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index e2647c0979..c8b9bfa162 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -279,7 +279,7 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.CLOSED; - SendAck(LastSEQ, LastACK); + SendAck(LastACK, LastSEQ + 1); } else if (Status == Status.OPENING && packet.SYN && packet.ACK) { From a9217c91e64cc9ce564bf69f586d342fd02d57af Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 30 Apr 2021 17:04:58 +0200 Subject: [PATCH 102/314] Forgot to update LastACK & LastSEQ with received FIN / ACK packet --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index c8b9bfa162..07166b3899 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -279,6 +279,9 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.CLOSED; + LastACK = packet.AckNumber; + LastSEQ = packet.SequenceNumber; + SendAck(LastACK, LastSEQ + 1); } else if (Status == Status.OPENING && packet.SYN && packet.ACK) From b817201600ffb39dd11aa5ef989f97d645f31bdf Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Sun, 2 May 2021 10:36:12 -0400 Subject: [PATCH 103/314] Update AtaPio.cs --- source/Cosmos.HAL2/BlockDevice/AtaPio.cs | 28 +++++++++++++----------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs b/source/Cosmos.HAL2/BlockDevice/AtaPio.cs index 70d03bd2d8..f7e33315cb 100644 --- a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs +++ b/source/Cosmos.HAL2/BlockDevice/AtaPio.cs @@ -250,20 +250,22 @@ public Status SendCmd(Cmd aCmd, bool aThrowOnError) return xStatus; } - protected string GetString(UInt16[] aBuffer, int aIndexStart, int aStringLength) + protected string GetString(ushort[] aBuffer, int aIndexStart, int aStringLength) { - // Would be nice to convert to byte[] and use - // new string(ASCIIEncoding.ASCII.GetChars(xBytes)); - // But it requires some code Cosmos doesnt support yet - var xChars = new char[aStringLength]; - for (int i = 0; i < aStringLength / 2; i++) - { - UInt16 xChar = aBuffer[aIndexStart + i]; - xChars[i * 2] = (char)(xChar >> 8); - xChars[i * 2 + 1] = (char)xChar; - } - return new string(xChars); - } + //Convert ushort[] to byte[] + var array = new List(); + for (int i = aIndexStart; i < aIndexStart + (aStringLength/2); i++) + { + var item = aBuffer[i]; + var bytes = BitConverter.GetBytes(item); + for (int i2 = 1; i2 >= 0; i2--) + { + array.Add(bytes[i2]); + } + } + //Convert byte[] to string + return Encoding.ASCII.GetString(array.ToArray()); + } public bool LBA48Bit; protected void InitDrive() From d17964ec4b0b6ab52322eb5ce1f1e4ca455e8e36 Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Sun, 2 May 2021 11:16:53 -0400 Subject: [PATCH 104/314] Resolve the review --- source/Cosmos.HAL2/BlockDevice/AtaPio.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs b/source/Cosmos.HAL2/BlockDevice/AtaPio.cs index f7e33315cb..2f92bd9674 100644 --- a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs +++ b/source/Cosmos.HAL2/BlockDevice/AtaPio.cs @@ -253,15 +253,14 @@ public Status SendCmd(Cmd aCmd, bool aThrowOnError) protected string GetString(ushort[] aBuffer, int aIndexStart, int aStringLength) { //Convert ushort[] to byte[] - var array = new List(); + byte[] array = new byte[aStringLength / 2]; + int counter = 0; for (int i = aIndexStart; i < aIndexStart + (aStringLength/2); i++) { var item = aBuffer[i]; var bytes = BitConverter.GetBytes(item); - for (int i2 = 1; i2 >= 0; i2--) - { - array.Add(bytes[i2]); - } + array[counter++] = bytes[1]; + array[counter++] = bytes[0]; } //Convert byte[] to string return Encoding.ASCII.GetString(array.ToArray()); From 65a754c12a3d5189e6f4e4b6c5912b1937132b8a Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Sun, 2 May 2021 11:51:22 -0400 Subject: [PATCH 105/314] Fix build error --- source/Cosmos.HAL2/BlockDevice/AtaPio.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs b/source/Cosmos.HAL2/BlockDevice/AtaPio.cs index 2f92bd9674..142f9564b6 100644 --- a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs +++ b/source/Cosmos.HAL2/BlockDevice/AtaPio.cs @@ -263,7 +263,7 @@ protected string GetString(ushort[] aBuffer, int aIndexStart, int aStringLength) array[counter++] = bytes[0]; } //Convert byte[] to string - return Encoding.ASCII.GetString(array.ToArray()); + return Encoding.ASCII.GetString(array); } public bool LBA48Bit; From 505883f742beebfcb59d6cafa298bd30f6719c4a Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Sun, 2 May 2021 13:09:18 -0400 Subject: [PATCH 106/314] Fix build --- Setup/Cosmos.iss | 12 ++++++------ source/Cosmos.HAL2/BlockDevice/AtaPio.cs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Setup/Cosmos.iss b/Setup/Cosmos.iss index 75ed8c4d01..75209b5efb 100644 --- a/Setup/Cosmos.iss +++ b/Setup/Cosmos.iss @@ -151,17 +151,17 @@ UseRelativePaths=True Filename: "{app}\Build\Tools\nuget.exe"; Parameters: "sources Remove -Name ""Cosmos Local Package Feed"""; WorkingDir: "{app}"; Description: "Uninstall Kernel Packages"; StatusMsg: "Uninstalling Kernel Packages" Filename: "{app}\Build\Tools\nuget.exe"; Parameters: "sources Add -Name ""Cosmos Local Package Feed"" -Source ""{app}\packages\\"""; WorkingDir: "{app}"; Description: "Install Kernel Packages"; StatusMsg: "Installing Kernel Packages" -Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.ProjectSystem"; Description: "Remove Cosmos Project System"; StatusMsg: "Removing Visual Studio Extension: Cosmos Project System" -Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.DebugEngine"; Description: "Remove Cosmos Debug Engine"; StatusMsg: "Removing Visual Studio Extension: Cosmos Debug Engine" +; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.ProjectSystem"; Description: "Remove Cosmos Project System"; StatusMsg: "Removing Visual Studio Extension: Cosmos Project System" +; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.DebugEngine"; Description: "Remove Cosmos Debug Engine"; StatusMsg: "Removing Visual Studio Extension: Cosmos Debug Engine" -Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q Cosmos.VS.DebugEngine.vsix"; WorkingDir: "{app}\VSIX\"; Description: "Install Cosmos Debug Engine"; StatusMsg: "Installing Visual Studio Extension: Cosmos Debug Engine" -Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q Cosmos.VS.ProjectSystem.vsix"; WorkingDir: "{app}\VSIX\"; Description: "Install Cosmos Project System"; StatusMsg: "Installing Visual Studio Extension: Cosmos Project System" +; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q Cosmos.VS.DebugEngine.vsix"; WorkingDir: "{app}\VSIX\"; Description: "Install Cosmos Debug Engine"; StatusMsg: "Installing Visual Studio Extension: Cosmos Debug Engine" +; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q Cosmos.VS.ProjectSystem.vsix"; WorkingDir: "{app}\VSIX\"; Description: "Install Cosmos Project System"; StatusMsg: "Installing Visual Studio Extension: Cosmos Project System" [UninstallRun] Filename: "{app}\Build\Tools\nuget.exe"; Parameters: "sources Remove -Name ""Cosmos Local Package Feed"""; WorkingDir: "{app}"; StatusMsg: "Uninstalling Kernel Packages" -Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.ProjectSystem"; StatusMsg: "Removing Visual Studio Extension: Cosmos Project System" -Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.DebugEngine"; StatusMsg: "Removing Visual Studio Extension: Cosmos Debug Engine" +; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.ProjectSystem"; StatusMsg: "Removing Visual Studio Extension: Cosmos Project System" +; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.DebugEngine"; StatusMsg: "Removing Visual Studio Extension: Cosmos Debug Engine" [Code] function IsAppRunning(const FileName: string): Boolean; diff --git a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs b/source/Cosmos.HAL2/BlockDevice/AtaPio.cs index 142f9564b6..b69757ccdc 100644 --- a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs +++ b/source/Cosmos.HAL2/BlockDevice/AtaPio.cs @@ -253,9 +253,9 @@ public Status SendCmd(Cmd aCmd, bool aThrowOnError) protected string GetString(ushort[] aBuffer, int aIndexStart, int aStringLength) { //Convert ushort[] to byte[] - byte[] array = new byte[aStringLength / 2]; + byte[] array = new byte[aStringLength]; int counter = 0; - for (int i = aIndexStart; i < aIndexStart + (aStringLength/2); i++) + for (int i = aIndexStart; i < aIndexStart + (aStringLength / 2); i++) { var item = aBuffer[i]; var bytes = BitConverter.GetBytes(item); From d83d2eacfa5be085b7d2469a5230f847ad8ecba2 Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Sun, 2 May 2021 13:42:52 -0400 Subject: [PATCH 107/314] Update Cosmos.iss --- Setup/Cosmos.iss | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Setup/Cosmos.iss b/Setup/Cosmos.iss index 75209b5efb..75ed8c4d01 100644 --- a/Setup/Cosmos.iss +++ b/Setup/Cosmos.iss @@ -151,17 +151,17 @@ UseRelativePaths=True Filename: "{app}\Build\Tools\nuget.exe"; Parameters: "sources Remove -Name ""Cosmos Local Package Feed"""; WorkingDir: "{app}"; Description: "Uninstall Kernel Packages"; StatusMsg: "Uninstalling Kernel Packages" Filename: "{app}\Build\Tools\nuget.exe"; Parameters: "sources Add -Name ""Cosmos Local Package Feed"" -Source ""{app}\packages\\"""; WorkingDir: "{app}"; Description: "Install Kernel Packages"; StatusMsg: "Installing Kernel Packages" -; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.ProjectSystem"; Description: "Remove Cosmos Project System"; StatusMsg: "Removing Visual Studio Extension: Cosmos Project System" -; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.DebugEngine"; Description: "Remove Cosmos Debug Engine"; StatusMsg: "Removing Visual Studio Extension: Cosmos Debug Engine" +Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.ProjectSystem"; Description: "Remove Cosmos Project System"; StatusMsg: "Removing Visual Studio Extension: Cosmos Project System" +Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.DebugEngine"; Description: "Remove Cosmos Debug Engine"; StatusMsg: "Removing Visual Studio Extension: Cosmos Debug Engine" -; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q Cosmos.VS.DebugEngine.vsix"; WorkingDir: "{app}\VSIX\"; Description: "Install Cosmos Debug Engine"; StatusMsg: "Installing Visual Studio Extension: Cosmos Debug Engine" -; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q Cosmos.VS.ProjectSystem.vsix"; WorkingDir: "{app}\VSIX\"; Description: "Install Cosmos Project System"; StatusMsg: "Installing Visual Studio Extension: Cosmos Project System" +Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q Cosmos.VS.DebugEngine.vsix"; WorkingDir: "{app}\VSIX\"; Description: "Install Cosmos Debug Engine"; StatusMsg: "Installing Visual Studio Extension: Cosmos Debug Engine" +Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q Cosmos.VS.ProjectSystem.vsix"; WorkingDir: "{app}\VSIX\"; Description: "Install Cosmos Project System"; StatusMsg: "Installing Visual Studio Extension: Cosmos Project System" [UninstallRun] Filename: "{app}\Build\Tools\nuget.exe"; Parameters: "sources Remove -Name ""Cosmos Local Package Feed"""; WorkingDir: "{app}"; StatusMsg: "Uninstalling Kernel Packages" -; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.ProjectSystem"; StatusMsg: "Removing Visual Studio Extension: Cosmos Project System" -; Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.DebugEngine"; StatusMsg: "Removing Visual Studio Extension: Cosmos Debug Engine" +Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.ProjectSystem"; StatusMsg: "Removing Visual Studio Extension: Cosmos Project System" +Filename: "{app}\Build\Tools\VSIXBootstrapper.exe"; Parameters: "/q /u:Cosmos.VS.DebugEngine"; StatusMsg: "Removing Visual Studio Extension: Cosmos Debug Engine" [Code] function IsAppRunning(const FileName: string): Boolean; From 215f107b87754671f2f1943751c456f80013ac5a Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 3 May 2021 13:03:53 +0200 Subject: [PATCH 108/314] Parse TCP packet with data fix + PSH out --- .../Network/IPv4/TCP/TCPClient.cs | 43 +++++++------------ .../Network/IPv4/TCP/TCPPacket.cs | 42 +++++++++--------- 2 files changed, 38 insertions(+), 47 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 07166b3899..76a5d92407 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -20,6 +20,7 @@ public enum Status { OPENED, OPENING, //SYN sent or received + DATASENT, CLOSED, CLOSING //FIN sent or received } @@ -204,31 +205,20 @@ public bool Close() /// Thrown on fatal error (contact support). /// Thrown if data array length is greater than Int32.MaxValue. /// Thrown on IO error. - public void Send(byte[] data) + public bool Send(byte[] data) { if ((destination == null) || (destinationPort == 0)) { throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); } - Send(data, destination, destinationPort); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, (ushort)(20 + data.Length), 0x18, 0xFAF0, 0, (ushort)data.Length, data); + OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - } - /// - /// Send data. - /// - /// Data array. - /// Destination address. - /// Destination port. - /// Thrown on fatal error (contact support). - /// Thrown if data array length is greater than Int32.MaxValue. - /// Thrown on IO error. - public void Send(byte[] data, Address dest, int destPort) - { - Address source = IPConfig.FindNetwork(dest); - var packet = new TCPPacket(); - OutgoingBuffer.AddPacket(packet); + Status = Status.DATASENT; + + return WaitStatus(Status.OPENED, 5000); } /// @@ -267,10 +257,13 @@ internal void ReceiveData(TCPPacket packet) throw new Exception("TCP Connection Reseted!"); } - else if (Status == Status.OPENED && packet.FIN) + + LastACK = packet.AckNumber; + LastSEQ = packet.SequenceNumber; + + if (Status == Status.OPENED && packet.FIN) { Status = Status.CLOSING; - SendAck(LastACK, LastSEQ + 1); //TODO: Send FIN Packet @@ -278,21 +271,17 @@ internal void ReceiveData(TCPPacket packet) else if (Status == Status.CLOSING && packet.FIN && packet.ACK) { Status = Status.CLOSED; - - LastACK = packet.AckNumber; - LastSEQ = packet.SequenceNumber; - SendAck(LastACK, LastSEQ + 1); } else if (Status == Status.OPENING && packet.SYN && packet.ACK) { Status = Status.OPENED; - - LastACK = packet.AckNumber; - LastSEQ = packet.SequenceNumber; - SendAck(LastACK, LastSEQ + 1); } + else if (Status == Status.DATASENT && packet.ACK) + { + Status = Status.OPENED; + } } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 417efdda40..1f9dca7eb0 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -174,39 +174,41 @@ protected override void InitFields() PSH = (RawData[47] & (1 << 3)) != 0; RST = (RawData[47] & (1 << 2)) != 0; - //options parsing - if (RawData.Length <= DataOffset + 20) + if (RawData.Length == (DataOffset + headerLenght)) //no data { - return; - } - if (RawData[DataOffset + 20] != 0) - { - options = new List(); - - for (int i = 0; i < RawData.Length - (DataOffset + 20); i++) + if (headerLenght > 20) //options { - var option = new TCPOption(); - option.Kind = RawData[DataOffset + 20 + i]; + options = new List(); - if (option.Kind != 1) //NOP + for (int i = 0; i < RawData.Length - (DataOffset + 20); i++) { - option.Length = RawData[DataOffset + 20 + i + 1]; + var option = new TCPOption(); + option.Kind = RawData[DataOffset + 20 + i]; - if (option.Length != 2) + if (option.Kind != 1) //NOP { - option.Data = new byte[option.Length - 2]; - for (int j = 0; j < option.Length - 2; j++) + option.Length = RawData[DataOffset + 20 + i + 1]; + + if (option.Length != 2) { - option.Data[j] = RawData[DataOffset + 20 + i + 2 + j]; + option.Data = new byte[option.Length - 2]; + for (int j = 0; j < option.Length - 2; j++) + { + option.Data[j] = RawData[DataOffset + 20 + i + 2 + j]; + } } - } - options.Add(option); + options.Add(option); - i += option.Length - 1; + i += option.Length - 1; + } } } } + else + { + //TODO: Parse data + } } internal void AddOption(TCPOption option) From 33befa1d65459b14aa6cf6f4a8466234b73ee5aa Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 3 May 2021 13:08:02 +0200 Subject: [PATCH 109/314] Replace bool by exceptions --- .../Network/IPv4/TCP/TCPClient.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 76a5d92407..3124ec0347 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -142,7 +142,7 @@ public TcpClient(Address dest, int destPort) /// /// Destination address. /// Destination port. - public bool Connect(Address dest, int destPort, int timeout = 5000) + public void Connect(Address dest, int destPort, int timeout = 5000) { destination = dest; destinationPort = destPort; @@ -166,14 +166,17 @@ public bool Connect(Address dest, int destPort, int timeout = 5000) Status = Status.OPENING; - return WaitStatus(Status.OPENED, timeout); + if (WaitStatus(Status.OPENED, timeout) == false) + { + throw new Exception("Failed to open TCP connection!"); + } } /// /// Close connection. /// /// Thrown on fatal error (contact support). - public bool Close() + public void Close() { if (Status == Status.OPENED) { @@ -185,7 +188,7 @@ public bool Close() if (WaitStatus(Status.CLOSED, 5000) == false) { - return false; + throw new Exception("Failed to close TCP connection!"); } } @@ -193,8 +196,6 @@ public bool Close() { clients.Remove((uint)localPort); } - - return true; } /// @@ -205,7 +206,7 @@ public bool Close() /// Thrown on fatal error (contact support). /// Thrown if data array length is greater than Int32.MaxValue. /// Thrown on IO error. - public bool Send(byte[] data) + public void Send(byte[] data) { if ((destination == null) || (destinationPort == 0)) { @@ -218,7 +219,10 @@ public bool Send(byte[] data) Status = Status.DATASENT; - return WaitStatus(Status.OPENED, 5000); + if (WaitStatus(Status.OPENED, 5000) == false) + { + throw new Exception("Failed to send TCP data!"); + } } /// From bf50ae811d20b6d16455541e46bbf0f4b41fedfd Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 3 May 2021 13:13:51 +0200 Subject: [PATCH 110/314] Header length = 20 if data --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 3124ec0347..122596b7b4 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -213,7 +213,7 @@ public void Send(byte[] data) throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); } - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, (ushort)(20 + data.Length), 0x18, 0xFAF0, 0, (ushort)data.Length, data); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, 20, 0x18, 0xFAF0, 0, (ushort)data.Length, data); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); From 771cae2a7d14d4fe19a8cc2540ae6a5cc18623de Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 3 May 2021 14:02:22 +0200 Subject: [PATCH 111/314] TCP fix after DATASENT / ACK in --- .../Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 122596b7b4..caa9f072fa 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -262,9 +262,6 @@ internal void ReceiveData(TCPPacket packet) throw new Exception("TCP Connection Reseted!"); } - LastACK = packet.AckNumber; - LastSEQ = packet.SequenceNumber; - if (Status == Status.OPENED && packet.FIN) { Status = Status.CLOSING; @@ -275,16 +272,27 @@ internal void ReceiveData(TCPPacket packet) else if (Status == Status.CLOSING && packet.FIN && packet.ACK) { Status = Status.CLOSED; + + LastACK = packet.AckNumber; + LastSEQ = packet.SequenceNumber; + SendAck(LastACK, LastSEQ + 1); } else if (Status == Status.OPENING && packet.SYN && packet.ACK) { Status = Status.OPENED; + + LastACK = packet.AckNumber; + LastSEQ = packet.SequenceNumber; + SendAck(LastACK, LastSEQ + 1); } else if (Status == Status.DATASENT && packet.ACK) { Status = Status.OPENED; + + LastACK = packet.SequenceNumber; + LastSEQ = packet.AckNumber; } } From fa1a2b425d791297b0e8c5981c423438823c0771 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 3 May 2021 14:18:02 +0200 Subject: [PATCH 112/314] Receive packets (PSH / ACK in) - Add Receive + NonBlockingReceive - TCP_Data getter - enqueue PSH / ACK packet in rxBuffer queue --- .../Network/IPv4/TCP/TCPClient.cs | 28 +++++++++++++++++-- .../Network/IPv4/TCP/TCPPacket.cs | 24 ++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index caa9f072fa..0e57975937 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -233,7 +233,16 @@ public void Send(byte[] data) /// Thrown on fatal error (contact support). public byte[] NonBlockingReceive(ref EndPoint source) { - throw new NotImplementedException(); + if (rxBuffer.Count < 1) + { + return null; + } + + var packet = new TCPPacket(rxBuffer.Dequeue().RawData); + source.address = packet.SourceIP; + source.port = packet.SourcePort; + + return packet.TCP_Data; } /// @@ -244,7 +253,13 @@ public byte[] NonBlockingReceive(ref EndPoint source) /// Thrown on fatal error (contact support). public byte[] Receive(ref EndPoint source) { - throw new NotImplementedException(); + while (rxBuffer.Count < 1); + + var packet = new TCPPacket(rxBuffer.Dequeue().RawData); + source.address = packet.SourceIP; + source.port = packet.SourcePort; + + return packet.TCP_Data; } /// @@ -294,6 +309,15 @@ internal void ReceiveData(TCPPacket packet) LastACK = packet.SequenceNumber; LastSEQ = packet.AckNumber; } + else if (Status == Status.OPENED && packet.PSH && packet.ACK) + { + LastACK = packet.AckNumber; + LastSEQ = packet.SequenceNumber; + + rxBuffer.Enqueue(packet); + + SendAck(LastACK, LastSEQ + 1); + } } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 1f9dca7eb0..b16adc196c 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -278,6 +278,30 @@ internal int TCPFlags get { return flags; } } + /// + /// Get TCP data lenght. + /// + public ushort TCP_DataLength => (ushort)(RawData.Length - (DataOffset + headerLenght)); + + /// + /// Get TCP data. + /// + /// Thrown on fatal error (contact support). + internal byte[] TCP_Data + { + get + { + byte[] data = new byte[TCP_DataLength]; + + for (int b = 0; b < data.Length; b++) + { + data[b] = RawData[DataOffset + headerLenght + b]; + } + + return data; + } + } + public override string ToString() { return "TCP Packet Src=" + SourceIP + ":" + sourcePort + ", Dest=" + DestinationIP + ":" + destinationPort; From 7d0c80f5a7128b04a8a0c5c554e575f5de7e731a Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 3 May 2021 15:58:49 +0200 Subject: [PATCH 113/314] Correct headerLenght parsing + SYN in --- .../Network/IPv4/TCP/TCPClient.cs | 25 +++++++++++++------ .../Network/IPv4/TCP/TCPPacket.cs | 2 +- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 0e57975937..4d2b34df11 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -270,14 +270,12 @@ public byte[] Receive(ref EndPoint source) /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { - if (packet.RST) + if (Status == Status.CLOSED && packet.SYN) { - Status = Status.CLOSED; - - throw new Exception("TCP Connection Reseted!"); + Status = Status.OPENING; + SendAck(LastACK, LastSEQ + 1, 0x12); //SYN / ACK } - - if (Status == Status.OPENED && packet.FIN) + else if (Status == Status.OPENED && packet.FIN) { Status = Status.CLOSING; SendAck(LastACK, LastSEQ + 1); @@ -302,6 +300,17 @@ internal void ReceiveData(TCPPacket packet) SendAck(LastACK, LastSEQ + 1); } + if (Status == Status.OPENING && packet.ACK) + { + Status = Status.OPENED; + + LastACK = packet.AckNumber; + LastSEQ = packet.SequenceNumber; + } + else if (Status == Status.OPENING && packet.RST && packet.ACK) + { + throw new Exception("Connection rejected!"); + } else if (Status == Status.DATASENT && packet.ACK) { Status = Status.OPENED; @@ -354,9 +363,9 @@ private bool WaitStatus(Status status, int timeout) /// /// Send acknowledgement packet /// - private void SendAck(uint lastSEQ, uint lastACK) + private void SendAck(uint lastSEQ, uint lastACK, ushort flag = 0x10) { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, lastSEQ, lastACK, 20, 0x10, 0xFAF0, 0); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, lastSEQ, lastACK, 20, flag, 0xFAF0, 0); LastACK = packet.AckNumber; LastSEQ = packet.SequenceNumber; diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index b16adc196c..30feef5685 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -162,7 +162,7 @@ protected override void InitFields() destinationPort = (ushort)((RawData[DataOffset + 2] << 8) | RawData[DataOffset + 3]); sequenceNumber = (uint)((RawData[DataOffset + 4] << 24) | (RawData[DataOffset + 5] << 16) | (RawData[DataOffset + 6] << 8) | RawData[DataOffset + 7]); ackNumber = (uint)((RawData[DataOffset + 8] << 24) | (RawData[DataOffset + 9] << 16) | (RawData[DataOffset + 10] << 8) | RawData[DataOffset + 11]); - headerLenght = RawData[DataOffset + 12]; + headerLenght = (RawData[DataOffset + 12] >> 4) * 4; flags = RawData[DataOffset + 13]; wsValue = (ushort)((RawData[DataOffset + 14] << 8) | RawData[DataOffset + 15]); checksum = (ushort)((RawData[DataOffset + 16] << 8) | RawData[DataOffset + 17]); From 88deefa03680d0d6c5766be421da001be0142966 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 3 May 2021 16:10:36 +0200 Subject: [PATCH 114/314] Add RST case --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 4d2b34df11..68ffce1f30 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -327,6 +327,10 @@ internal void ReceiveData(TCPPacket packet) SendAck(LastACK, LastSEQ + 1); } + else if (packet.RST) + { + throw new Exception("Connection reseted!"); + } } /// From b6fd4a1fd2b8f89ae190d82ea1cb382c6f912aee Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 3 May 2021 16:15:05 +0200 Subject: [PATCH 115/314] Find source if new TCP connection --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 68ffce1f30..c4db8283ca 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -273,6 +273,9 @@ internal void ReceiveData(TCPPacket packet) if (Status == Status.CLOSED && packet.SYN) { Status = Status.OPENING; + + source = IPConfig.FindNetwork(packet.SourceIP); + SendAck(LastACK, LastSEQ + 1, 0x12); //SYN / ACK } else if (Status == Status.OPENED && packet.FIN) From 2235b64f850419a320da9a328c9a6df9bfd43109 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 3 May 2021 16:35:31 +0200 Subject: [PATCH 116/314] Add checksum computation for incoming packets (disabled for now) --- .../Network/IPv4/TCP/TCPPacket.cs | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 30feef5685..b6942e9418 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -33,7 +33,7 @@ public class TCPPacket : IPPacket protected int headerLenght; protected int flags; protected int wsValue; - protected int checksum; + protected ushort checksum; protected int urgentPointer; protected List options = null; @@ -50,10 +50,17 @@ internal static void TCPHandler(byte[] packetData) Global.mDebugger.Send("[Received] TCP packet from " + packet.SourceIP.ToString() + ":" + packet.SourcePort.ToString()); - var receiver = TcpClient.GetClient(packet.DestinationPort); - if (receiver != null) + if (packet.CheckCRC()) { - receiver.ReceiveData(packet); + var receiver = TcpClient.GetClient(packet.DestinationPort); + if (receiver != null) + { + receiver.ReceiveData(packet); + } + } + else + { + Global.mDebugger.Send("Checksum incorrect! Packet passed."); } } @@ -257,6 +264,26 @@ internal byte[] MakeHeader() return header; } + /// + /// Check TCP Checksum + /// + /// True if checksum correct, False otherwise. + public bool CheckCRC() + { + /*byte[] header = MakeHeader(); + + if (CalcOcCRC(header, 0, header.Length) == checksum) + { + return true; + } + else + { + return false; + }*/ + return true; + } + + internal ushort DestinationPort { get { return destinationPort; } From b11ab7fcab4811476f479711d79b1e6dc09526c2 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 3 May 2021 16:47:11 +0200 Subject: [PATCH 117/314] NRE Fix (forgot to update LastACK + LastSEQ in new SYN in) --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index c4db8283ca..47d6c7af6b 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -276,6 +276,9 @@ internal void ReceiveData(TCPPacket packet) source = IPConfig.FindNetwork(packet.SourceIP); + LastACK = packet.AckNumber; + LastSEQ = packet.SequenceNumber; + SendAck(LastACK, LastSEQ + 1, 0x12); //SYN / ACK } else if (Status == Status.OPENED && packet.FIN) From 15e6e4867f8267ddbca13d081d3a8bf36f7c3466 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 3 May 2021 17:00:10 +0200 Subject: [PATCH 118/314] Forgot destination + destinationPort too --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 47d6c7af6b..3f81170e7c 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -276,6 +276,9 @@ internal void ReceiveData(TCPPacket packet) source = IPConfig.FindNetwork(packet.SourceIP); + destination = packet.SourceIP; + destinationPort = packet.SourcePort; + LastACK = packet.AckNumber; LastSEQ = packet.SequenceNumber; From 589e7bc87592ad9605711b5e806ff1610ebe6ab3 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 4 May 2021 14:09:30 +0200 Subject: [PATCH 119/314] Add TCP flags values --- .../Cosmos.System2/Network/IPv4/IPPacket.cs | 4 +-- .../Network/IPv4/TCP/TCPClient.cs | 24 +++++++-------- .../Network/IPv4/TCP/TCPPacket.cs | 30 +++++++++++++------ 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/IPPacket.cs b/source/Cosmos.System2/Network/IPv4/IPPacket.cs index 03a624905c..2e212b1e79 100644 --- a/source/Cosmos.System2/Network/IPv4/IPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/IPPacket.cs @@ -98,7 +98,7 @@ protected override void InitFields() TypeOfService = RawData[15]; IPLength = (ushort)((RawData[16] << 8) | RawData[17]); FragmentID = (ushort)((RawData[18] << 8) | RawData[19]); - Flags = (byte)((RawData[20] & 0xE0) >> 5); + IPFlags = (byte)((RawData[20] & 0xE0) >> 5); FragmentOffset = (ushort)(((RawData[20] & 0x1F) << 8) | RawData[21]); TTL = RawData[22]; Protocol = RawData[23]; @@ -240,7 +240,7 @@ protected ushort CalcIPCRC(ushort headerLength) /// /// Get flags. /// - internal byte Flags { get; private set; } + internal byte IPFlags { get; private set; } /// /// Get fragment offset. /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 3f81170e7c..5e1273ee2b 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -23,6 +23,7 @@ public enum Status DATASENT, CLOSED, CLOSING //FIN sent or received + //TODO: Implement real status values from RFC793 } /// @@ -149,17 +150,12 @@ public void Connect(Address dest, int destPort, int timeout = 5000) source = IPConfig.FindNetwork(dest); - byte[] options = new byte[] - { - 0x02, 0x04, 0x05, 0xB4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01, 0x04, 0x02 - }; - //Generate Random Sequence Number var rnd = new Random(); ulong sequencenumber = (ulong)((rnd.Next(0, Int32.MaxValue)) << 32) | (ulong)(rnd.Next(0, Int32.MaxValue)); // Flags=0x02 -> Syn - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destPort, sequencenumber, 0, (ushort)(20 + options.Length), 0x02, 0xFAF0, 0, (ushort)options.Length, options); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destPort, sequencenumber, 0, 20, 0x02, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); @@ -282,12 +278,12 @@ internal void ReceiveData(TCPPacket packet) LastACK = packet.AckNumber; LastSEQ = packet.SequenceNumber; - SendAck(LastACK, LastSEQ + 1, 0x12); //SYN / ACK + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.SYN | Flags.ACK); } else if (Status == Status.OPENED && packet.FIN) { Status = Status.CLOSING; - SendAck(LastACK, LastSEQ + 1); + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); //TODO: Send FIN Packet } @@ -298,7 +294,7 @@ internal void ReceiveData(TCPPacket packet) LastACK = packet.AckNumber; LastSEQ = packet.SequenceNumber; - SendAck(LastACK, LastSEQ + 1); + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); } else if (Status == Status.OPENING && packet.SYN && packet.ACK) { @@ -307,9 +303,9 @@ internal void ReceiveData(TCPPacket packet) LastACK = packet.AckNumber; LastSEQ = packet.SequenceNumber; - SendAck(LastACK, LastSEQ + 1); + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); } - if (Status == Status.OPENING && packet.ACK) + else if (Status == Status.OPENING && packet.ACK) { Status = Status.OPENED; @@ -334,7 +330,7 @@ internal void ReceiveData(TCPPacket packet) rxBuffer.Enqueue(packet); - SendAck(LastACK, LastSEQ + 1); + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); } else if (packet.RST) { @@ -376,9 +372,9 @@ private bool WaitStatus(Status status, int timeout) /// /// Send acknowledgement packet /// - private void SendAck(uint lastSEQ, uint lastACK, ushort flag = 0x10) + private void SendEmptyPacket(uint lastSEQ, uint lastACK, Flags flag) { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, lastSEQ, lastACK, 20, flag, 0xFAF0, 0); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, lastSEQ, lastACK, 20, (byte)flag, 0xFAF0, 0); LastACK = packet.AckNumber; LastSEQ = packet.SequenceNumber; diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index b6942e9418..a2a46b43c8 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -12,6 +12,18 @@ namespace Cosmos.System.Network.IPv4.TCP { + /// + /// TCP Flags + /// + public enum Flags + { + FIN = (1 << 0), + SYN = (1 << 1), + RST = (1 << 2), + PSH = (1 << 3), + ACK = (1 << 4), + URG = (1 << 5) + } /// /// DHCP Option @@ -81,7 +93,7 @@ internal TCPPacket(byte[] rawData) { } public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, - ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, ushort Flags, + ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, byte Flags, ushort WSValue, ushort UrgentPointer, ushort len, byte[] options) : base((ushort)(20 + len), 6, source, dest, 0x40) { @@ -91,7 +103,7 @@ public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, } public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, - ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, ushort Flags, + ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, byte Flags, ushort WSValue, ushort UrgentPointer) : base(20, 6, source, dest, 0x40) { @@ -100,7 +112,7 @@ public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, } public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, - ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, ushort Flags, + ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, byte Flags, ushort WSValue, ushort UrgentPointer, ushort len) : base((ushort)(20 + len), 6, source, dest, 0x40) { @@ -109,7 +121,7 @@ public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, } private void MakePacket(Address source, Address dest, ushort srcPort, ushort destPort, - ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, ushort Flags, + ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, byte Flags, ushort WSValue, ushort UrgentPointer, ushort len) { optionLen = len; @@ -175,11 +187,11 @@ protected override void InitFields() checksum = (ushort)((RawData[DataOffset + 16] << 8) | RawData[DataOffset + 17]); urgentPointer = (ushort)((RawData[DataOffset + 18] << 8) | RawData[DataOffset + 19]); - SYN = (RawData[47] & (1 << 1)) != 0; - ACK = (RawData[47] & (1 << 4)) != 0; - FIN = (RawData[47] & (1 << 0)) != 0; - PSH = (RawData[47] & (1 << 3)) != 0; - RST = (RawData[47] & (1 << 2)) != 0; + SYN = (RawData[47] & (byte)Flags.SYN) != 0; + ACK = (RawData[47] & (byte)Flags.ACK) != 0; + FIN = (RawData[47] & (byte)Flags.FIN) != 0; + PSH = (RawData[47] & (byte)Flags.PSH) != 0; + RST = (RawData[47] & (byte)Flags.RST) != 0; if (RawData.Length == (DataOffset + headerLenght)) //no data { From f266bc0386c648fc69c98e855eb16775dbfe3dd1 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 4 May 2021 15:39:53 +0200 Subject: [PATCH 120/314] Use TCP states from RFC793 - Open connection - Close connection --- .../Network/IPv4/TCP/TCPClient.cs | 146 ++++++++++++------ 1 file changed, 99 insertions(+), 47 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 5e1273ee2b..7d2f5ba7ef 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading; using Cosmos.HAL; using Cosmos.System.Network.Config; @@ -18,12 +19,17 @@ namespace Cosmos.System.Network.IPv4.TCP /// public enum Status { - OPENED, - OPENING, //SYN sent or received - DATASENT, - CLOSED, - CLOSING //FIN sent or received - //TODO: Implement real status values from RFC793 + LISTEN, + SYN_SENT, + SYN_RECEIVED, + ESTABLISHED, + FIN_WAIT1, + FIN_WAIT2, + CLOSE_WAIT, + CLOSING, + LAST_ACK, + TIME_WAIT, + CLOSED } /// @@ -155,14 +161,14 @@ public void Connect(Address dest, int destPort, int timeout = 5000) ulong sequencenumber = (ulong)((rnd.Next(0, Int32.MaxValue)) << 32) | (ulong)(rnd.Next(0, Int32.MaxValue)); // Flags=0x02 -> Syn - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destPort, sequencenumber, 0, 20, 0x02, 0xFAF0, 0); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destPort, sequencenumber, 0, 20, (byte)Flags.SYN, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - Status = Status.OPENING; + Status = Status.SYN_SENT; - if (WaitStatus(Status.OPENED, timeout) == false) + if (WaitStatus(Status.ESTABLISHED, timeout) == false) { throw new Exception("Failed to open TCP connection!"); } @@ -174,13 +180,13 @@ public void Connect(Address dest, int destPort, int timeout = 5000) /// Thrown on fatal error (contact support). public void Close() { - if (Status == Status.OPENED) + if (Status == Status.ESTABLISHED) { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, 20, 0x11, 0xFAF0, 0); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, 20, (byte)Flags.FIN, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - Status = Status.CLOSING; + Status = Status.FIN_WAIT1; if (WaitStatus(Status.CLOSED, 5000) == false) { @@ -266,57 +272,98 @@ public byte[] Receive(ref EndPoint source) /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { - if (Status == Status.CLOSED && packet.SYN) + if (Status == Status.LISTEN) { - Status = Status.OPENING; - - source = IPConfig.FindNetwork(packet.SourceIP); + if (packet.SYN) + { + Status = Status.SYN_RECEIVED; - destination = packet.SourceIP; - destinationPort = packet.SourcePort; + source = IPConfig.FindNetwork(packet.SourceIP); - LastACK = packet.AckNumber; - LastSEQ = packet.SequenceNumber; + destination = packet.SourceIP; + destinationPort = packet.SourcePort; - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.SYN | Flags.ACK); + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.SYN | Flags.ACK); + } } - else if (Status == Status.OPENED && packet.FIN) + else if (Status == Status.SYN_RECEIVED) { - Status = Status.CLOSING; - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); + if (packet.RST) + { + Status = Status.LISTEN; + } + else if (packet.ACK) + { + Status = Status.ESTABLISHED; + } + } + else if (Status == Status.SYN_SENT) + { + if (packet.SYN && packet.ACK) + { + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); - //TODO: Send FIN Packet + Status = Status.ESTABLISHED; + } } - else if (Status == Status.CLOSING && packet.FIN && packet.ACK) + else if (Status == Status.ESTABLISHED) { - Status = Status.CLOSED; + if (packet.FIN) + { + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); - LastACK = packet.AckNumber; - LastSEQ = packet.SequenceNumber; + Status = Status.CLOSE_WAIT; - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.FIN); + } } - else if (Status == Status.OPENING && packet.SYN && packet.ACK) + else if (Status == Status.FIN_WAIT1) { - Status = Status.OPENED; + if (packet.FIN && packet.ACK) + { + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); - LastACK = packet.AckNumber; - LastSEQ = packet.SequenceNumber; + WaitAndClose(); + } + else if (packet.FIN) + { + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); + Status = Status.CLOSING; + } + else if (packet.ACK) + { + Status = Status.FIN_WAIT2; + + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); + } } - else if (Status == Status.OPENING && packet.ACK) + else if (Status == Status.FIN_WAIT2) { - Status = Status.OPENED; + if (packet.FIN) + { + SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); - LastACK = packet.AckNumber; - LastSEQ = packet.SequenceNumber; + WaitAndClose(); + } } - else if (Status == Status.OPENING && packet.RST && packet.ACK) + else if (Status == Status.CLOSING) { - throw new Exception("Connection rejected!"); + if (packet.ACK) + { + WaitAndClose(); + } } - else if (Status == Status.DATASENT && packet.ACK) + else if (Status == Status.CLOSE_WAIT) + { + if (packet.ACK) + { + Status = Status.CLOSED; + } + } + + + /*else if (Status == Status.DATASENT && packet.ACK) { Status = Status.OPENED; @@ -331,11 +378,16 @@ internal void ReceiveData(TCPPacket packet) rxBuffer.Enqueue(packet); SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); - } - else if (packet.RST) - { - throw new Exception("Connection reseted!"); - } + }*/ + } + + private void WaitAndClose() + { + Status = Status.TIME_WAIT; + + Thread.Sleep(100); //100ms for now + + Status = Status.CLOSED; } /// From 2fc852b47626ff7fbb4658e3a28df61e02af7c9b Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 4 May 2021 16:20:09 +0200 Subject: [PATCH 121/314] Update ack + seq values --- .../Network/IPv4/TCP/TCPClient.cs | 64 ++++++++++++------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 7d2f5ba7ef..31131c3e30 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -72,12 +72,17 @@ public class TcpClient : IDisposable /// /// Last Connection Acknowledgement number. /// - internal uint LastACK; + internal uint AckNumber; /// /// Last Connection Sequence number. /// - internal uint LastSEQ; + internal uint SequenceNumber; + + /// + /// Next Connection Sequence number. + /// + internal uint NextSequenceNumber; /// /// Assign clients dictionary. @@ -280,10 +285,13 @@ internal void ReceiveData(TCPPacket packet) source = IPConfig.FindNetwork(packet.SourceIP); + AckNumber = packet.SequenceNumber + 1; + SequenceNumber = 0xbeefcafe; //TODO: Generate this + destination = packet.SourceIP; destinationPort = packet.SourcePort; - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.SYN | Flags.ACK); + SendEmptyPacket(Flags.SYN | Flags.ACK); } } else if (Status == Status.SYN_RECEIVED) @@ -295,13 +303,18 @@ internal void ReceiveData(TCPPacket packet) else if (packet.ACK) { Status = Status.ESTABLISHED; + + SequenceNumber = packet.SequenceNumber; } } else if (Status == Status.SYN_SENT) { if (packet.SYN && packet.ACK) { - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); + AckNumber = packet.SequenceNumber + 1; + SequenceNumber++; + + SendEmptyPacket(Flags.ACK); Status = Status.ESTABLISHED; } @@ -310,39 +323,45 @@ internal void ReceiveData(TCPPacket packet) { if (packet.FIN) { - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); + AckNumber++; + + SendEmptyPacket(Flags.ACK); Status = Status.CLOSE_WAIT; - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.FIN); + SendEmptyPacket(Flags.FIN); } } else if (Status == Status.FIN_WAIT1) { if (packet.FIN && packet.ACK) { - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); + AckNumber++; + + SendEmptyPacket(Flags.ACK); WaitAndClose(); } else if (packet.FIN) { - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); + AckNumber++; + + SendEmptyPacket(Flags.ACK); Status = Status.CLOSING; } else if (packet.ACK) { Status = Status.FIN_WAIT2; - - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); } } else if (Status == Status.FIN_WAIT2) { if (packet.FIN) { - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); + AckNumber++; + + SendEmptyPacket(Flags.ACK); WaitAndClose(); } @@ -390,14 +409,6 @@ private void WaitAndClose() Status = Status.CLOSED; } - /// - /// Close Client - /// - public void Dispose() - { - Close(); - } - /// /// Wait for new TCP connection status. /// @@ -424,15 +435,20 @@ private bool WaitStatus(Status status, int timeout) /// /// Send acknowledgement packet /// - private void SendEmptyPacket(uint lastSEQ, uint lastACK, Flags flag) + private void SendEmptyPacket(Flags flag) { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, lastSEQ, lastACK, 20, (byte)flag, 0xFAF0, 0); - - LastACK = packet.AckNumber; - LastSEQ = packet.SequenceNumber; + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)flag, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); } + + /// + /// Close Client + /// + public void Dispose() + { + Close(); + } } } From 49c38f07e45d24fe6ad48f689470b9597512869d Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 4 May 2021 16:27:13 +0200 Subject: [PATCH 122/314] Update SequenceNumber with data length --- .../Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 31131c3e30..b39b752e3e 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -187,10 +187,12 @@ public void Close() { if (Status == Status.ESTABLISHED) { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, 20, (byte)Flags.FIN, 0xFAF0, 0); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)Flags.FIN, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); + SequenceNumber++; + Status = Status.FIN_WAIT1; if (WaitStatus(Status.CLOSED, 5000) == false) @@ -220,16 +222,16 @@ public void Send(byte[] data) throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); } - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, LastSEQ, LastACK, 20, 0x18, 0xFAF0, 0, (ushort)data.Length, data); + SequenceNumber += (uint)data.Length; + + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, 0x18, 0xFAF0, 0, (ushort)data.Length, data); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - Status = Status.DATASENT; - - if (WaitStatus(Status.OPENED, 5000) == false) + /*if (WaitStatus(Status.OPENED, 5000) == false) { throw new Exception("Failed to send TCP data!"); - } + }*/ } /// From 44fe61a62decfb4cb5b4ee256d69a539096173b0 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 4 May 2021 17:02:54 +0200 Subject: [PATCH 123/314] Remove useless NextSequenceNumber + Build fix (Thread) --- .../Network/IPv4/TCP/TCPClient.cs | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index b39b752e3e..05b1629748 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -72,17 +72,12 @@ public class TcpClient : IDisposable /// /// Last Connection Acknowledgement number. /// - internal uint AckNumber; + internal ulong AckNumber; /// /// Last Connection Sequence number. /// - internal uint SequenceNumber; - - /// - /// Next Connection Sequence number. - /// - internal uint NextSequenceNumber; + internal ulong SequenceNumber; /// /// Assign clients dictionary. @@ -163,10 +158,10 @@ public void Connect(Address dest, int destPort, int timeout = 5000) //Generate Random Sequence Number var rnd = new Random(); - ulong sequencenumber = (ulong)((rnd.Next(0, Int32.MaxValue)) << 32) | (ulong)(rnd.Next(0, Int32.MaxValue)); + SequenceNumber = (ulong)((rnd.Next(0, Int32.MaxValue)) << 32) | (ulong)(rnd.Next(0, Int32.MaxValue)); // Flags=0x02 -> Syn - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destPort, sequencenumber, 0, 20, (byte)Flags.SYN, 0xFAF0, 0); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destPort, SequenceNumber, 0, 20, (byte)Flags.SYN, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); @@ -187,7 +182,7 @@ public void Close() { if (Status == Status.ESTABLISHED) { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)Flags.FIN, 0xFAF0, 0); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)(Flags.FIN | Flags.ACK), 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); @@ -222,12 +217,12 @@ public void Send(byte[] data) throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); } - SequenceNumber += (uint)data.Length; - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, 0x18, 0xFAF0, 0, (ushort)data.Length, data); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); + SequenceNumber += (uint)data.Length; + /*if (WaitStatus(Status.OPENED, 5000) == false) { throw new Exception("Failed to send TCP data!"); @@ -406,7 +401,7 @@ private void WaitAndClose() { Status = Status.TIME_WAIT; - Thread.Sleep(100); //100ms for now + //Thread.Sleep(100); //100ms for now Status = Status.CLOSED; } From 1239027f01b1ead0bfa112f0f2033fd22f670f7c Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 4 May 2021 17:11:51 +0200 Subject: [PATCH 124/314] Packet reception --- .../Network/IPv4/TCP/TCPClient.cs | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 05b1629748..ec5177414b 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -328,6 +328,14 @@ internal void ReceiveData(TCPPacket packet) SendEmptyPacket(Flags.FIN); } + else if (packet.PSH && packet.ACK) + { + AckNumber += packet.TCP_DataLength; + + rxBuffer.Enqueue(packet); + + SendEmptyPacket(Flags.ACK); + } } else if (Status == Status.FIN_WAIT1) { @@ -377,24 +385,6 @@ internal void ReceiveData(TCPPacket packet) Status = Status.CLOSED; } } - - - /*else if (Status == Status.DATASENT && packet.ACK) - { - Status = Status.OPENED; - - LastACK = packet.SequenceNumber; - LastSEQ = packet.AckNumber; - } - else if (Status == Status.OPENED && packet.PSH && packet.ACK) - { - LastACK = packet.AckNumber; - LastSEQ = packet.SequenceNumber; - - rxBuffer.Enqueue(packet); - - SendEmptyPacket(LastACK, LastSEQ + 1, Flags.ACK); - }*/ } private void WaitAndClose() From 918d74dcaca91d0c3670616456b6851e072cc7f8 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 5 May 2021 13:21:01 +0200 Subject: [PATCH 125/314] Add doc comments + code clean --- .../Network/IPv4/TCP/TCPClient.cs | 7 +- .../Network/IPv4/TCP/TCPPacket.cs | 246 ++++++++++++------ 2 files changed, 169 insertions(+), 84 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index ec5177414b..dcd789f9c2 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -217,7 +217,7 @@ public void Send(byte[] data) throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); } - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, 0x18, 0xFAF0, 0, (ushort)data.Length, data); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, 0x18, 0xFAF0, 0, data); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); @@ -267,7 +267,7 @@ public byte[] Receive(ref EndPoint source) } /// - /// Receive data from packet. + /// Handle TCP discussions and data. /// /// Packet to receive. /// Thrown on fatal error (contact support). @@ -387,6 +387,9 @@ internal void ReceiveData(TCPPacket packet) } } + /// + /// Wait until remote receive ACK of its connection termination request. + /// private void WaitAndClose() { Status = Status.TIME_WAIT; diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index a2a46b43c8..b0fa5a5261 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -26,7 +26,7 @@ public enum Flags } /// - /// DHCP Option + /// TCP Option /// public class TCPOption { @@ -35,27 +35,19 @@ public class TCPOption public byte[] Data { get; set; } } + /// + /// TCP Packet Class + /// public class TCPPacket : IPPacket { - protected ushort sourcePort; - protected ushort destinationPort; - protected ushort optionLen; - protected uint sequenceNumber; - protected uint ackNumber; - protected int headerLenght; - protected int flags; - protected int wsValue; - protected ushort checksum; - protected int urgentPointer; - - protected List options = null; - - public bool SYN; - public bool ACK; - public bool FIN; - public bool PSH; - public bool RST; - + /// + /// TCP handler. + /// + /// Packet data. + /// Thrown on fatal error (contact support). + /// Thrown on IO error. + /// Thrown on fatal error (contact support). + /// Thrown if packetData array length is greater than Int32.MaxValue. internal static void TCPHandler(byte[] packetData) { var packet = new TCPPacket(packetData); @@ -77,55 +69,89 @@ internal static void TCPHandler(byte[] packetData) } /// - /// Work around to make VMT scanner include the initFields method + /// Create new instance of the class. /// - public static void VMTInclude() - { - new TCPPacket(); - } - internal TCPPacket() : base() { } + /// + /// Create new instance of the class. + /// + /// Raw data. internal TCPPacket(byte[] rawData) : base(rawData) { } + /// + /// Create new instance of the class. + /// + /// Source address. + /// Destination address. + /// Source port. + /// Destination port. + /// Sequence number. + /// /// Acknowledgment Number. + /// /// TCP Header length. + /// /// TCP flags. + /// /// Windows size. + /// /// Urgent Pointer. + /// /// Raw data. + /// Thrown if data array length is greater than Int32.MaxValue. + /// Thrown if RawData is invalid or null. public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, byte Flags, - ushort WSValue, ushort UrgentPointer, ushort len, byte[] options) - : base((ushort)(20 + len), 6, source, dest, 0x40) + ushort WSValue, ushort UrgentPointer, byte[] data) + : base((ushort)(20 + data.Length), 6, source, dest, 0x40) { - AddRawOption(options); + AddRawData(data); MakePacket(source, dest, srcPort, destPort, sequencenumber, - acknowledgmentnb, Headerlenght, Flags, WSValue, UrgentPointer, len); + acknowledgmentnb, Headerlenght, Flags, WSValue, UrgentPointer); } + /// + /// Create new instance of the class. + /// + /// Source address. + /// Destination address. + /// Source port. + /// Destination port. + /// Sequence number. + /// /// Acknowledgment Number. + /// /// TCP Header length. + /// /// TCP flags. + /// /// Windows size. + /// /// Urgent Pointer. + /// Thrown if data array length is greater than Int32.MaxValue. + /// Thrown if RawData is invalid or null. public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, byte Flags, ushort WSValue, ushort UrgentPointer) : base(20, 6, source, dest, 0x40) { MakePacket(source, dest, srcPort, destPort, sequencenumber, - acknowledgmentnb, Headerlenght, Flags, WSValue, UrgentPointer, 0); - } - - public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, - ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, byte Flags, - ushort WSValue, ushort UrgentPointer, ushort len) - : base((ushort)(20 + len), 6, source, dest, 0x40) - { - MakePacket(source, dest, srcPort, destPort, sequencenumber, - acknowledgmentnb, Headerlenght, Flags, WSValue, UrgentPointer, len); + acknowledgmentnb, Headerlenght, Flags, WSValue, UrgentPointer); } + /// + /// Make TCP Packet. + /// + /// Source address. + /// Destination address. + /// Source port. + /// Destination port. + /// Sequence number. + /// /// Acknowledgment Number. + /// /// TCP Header length. + /// /// TCP flags. + /// /// Windows size. + /// /// Urgent Pointer. + /// Thrown if data array length is greater than Int32.MaxValue. + /// Thrown if RawData is invalid or null. private void MakePacket(Address source, Address dest, ushort srcPort, ushort destPort, ulong sequencenumber, ulong acknowledgmentnb, ushort Headerlenght, byte Flags, - ushort WSValue, ushort UrgentPointer, ushort len) + ushort WSValue, ushort UrgentPointer) { - optionLen = len; - //ports RawData[DataOffset + 0] = (byte)((srcPort >> 8) & 0xFF); RawData[DataOffset + 1] = (byte)((srcPort >> 0) & 0xFF); @@ -174,18 +200,22 @@ private void MakePacket(Address source, Address dest, ushort srcPort, ushort des RawData[DataOffset + 17] = (byte)((calculatedcrc >> 0) & 0xFF); } + /// + /// Init TCPPacket fields. + /// + /// Thrown if RawData is invalid or null. protected override void InitFields() { base.InitFields(); - sourcePort = (ushort)((RawData[DataOffset] << 8) | RawData[DataOffset + 1]); - destinationPort = (ushort)((RawData[DataOffset + 2] << 8) | RawData[DataOffset + 3]); - sequenceNumber = (uint)((RawData[DataOffset + 4] << 24) | (RawData[DataOffset + 5] << 16) | (RawData[DataOffset + 6] << 8) | RawData[DataOffset + 7]); - ackNumber = (uint)((RawData[DataOffset + 8] << 24) | (RawData[DataOffset + 9] << 16) | (RawData[DataOffset + 10] << 8) | RawData[DataOffset + 11]); - headerLenght = (RawData[DataOffset + 12] >> 4) * 4; - flags = RawData[DataOffset + 13]; - wsValue = (ushort)((RawData[DataOffset + 14] << 8) | RawData[DataOffset + 15]); - checksum = (ushort)((RawData[DataOffset + 16] << 8) | RawData[DataOffset + 17]); - urgentPointer = (ushort)((RawData[DataOffset + 18] << 8) | RawData[DataOffset + 19]); + SourcePort = (ushort)((RawData[DataOffset] << 8) | RawData[DataOffset + 1]); + DestinationPort = (ushort)((RawData[DataOffset + 2] << 8) | RawData[DataOffset + 3]); + SequenceNumber = (uint)((RawData[DataOffset + 4] << 24) | (RawData[DataOffset + 5] << 16) | (RawData[DataOffset + 6] << 8) | RawData[DataOffset + 7]); + AckNumber = (uint)((RawData[DataOffset + 8] << 24) | (RawData[DataOffset + 9] << 16) | (RawData[DataOffset + 10] << 8) | RawData[DataOffset + 11]); + TCPHeaderLength = (byte)((RawData[DataOffset + 12] >> 4) * 4); + TCPFlags = RawData[DataOffset + 13]; + WindowSize = (ushort)((RawData[DataOffset + 14] << 8) | RawData[DataOffset + 15]); + Checksum = (ushort)((RawData[DataOffset + 16] << 8) | RawData[DataOffset + 17]); + UrgentPointer = (ushort)((RawData[DataOffset + 18] << 8) | RawData[DataOffset + 19]); SYN = (RawData[47] & (byte)Flags.SYN) != 0; ACK = (RawData[47] & (byte)Flags.ACK) != 0; @@ -193,9 +223,9 @@ protected override void InitFields() PSH = (RawData[47] & (byte)Flags.PSH) != 0; RST = (RawData[47] & (byte)Flags.RST) != 0; - if (RawData.Length == (DataOffset + headerLenght)) //no data + if (RawData.Length == (DataOffset + TCPHeaderLength)) //no data { - if (headerLenght > 20) //options + if (TCPHeaderLength > 20) //options { options = new List(); @@ -224,18 +254,24 @@ protected override void InitFields() } } } - else - { - //TODO: Parse data - } } + /// + /// Add Option to TCP Packet. + /// + /// TCP Option. + /// Thrown if RawData is invalid or null. internal void AddOption(TCPOption option) { throw new NotImplementedException(); } - internal void AddRawOption(byte[] raw) + /// + /// Add raw data to TCP Packet. + /// + /// Raw data. + /// Thrown if RawData is invalid or null. + internal void AddRawData(byte[] raw) { for (int i = 0; i < raw.Length; i++) { @@ -295,32 +331,73 @@ public bool CheckCRC() return true; } + /// + /// TCP Options + /// + protected List options { get; set; } - internal ushort DestinationPort - { - get { return destinationPort; } - } - internal ushort SourcePort - { - get { return sourcePort; } - } - internal uint AckNumber - { - get { return ackNumber; } - } - internal uint SequenceNumber - { - get { return sequenceNumber; } - } - internal int TCPFlags - { - get { return flags; } - } + /// + /// Is SYN Flag set. + /// + public bool SYN; + /// + /// Is ACK Flag set. + /// + public bool ACK; + /// + /// Is FIN Flag set. + /// + public bool FIN; + /// + /// Is PSH Flag set. + /// + public bool PSH; + /// + /// Is RST Flag set. + /// + public bool RST; + + /// + /// Get destination port. + /// + internal ushort DestinationPort { get; private set; } + /// + /// Get source port. + /// + internal ushort SourcePort { get; private set; } + /// + /// Get acknowledge number. + /// + internal uint AckNumber { get; private set; } + /// + /// Get sequence number. + /// + internal uint SequenceNumber { get; private set; } + /// + /// Get sequence number. + /// + internal byte TCPHeaderLength { get; private set; } + /// + /// Get sequence number. + /// + internal byte TCPFlags { get; private set; } + /// + /// Get sequence number. + /// + internal ushort WindowSize { get; private set; } + /// + /// Get sequence number. + /// + internal ushort Checksum { get; private set; } + /// + /// Get sequence number. + /// + internal ushort UrgentPointer { get; private set; } /// /// Get TCP data lenght. /// - public ushort TCP_DataLength => (ushort)(RawData.Length - (DataOffset + headerLenght)); + public ushort TCP_DataLength => (ushort)(RawData.Length - (DataOffset + TCPHeaderLength)); /// /// Get TCP data. @@ -334,16 +411,21 @@ internal byte[] TCP_Data for (int b = 0; b < data.Length; b++) { - data[b] = RawData[DataOffset + headerLenght + b]; + data[b] = RawData[DataOffset + TCPHeaderLength + b]; } return data; } } + /// + /// To string. + /// + /// string value. public override string ToString() { - return "TCP Packet Src=" + SourceIP + ":" + sourcePort + ", Dest=" + DestinationIP + ":" + destinationPort; + return "TCP Packet Src=" + SourceIP + ":" + SourcePort + "," + + "Dest=" + DestinationIP + ":" + DestinationPort + ", DataLen=" + TCP_DataLength; } } } From cfd92bf453c60360de1670e4366410a889cd5ef4 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 5 May 2021 13:37:53 +0200 Subject: [PATCH 126/314] Generate sequence number with Random() + Add FIN / ACK handling --- .../Network/IPv4/TCP/TCPClient.cs | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index dcd789f9c2..d0ec1c426d 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -283,7 +283,9 @@ internal void ReceiveData(TCPPacket packet) source = IPConfig.FindNetwork(packet.SourceIP); AckNumber = packet.SequenceNumber + 1; - SequenceNumber = 0xbeefcafe; //TODO: Generate this + + var rnd = new Random(); + SequenceNumber = (ulong)((rnd.Next(0, Int32.MaxValue)) << 32) | (ulong)(rnd.Next(0, Int32.MaxValue)); destination = packet.SourceIP; destinationPort = packet.SourcePort; @@ -315,10 +317,24 @@ internal void ReceiveData(TCPPacket packet) Status = Status.ESTABLISHED; } + else if (packet.RST && packet.ACK) + { + AckNumber = packet.SequenceNumber + 1; + + Status = Status.CLOSED; + } } else if (Status == Status.ESTABLISHED) { - if (packet.FIN) + if (packet.FIN && packet.ACK) + { + AckNumber++; + + SendEmptyPacket(Flags.ACK); + + WaitAndClose(); + } + else if (packet.FIN) { AckNumber++; @@ -327,6 +343,8 @@ internal void ReceiveData(TCPPacket packet) Status = Status.CLOSE_WAIT; SendEmptyPacket(Flags.FIN); + + Status = Status.LAST_ACK; } else if (packet.PSH && packet.ACK) { @@ -336,6 +354,12 @@ internal void ReceiveData(TCPPacket packet) SendEmptyPacket(Flags.ACK); } + else if (packet.RST) + { + AckNumber = packet.SequenceNumber + 1; + + Status = Status.CLOSED; + } } else if (Status == Status.FIN_WAIT1) { @@ -378,7 +402,7 @@ internal void ReceiveData(TCPPacket packet) WaitAndClose(); } } - else if (Status == Status.CLOSE_WAIT) + else if (Status == Status.CLOSE_WAIT || Status == Status.LAST_ACK) { if (packet.ACK) { From 488755ab07e06879e9ec3a1fe81086424bf83153 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 5 May 2021 13:55:33 +0200 Subject: [PATCH 127/314] Add TCP article to documentation --- Docs/articles/Kernel/Network.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index cb7abf44b4..4127b943a4 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -49,6 +49,25 @@ using(var xClient = new UdpClient(4242)) } ``` +## TCP +Like UDP, TCP has to create a client and call Connect() to specify the remote machine address before sending or receiving data. +```csharp +using(var xClient = new TcpClient(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); + xClient.Receive(ref endpoint); //set endpoint to remote machine IP:port + xClient.NonBlockingReceive(ref endpoint); //retrieve receive buffer without waiting + + xClient.Close(); +} +``` + ## ICMP For ICMP, we will only 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 From 1fb50eeacdfa7bc9e55d9b5ac642674cef1ed7a7 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 5 May 2021 17:10:43 +0200 Subject: [PATCH 128/314] Typo + TCP_DataLength fix + Dup packet check (PSH / ACK) --- .../Network/IPv4/TCP/TCPClient.cs | 9 +++-- .../Network/IPv4/TCP/TCPPacket.cs | 34 +++++++++---------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index d0ec1c426d..a76d01a8a0 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -348,11 +348,14 @@ internal void ReceiveData(TCPPacket packet) } else if (packet.PSH && packet.ACK) { - AckNumber += packet.TCP_DataLength; + if (packet.SequenceNumber != SequenceNumber) //DUP Check + { + AckNumber += packet.TCP_DataLength; - rxBuffer.Enqueue(packet); + rxBuffer.Enqueue(packet); - SendEmptyPacket(Flags.ACK); + SendEmptyPacket(Flags.ACK); + } } else if (packet.RST) { diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index b0fa5a5261..23a1d6d475 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -91,12 +91,12 @@ internal TCPPacket(byte[] rawData) /// Source port. /// Destination port. /// Sequence number. - /// /// Acknowledgment Number. - /// /// TCP Header length. - /// /// TCP flags. - /// /// Windows size. - /// /// Urgent Pointer. - /// /// Raw data. + /// Acknowledgment Number. + /// TCP Header length. + /// TCP flags. + /// Windows size. + /// Urgent Pointer. + /// Raw data. /// Thrown if data array length is greater than Int32.MaxValue. /// Thrown if RawData is invalid or null. public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, @@ -117,11 +117,11 @@ public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, /// Source port. /// Destination port. /// Sequence number. - /// /// Acknowledgment Number. - /// /// TCP Header length. - /// /// TCP flags. - /// /// Windows size. - /// /// Urgent Pointer. + /// Acknowledgment Number. + /// TCP Header length. + /// TCP flags. + /// Windows size. + /// Urgent Pointer. /// Thrown if data array length is greater than Int32.MaxValue. /// Thrown if RawData is invalid or null. public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, @@ -141,11 +141,11 @@ public TCPPacket(Address source, Address dest, ushort srcPort, ushort destPort, /// Source port. /// Destination port. /// Sequence number. - /// /// Acknowledgment Number. - /// /// TCP Header length. - /// /// TCP flags. - /// /// Windows size. - /// /// Urgent Pointer. + /// Acknowledgment Number. + /// TCP Header length. + /// TCP flags. + /// Windows size. + /// Urgent Pointer. /// Thrown if data array length is greater than Int32.MaxValue. /// Thrown if RawData is invalid or null. private void MakePacket(Address source, Address dest, ushort srcPort, ushort destPort, @@ -397,7 +397,7 @@ public bool CheckCRC() /// /// Get TCP data lenght. /// - public ushort TCP_DataLength => (ushort)(RawData.Length - (DataOffset + TCPHeaderLength)); + public ushort TCP_DataLength => (ushort)(IPLength - HeaderLength - TCPHeaderLength); /// /// Get TCP data. From 7751ae4b6ca5da656e39c1840ca724a787623afa Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 5 May 2021 20:09:59 +0200 Subject: [PATCH 129/314] Prevent packets length upper than 1500 for now Need to implement packet sequencing before. --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index a76d01a8a0..c07991e793 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -216,6 +216,10 @@ public void Send(byte[] data) { throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); } + if (data.Length > 1500) + { + throw new NotImplementedException("Data length must be less than 1500 bytes (yet!)"); + } var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, 0x18, 0xFAF0, 0, data); OutgoingBuffer.AddPacket(packet); From c6ad00e0311a198deeb7d91def1c2481b5ee642c Mon Sep 17 00:00:00 2001 From: raxracks <39295557+raxracks@users.noreply.github.com> Date: Sun, 9 May 2021 00:10:48 +1200 Subject: [PATCH 130/314] Fix hyperlink in readme fixed discussions hyperlink --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f9a30ba1f..b613ae090b 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,6 @@ For instructions on how to install and use Cosmos, please visit the [Cosmos webs For documentation and technical information, see the [Cosmos Documentation](https://cosmosos.github.io). -If you have questions about how to use Cosmos, want to show off what you have made or have general questions, go check out [Github Discussions] (https://github.com/CosmosOS/Cosmos/discussions). If you think you found a bug in Cosmos, please check exising [issues](https://github.com/CosmosOS/Cosmos/issues) first before opening a new one. +If you have questions about how to use Cosmos, want to show off what you have made or have general questions, go check out [Github Discussions](https://github.com/CosmosOS/Cosmos/discussions). If you think you found a bug in Cosmos, please check exising [issues](https://github.com/CosmosOS/Cosmos/issues) first before opening a new one. We also have a [Discord Server](https://discord.com/invite/kwtBwv6jhD)! From 824f536b89595989b5f67974557baae685439375 Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Sat, 8 May 2021 12:07:53 -0400 Subject: [PATCH 131/314] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2f9a30ba1f..107eda331c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Cosmos [![Build status](https://ci.appveyor.com/api/projects/status/kust7g5dlnykhkaf/branch/master?svg=true)](https://ci.appveyor.com/project/CosmosOS/cosmos/branch/master) +[![Join the chat at (https://discord.com/invite/kwtBwv6jhD](https://img.shields.io/discord/833970409337913344)](https://discord.com/invite/kwtBwv6jhD) Cosmos is an operating system "construction kit". Build your own OS using managed languages such as C#, VB.NET, and more! From 5606e521f43ce56165a6e0bf9c6d9b709c4e8399 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 10 May 2021 13:41:55 +0200 Subject: [PATCH 132/314] ulong to uint (seq & ack nb) + dup check --- .../Network/IPv4/TCP/TCPClient.cs | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index c07991e793..9d65fd1b6f 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -70,14 +70,19 @@ public class TcpClient : IDisposable internal Status Status; /// - /// Last Connection Acknowledgement number. + /// Connection Acknowledgement number. /// - internal ulong AckNumber; + internal uint AckNumber; /// - /// Last Connection Sequence number. + /// Connection Sequence number. /// - internal ulong SequenceNumber; + internal uint SequenceNumber; + + /// + /// Last recveived Connection Sequence number. + /// + private uint LastSequenceNumber; /// /// Assign clients dictionary. @@ -122,6 +127,7 @@ public TcpClient(int localPort) { rxBuffer = new Queue(8); Status = Status.CLOSED; + LastSequenceNumber = 0; this.localPort = localPort; if (localPort > 0) @@ -158,7 +164,7 @@ public void Connect(Address dest, int destPort, int timeout = 5000) //Generate Random Sequence Number var rnd = new Random(); - SequenceNumber = (ulong)((rnd.Next(0, Int32.MaxValue)) << 32) | (ulong)(rnd.Next(0, Int32.MaxValue)); + SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); // Flags=0x02 -> Syn var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destPort, SequenceNumber, 0, 20, (byte)Flags.SYN, 0xFAF0, 0); @@ -289,7 +295,7 @@ internal void ReceiveData(TCPPacket packet) AckNumber = packet.SequenceNumber + 1; var rnd = new Random(); - SequenceNumber = (ulong)((rnd.Next(0, Int32.MaxValue)) << 32) | (ulong)(rnd.Next(0, Int32.MaxValue)); + SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); destination = packet.SourceIP; destinationPort = packet.SourcePort; @@ -352,10 +358,12 @@ internal void ReceiveData(TCPPacket packet) } else if (packet.PSH && packet.ACK) { - if (packet.SequenceNumber != SequenceNumber) //DUP Check + if (packet.SequenceNumber > LastSequenceNumber) //dup check { AckNumber += packet.TCP_DataLength; + LastSequenceNumber = packet.SequenceNumber; + rxBuffer.Enqueue(packet); SendEmptyPacket(Flags.ACK); From 7e1a58aae02eac6998c02a2f8d907b058850eb60 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 10 May 2021 15:09:02 +0200 Subject: [PATCH 133/314] Security check + throw exception if packet sequencing + add IsConnected method --- .../Network/IPv4/TCP/TCPClient.cs | 65 +++++++++++++++---- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 9d65fd1b6f..949fa0004a 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -155,8 +155,14 @@ public TcpClient(Address dest, int destPort) /// /// Destination address. /// Destination port. + /// Thrown if TCP Status is not CLOSED. public void Connect(Address dest, int destPort, int timeout = 5000) { + if (Status != Status.CLOSED) + { + throw new Exception("Client must be closed before setting a new connection."); + } + destination = dest; destinationPort = destPort; @@ -184,8 +190,13 @@ public void Connect(Address dest, int destPort, int timeout = 5000) /// Close connection. /// /// Thrown on fatal error (contact support). + /// Thrown if TCP Status is CLOSED. public void Close() { + if (Status == Status.CLOSED) + { + throw new Exception("Client already closed."); + } if (Status == Status.ESTABLISHED) { var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)(Flags.FIN | Flags.ACK), 0xFAF0, 0); @@ -216,6 +227,7 @@ public void Close() /// Thrown on fatal error (contact support). /// Thrown if data array length is greater than Int32.MaxValue. /// Thrown on IO error. + /// Thrown if TCP Status is not ESTABLISHED. public void Send(byte[] data) { if ((destination == null) || (destinationPort == 0)) @@ -226,17 +238,16 @@ public void Send(byte[] data) { throw new NotImplementedException("Data length must be less than 1500 bytes (yet!)"); } + if (Status != Status.ESTABLISHED) + { + throw new Exception("Client must be connected before sending data."); + } var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, 0x18, 0xFAF0, 0, data); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); SequenceNumber += (uint)data.Length; - - /*if (WaitStatus(Status.OPENED, 5000) == false) - { - throw new Exception("Failed to send TCP data!"); - }*/ } /// @@ -245,8 +256,13 @@ public void Send(byte[] data) /// Source end point. /// byte array value. /// Thrown on fatal error (contact support). + /// Thrown if TCP Status is not ESTABLISHED. public byte[] NonBlockingReceive(ref EndPoint source) { + if (Status != Status.ESTABLISHED) + { + throw new Exception("Client must be connected before receiving data."); + } if (rxBuffer.Count < 1) { return null; @@ -265,8 +281,13 @@ public byte[] NonBlockingReceive(ref EndPoint source) /// Source end point. /// byte array value. /// Thrown on fatal error (contact support). + /// Thrown if TCP Status is not ESTABLISHED. public byte[] Receive(ref EndPoint source) { + if (Status != Status.ESTABLISHED) + { + throw new Exception("Client must be connected before receiving data."); + } while (rxBuffer.Count < 1); var packet = new TCPPacket(rxBuffer.Dequeue().RawData); @@ -336,7 +357,15 @@ internal void ReceiveData(TCPPacket packet) } else if (Status == Status.ESTABLISHED) { - if (packet.FIN && packet.ACK) + if (packet.RST) + { + Status = Status.CLOSED; + } + else if (packet.TCPFlags == (byte)Flags.ACK) //only ACK + { + throw new NotImplementedException("TCP sequencing is not supported yet! (received packet size is too huge)"); + } + else if (packet.FIN && packet.ACK) { AckNumber++; @@ -369,12 +398,6 @@ internal void ReceiveData(TCPPacket packet) SendEmptyPacket(Flags.ACK); } } - else if (packet.RST) - { - AckNumber = packet.SequenceNumber + 1; - - Status = Status.CLOSED; - } } else if (Status == Status.FIN_WAIT1) { @@ -433,7 +456,7 @@ private void WaitAndClose() { Status = Status.TIME_WAIT; - //Thread.Sleep(100); //100ms for now + HAL.Global.PIT.Wait(300); //TODO: Calculate time value Status = Status.CLOSED; } @@ -472,6 +495,22 @@ private void SendEmptyPacket(Flags flag) NetworkStack.Update(); } + /// + /// Is TCP Connected. + /// + /// Boolean value. + public bool IsConnected() + { + if (Status == Status.ESTABLISHED) + { + return true; + } + else + { + return false; + } + } + /// /// Close Client /// From f9b9f1b40514954fff9760c17d299d835eb87fc2 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 10 May 2021 15:22:43 +0200 Subject: [PATCH 134/314] Prevent incoming packet sequencing + coding style + remove useless ctor --- .../Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 949fa0004a..6308a80207 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -100,7 +100,7 @@ static TcpClient() /// TcpClient internal static TcpClient GetClient(ushort destPort) { - if (clients.ContainsKey((uint)destPort) == true) + if (clients.ContainsKey((uint)destPort)) { return clients[(uint)destPort]; } @@ -108,15 +108,6 @@ internal static TcpClient GetClient(ushort destPort) return null; } - /// - /// Create new instance of the class. - /// - /// Thrown on fatal error (contact support). - /// Thrown if TcpClient with localPort 0 exists. - public TcpClient() - : this(0) - { } - /// /// Create new instance of the class. /// @@ -213,7 +204,7 @@ public void Close() } } - if (clients.ContainsKey((uint)localPort) == true) + if (clients.ContainsKey((uint)localPort)) { clients.Remove((uint)localPort); } @@ -361,7 +352,7 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.CLOSED; } - else if (packet.TCPFlags == (byte)Flags.ACK) //only ACK + else if (packet.TCPFlags == (byte)Flags.ACK && packet.SequenceNumber > LastSequenceNumber) //only ACK { throw new NotImplementedException("TCP sequencing is not supported yet! (received packet size is too huge)"); } From 33e0b31ba7b2cade89a63ba9218271fce723f551 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 10 May 2021 15:37:07 +0200 Subject: [PATCH 135/314] Add TCP Packet parsing test --- Tests/Kernels/NetworkTest/Kernel.cs | 12 +++++++++++- source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Tests/Kernels/NetworkTest/Kernel.cs b/Tests/Kernels/NetworkTest/Kernel.cs index 197904fb74..9312ac2308 100644 --- a/Tests/Kernels/NetworkTest/Kernel.cs +++ b/Tests/Kernels/NetworkTest/Kernel.cs @@ -85,6 +85,16 @@ protected override void Run() DHCPPacket dhcpPacket = new DHCPPacket(dhcpPacketData); Equals(dhcpPacketData, dhcpPacket.RawData); + /** TCP Packet Parsing Test **/ + byte[] tcpPacketData = new byte[] + { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x00, 0x45, 0x00, 0x00, 0x2C, 0x21, 0x69, 0x40, 0x00, 0x80, 0x06, 0x9C, + 0xDA, 0x0A, 0x21, 0x14, 0x11, 0x0A, 0x21, 0x14, 0x36, 0x10, 0x92, 0x10, 0x92, 0xA7, 0xAE, 0x27, 0xD1, 0x56, 0x00, 0x00, 0x1A, 0x50, 0x18, 0xFF, 0x56, + 0x63, 0xAF, 0x00, 0x00, 0x65, 0x6E, 0x64, 0x0D + }; + TCPPacket tcpPacket = new TCPPacket(tcpPacketData); + Equals(tcpPacketData, tcpPacket.RawData); + /** ARP Packet Parsing Test **/ byte[] arpPacketData = new byte[] { @@ -109,7 +119,7 @@ protected override void Run() var udpClient = new UdpClient(); udpClient.Close(); - var tcpClient = new TcpClient(); + var tcpClient = new TcpClient(4242); tcpClient.Close(); var icmpClient = new ICMPClient(); diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 23a1d6d475..f43acb7389 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -79,7 +79,7 @@ internal TCPPacket() /// Create new instance of the class. /// /// Raw data. - internal TCPPacket(byte[] rawData) + public TCPPacket(byte[] rawData) : base(rawData) { } From 086a292efceefba2dc6e4ea3514720d996a39764 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 10 May 2021 16:03:04 +0200 Subject: [PATCH 136/314] Incoming SYN fixes + More exceptions --- .../Network/IPv4/TCP/TCPClient.cs | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 6308a80207..f538845995 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -296,7 +296,7 @@ public byte[] Receive(ref EndPoint source) /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { - if (Status == Status.LISTEN) + if (Status == Status.LISTEN || Status == Status.CLOSED) { if (packet.SYN) { @@ -314,6 +314,10 @@ internal void ReceiveData(TCPPacket packet) SendEmptyPacket(Flags.SYN | Flags.ACK); } + else + { + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSED||LISTEN)"); + } } else if (Status == Status.SYN_RECEIVED) { @@ -325,7 +329,11 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.ESTABLISHED; - SequenceNumber = packet.SequenceNumber; + SequenceNumber++; + } + else + { + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_RECEIVED)"); } } else if (Status == Status.SYN_SENT) @@ -339,12 +347,18 @@ internal void ReceiveData(TCPPacket packet) Status = Status.ESTABLISHED; } + else if (packet.SYN) + { + throw new NotImplementedException("Simultaneous open not supported."); + } else if (packet.RST && packet.ACK) { - AckNumber = packet.SequenceNumber + 1; - Status = Status.CLOSED; } + else + { + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_SENT)"); + } } else if (Status == Status.ESTABLISHED) { @@ -389,6 +403,10 @@ internal void ReceiveData(TCPPacket packet) SendEmptyPacket(Flags.ACK); } } + else + { + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=ESTABLISHED)"); + } } else if (Status == Status.FIN_WAIT1) { @@ -412,6 +430,10 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.FIN_WAIT2; } + else + { + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT1)"); + } } else if (Status == Status.FIN_WAIT2) { @@ -423,6 +445,10 @@ internal void ReceiveData(TCPPacket packet) WaitAndClose(); } + else + { + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT2)"); + } } else if (Status == Status.CLOSING) { @@ -430,6 +456,10 @@ internal void ReceiveData(TCPPacket packet) { WaitAndClose(); } + else + { + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSING)"); + } } else if (Status == Status.CLOSE_WAIT || Status == Status.LAST_ACK) { @@ -437,9 +467,15 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.CLOSED; } + else + { + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSE_WAIT||LAST_ACK)"); + } } } + #region Utils + /// /// Wait until remote receive ACK of its connection termination request. /// @@ -486,6 +522,8 @@ private void SendEmptyPacket(Flags flag) NetworkStack.Update(); } + #endregion + /// /// Is TCP Connected. /// From 18a8c6802bd0b4e7608238ac36a1c7df76425100 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 10 May 2021 16:55:07 +0200 Subject: [PATCH 137/314] Prevent TCP sequencing fix --- .../Network/IPv4/TCP/TCPClient.cs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index f538845995..95f8daaee7 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -29,7 +29,8 @@ public enum Status CLOSING, LAST_ACK, TIME_WAIT, - CLOSED + CLOSED, + WAITING_ACK } /// @@ -238,6 +239,8 @@ public void Send(byte[] data) OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); + Status = Status.WAITING_ACK; + SequenceNumber += (uint)data.Length; } @@ -360,17 +363,24 @@ internal void ReceiveData(TCPPacket packet) throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_SENT)"); } } - else if (Status == Status.ESTABLISHED) + else if (Status == Status.ESTABLISHED || Status == Status.WAITING_ACK) { if (packet.RST) { Status = Status.CLOSED; } - else if (packet.TCPFlags == (byte)Flags.ACK && packet.SequenceNumber > LastSequenceNumber) //only ACK + if (packet.TCPFlags == (byte)Flags.ACK) { - throw new NotImplementedException("TCP sequencing is not supported yet! (received packet size is too huge)"); + if (Status == Status.WAITING_ACK) + { + Status = Status.ESTABLISHED; + } + else + { + throw new NotImplementedException("TCP sequencing is not supported yet! (sent packet size is too huge)"); + } } - else if (packet.FIN && packet.ACK) + if (packet.FIN && packet.ACK) { AckNumber++; From 58913b813addc58d595e3bc741bf6d5322fba4cc Mon Sep 17 00:00:00 2001 From: Charles Betros Date: Mon, 10 May 2021 15:25:41 -0500 Subject: [PATCH 138/314] Add back shell execute so we get bochs debugger --- source/Cosmos.Debug.Hosts/Bochs.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/Cosmos.Debug.Hosts/Bochs.cs b/source/Cosmos.Debug.Hosts/Bochs.cs index 3687be748d..6f23ed6b4d 100644 --- a/source/Cosmos.Debug.Hosts/Bochs.cs +++ b/source/Cosmos.Debug.Hosts/Bochs.cs @@ -106,8 +106,7 @@ public override void Start() } _bochsStartInfo.Arguments = string.Format("-q {1} -f \"{0}\"", _bochsConfigurationFile.FullName, xExtraLog); _bochsStartInfo.WorkingDirectory = _bochsConfigurationFile.Directory.FullName; - _bochsStartInfo.CreateNoWindow = true; // when ProcessStartInfo.UseShellExecute is supported in .net core, maybe this line isn't needed - //_bochsStartInfo.UseShellExecute = true; + _bochsStartInfo.UseShellExecute = true; if (RedirectOutput) { if (LogOutput == null) From b0acaf1a0dbe078b3d26e41a82139a51bebc66b7 Mon Sep 17 00:00:00 2001 From: Michal99998 <59791284+Michal99998@users.noreply.github.com> Date: Tue, 11 May 2021 12:55:25 +0200 Subject: [PATCH 139/314] Fix typo in DiskManager.cs at 22:51 --- source/Cosmos.System2/FileSystem/DiskManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.System2/FileSystem/DiskManager.cs b/source/Cosmos.System2/FileSystem/DiskManager.cs index 32e82ac114..8b6d16ea26 100644 --- a/source/Cosmos.System2/FileSystem/DiskManager.cs +++ b/source/Cosmos.System2/FileSystem/DiskManager.cs @@ -19,7 +19,7 @@ public class DiskManager /// /// Create new instance of class. /// - /// A drive name assinged to the disk. + /// A drive name assigned to the disk. /// Thrown if aDriveName is null. /// Thrown if aDriveName length is smaller then 2, or greater than Int32.MaxValue. /// Thrown if aDriveName is invalid drive identifier / not a root dir. From bb50bc973b5a94083b803face6d986c8e951ee2b Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 11 May 2021 13:21:04 +0200 Subject: [PATCH 140/314] Add TCP packet parsing tests --- Tests/Kernels/NetworkTest/Kernel.cs | 15 +++++--- .../Cosmos.System2/Network/EthernetPacket.cs | 6 +--- .../Network/IPv4/TCP/TCPClient.cs | 9 +---- .../Network/IPv4/TCP/TCPPacket.cs | 36 +++++++++---------- 4 files changed, 31 insertions(+), 35 deletions(-) diff --git a/Tests/Kernels/NetworkTest/Kernel.cs b/Tests/Kernels/NetworkTest/Kernel.cs index 9312ac2308..1d1a5bfdfb 100644 --- a/Tests/Kernels/NetworkTest/Kernel.cs +++ b/Tests/Kernels/NetworkTest/Kernel.cs @@ -88,12 +88,19 @@ protected override void Run() /** TCP Packet Parsing Test **/ byte[] tcpPacketData = new byte[] { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x00, 0x45, 0x00, 0x00, 0x2C, 0x21, 0x69, 0x40, 0x00, 0x80, 0x06, 0x9C, - 0xDA, 0x0A, 0x21, 0x14, 0x11, 0x0A, 0x21, 0x14, 0x36, 0x10, 0x92, 0x10, 0x92, 0xA7, 0xAE, 0x27, 0xD1, 0x56, 0x00, 0x00, 0x1A, 0x50, 0x18, 0xFF, 0x56, - 0x63, 0xAF, 0x00, 0x00, 0x65, 0x6E, 0x64, 0x0D + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x00, 0x45, 0x00, 0x00, 0x3C, 0x64, 0x92, 0x40, 0x00, 0x40, 0x06, 0x51, + 0xA2, 0xC0, 0xA8, 0x01, 0xD3, 0xC0, 0xA8, 0x01, 0x64, 0xA8, 0xAB, 0x10, 0x92, 0x67, 0x7C, 0xCE, 0x18, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x02, 0x72, 0x10, + 0x5F, 0xF0, 0x00, 0x00, 0x02, 0x04, 0x05, 0xB4, 0x04, 0x02, 0x08, 0x0A, 0x58, 0x1A, 0xAA, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x07 }; TCPPacket tcpPacket = new TCPPacket(tcpPacketData); - Equals(tcpPacketData, tcpPacket.RawData); + Equals(tcpPacket.SourcePort, 43179); + Equals(tcpPacket.DestinationPort, 4242); + Equals(tcpPacket.SequenceNumber, 0x677CCE18); + Equals(tcpPacket.AckNumber, 0); + Equals(tcpPacket.TCPFlags, Flags.SYN); + Equals(tcpPacket.WindowSize, 29200); + Equals(tcpPacket.Checksum, 0x5FF0); + Equals(tcpPacket.UrgentPointer, 0); /** ARP Packet Parsing Test **/ byte[] arpPacketData = new byte[] diff --git a/source/Cosmos.System2/Network/EthernetPacket.cs b/source/Cosmos.System2/Network/EthernetPacket.cs index 876df7c358..f81f828d65 100644 --- a/source/Cosmos.System2/Network/EthernetPacket.cs +++ b/source/Cosmos.System2/Network/EthernetPacket.cs @@ -129,11 +129,7 @@ internal MACAddress DestinationMAC /// Prepare packet for sending. /// Not implemented. /// - public virtual void PrepareForSending() - { - - - } + internal virtual void PrepareForSending() { } /// /// To string. diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 95f8daaee7..a4e23ac826 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -540,14 +540,7 @@ private void SendEmptyPacket(Flags flag) /// Boolean value. public bool IsConnected() { - if (Status == Status.ESTABLISHED) - { - return true; - } - else - { - return false; - } + return Status == Status.ESTABLISHED; } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index f43acb7389..270f855c1d 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -227,7 +227,7 @@ protected override void InitFields() { if (TCPHeaderLength > 20) //options { - options = new List(); + Options = new List(); for (int i = 0; i < RawData.Length - (DataOffset + 20); i++) { @@ -247,7 +247,7 @@ protected override void InitFields() } } - options.Add(option); + Options.Add(option); i += option.Length - 1; } @@ -316,7 +316,7 @@ internal byte[] MakeHeader() /// Check TCP Checksum /// /// True if checksum correct, False otherwise. - public bool CheckCRC() + private bool CheckCRC() { /*byte[] header = MakeHeader(); @@ -334,65 +334,65 @@ public bool CheckCRC() /// /// TCP Options /// - protected List options { get; set; } + public List Options { get; set; } /// /// Is SYN Flag set. /// - public bool SYN; + internal bool SYN; /// /// Is ACK Flag set. /// - public bool ACK; + internal bool ACK; /// /// Is FIN Flag set. /// - public bool FIN; + internal bool FIN; /// /// Is PSH Flag set. /// - public bool PSH; + internal bool PSH; /// /// Is RST Flag set. /// - public bool RST; + internal bool RST; /// /// Get destination port. /// - internal ushort DestinationPort { get; private set; } + public ushort DestinationPort { get; private set; } /// /// Get source port. /// - internal ushort SourcePort { get; private set; } + public ushort SourcePort { get; private set; } /// /// Get acknowledge number. /// - internal uint AckNumber { get; private set; } + public uint AckNumber { get; private set; } /// /// Get sequence number. /// - internal uint SequenceNumber { get; private set; } + public uint SequenceNumber { get; private set; } /// /// Get sequence number. /// - internal byte TCPHeaderLength { get; private set; } + public byte TCPHeaderLength { get; private set; } /// /// Get sequence number. /// - internal byte TCPFlags { get; private set; } + public byte TCPFlags { get; private set; } /// /// Get sequence number. /// - internal ushort WindowSize { get; private set; } + public ushort WindowSize { get; private set; } /// /// Get sequence number. /// - internal ushort Checksum { get; private set; } + public ushort Checksum { get; private set; } /// /// Get sequence number. /// - internal ushort UrgentPointer { get; private set; } + public ushort UrgentPointer { get; private set; } /// /// Get TCP data lenght. From 91b41c3b7da95b7e163d6316a39ce7b1e149740c Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 11 May 2021 13:28:09 +0200 Subject: [PATCH 141/314] [DOC] Get data from Receive (udp and tcp) --- Docs/articles/Kernel/Network.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index 4127b943a4..92d583b09a 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -42,8 +42,8 @@ using(var xClient = new UdpClient(4242)) /** Receive data **/ var endpoint = new EndPoint(Address.Zero, 0); - xClient.Receive(ref endpoint); //set endpoint to remote machine IP:port - xClient.NonBlockingReceive(ref endpoint); //retrieve receive buffer without waiting + var data = xClient.Receive(ref endpoint); //set endpoint to remote machine IP:port + var data2 = xClient.NonBlockingReceive(ref endpoint); //retrieve receive buffer without waiting xClient.Close(); } @@ -61,8 +61,8 @@ using(var xClient = new TcpClient(4242)) /** Receive data **/ var endpoint = new EndPoint(Address.Zero, 0); - xClient.Receive(ref endpoint); //set endpoint to remote machine IP:port - xClient.NonBlockingReceive(ref endpoint); //retrieve receive buffer without waiting + var data = xClient.Receive(ref endpoint); //set endpoint to remote machine IP:port + var data2 = xClient.NonBlockingReceive(ref endpoint); //retrieve receive buffer without waiting xClient.Close(); } From 885725edf65065ffec812083106e36ca2d5eff80 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 11 May 2021 14:41:43 +0200 Subject: [PATCH 142/314] Connect to an existing TCP connection + Receive fix --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index a4e23ac826..ea4496d593 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -253,7 +253,7 @@ public void Send(byte[] data) /// Thrown if TCP Status is not ESTABLISHED. public byte[] NonBlockingReceive(ref EndPoint source) { - if (Status != Status.ESTABLISHED) + if (Status != Status.ESTABLISHED || Status == Status.WAITING_ACK) { throw new Exception("Client must be connected before receiving data."); } @@ -278,7 +278,7 @@ public byte[] NonBlockingReceive(ref EndPoint source) /// Thrown if TCP Status is not ESTABLISHED. public byte[] Receive(ref EndPoint source) { - if (Status != Status.ESTABLISHED) + if (Status != Status.ESTABLISHED || Status == Status.WAITING_ACK) { throw new Exception("Client must be connected before receiving data."); } @@ -358,6 +358,13 @@ internal void ReceiveData(TCPPacket packet) { Status = Status.CLOSED; } + else if (packet.ACK) + { + AckNumber = packet.SequenceNumber + 1; + SequenceNumber = packet.AckNumber; + + Status = Status.ESTABLISHED; + } else { throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_SENT)"); From fedb00550cf22a6e7d860c29fafb85fc2fb1f8ee Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 11 May 2021 15:27:14 +0200 Subject: [PATCH 143/314] Remove useless connection status (WAITING_ACK) + Close connection for each exception --- .../Network/IPv4/TCP/TCPClient.cs | 64 +++++++++++++++---- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index ea4496d593..af6681eee4 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -29,8 +29,7 @@ public enum Status CLOSING, LAST_ACK, TIME_WAIT, - CLOSED, - WAITING_ACK + CLOSED } /// @@ -85,6 +84,8 @@ public class TcpClient : IDisposable /// private uint LastSequenceNumber; + private bool WaitingAck = false; + /// /// Assign clients dictionary. /// @@ -239,7 +240,7 @@ public void Send(byte[] data) OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - Status = Status.WAITING_ACK; + WaitingAck = true; SequenceNumber += (uint)data.Length; } @@ -253,7 +254,7 @@ public void Send(byte[] data) /// Thrown if TCP Status is not ESTABLISHED. public byte[] NonBlockingReceive(ref EndPoint source) { - if (Status != Status.ESTABLISHED || Status == Status.WAITING_ACK) + if (Status != Status.ESTABLISHED) { throw new Exception("Client must be connected before receiving data."); } @@ -278,7 +279,7 @@ public byte[] NonBlockingReceive(ref EndPoint source) /// Thrown if TCP Status is not ESTABLISHED. public byte[] Receive(ref EndPoint source) { - if (Status != Status.ESTABLISHED || Status == Status.WAITING_ACK) + if (Status != Status.ESTABLISHED) { throw new Exception("Client must be connected before receiving data."); } @@ -319,6 +320,8 @@ internal void ReceiveData(TCPPacket packet) } else { + Status = Status.CLOSED; + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSED||LISTEN)"); } } @@ -336,6 +339,8 @@ internal void ReceiveData(TCPPacket packet) } else { + Status = Status.CLOSED; + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_RECEIVED)"); } } @@ -352,39 +357,58 @@ internal void ReceiveData(TCPPacket packet) } else if (packet.SYN) { + Status = Status.CLOSED; + throw new NotImplementedException("Simultaneous open not supported."); } - else if (packet.RST && packet.ACK) + else if (packet.RST) { Status = Status.CLOSED; + + throw new Exception("Connection refused by remote computer."); } else if (packet.ACK) { - AckNumber = packet.SequenceNumber + 1; - SequenceNumber = packet.AckNumber; + Status = Status.CLOSED; - Status = Status.ESTABLISHED; + throw new NotImplementedException("Connecting to an existing connection is not implemented."); } else { + Status = Status.CLOSED; + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_SENT)"); } } - else if (Status == Status.ESTABLISHED || Status == Status.WAITING_ACK) + else if (Status == Status.ESTABLISHED) { if (packet.RST) { Status = Status.CLOSED; + + throw new Exception("TCP Connection resetted!"); } if (packet.TCPFlags == (byte)Flags.ACK) { - if (Status == Status.WAITING_ACK) + if (WaitingAck) { - Status = Status.ESTABLISHED; + if (SequenceNumber == packet.AckNumber) + { + WaitingAck = false; + } } else { - throw new NotImplementedException("TCP sequencing is not supported yet! (sent packet size is too huge)"); + if (packet.SequenceNumber > AckNumber) + { + SequenceNumber++; + + SendEmptyPacket(Flags.RST); + + Status = Status.CLOSED; + + throw new NotImplementedException("TCP sequencing is not supported yet! (sent packet size is too huge)"); + } } } if (packet.FIN && packet.ACK) @@ -420,8 +444,14 @@ internal void ReceiveData(TCPPacket packet) SendEmptyPacket(Flags.ACK); } } + else if (packet.ACK) + { + //DO NOTHING + } else { + Status = Status.CLOSED; + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=ESTABLISHED)"); } } @@ -449,6 +479,8 @@ internal void ReceiveData(TCPPacket packet) } else { + Status = Status.CLOSED; + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT1)"); } } @@ -464,6 +496,8 @@ internal void ReceiveData(TCPPacket packet) } else { + Status = Status.CLOSED; + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT2)"); } } @@ -475,6 +509,8 @@ internal void ReceiveData(TCPPacket packet) } else { + Status = Status.CLOSED; + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSING)"); } } @@ -486,6 +522,8 @@ internal void ReceiveData(TCPPacket packet) } else { + Status = Status.CLOSED; + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSE_WAIT||LAST_ACK)"); } } From bddce8c9058ce1126ccb6900acbb5f634fabbf84 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 11 May 2021 15:44:50 +0200 Subject: [PATCH 144/314] Parse options again --- .../Network/IPv4/TCP/TCPPacket.cs | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 270f855c1d..1acb3ccbef 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -223,34 +223,31 @@ protected override void InitFields() PSH = (RawData[47] & (byte)Flags.PSH) != 0; RST = (RawData[47] & (byte)Flags.RST) != 0; - if (RawData.Length == (DataOffset + TCPHeaderLength)) //no data + if (TCPHeaderLength > 20) //options { - if (TCPHeaderLength > 20) //options + Options = new List(); + + for (int i = 0; i < TCP_DataLength; i++) { - Options = new List(); + var option = new TCPOption(); + option.Kind = RawData[DataOffset + 20 + i]; - for (int i = 0; i < RawData.Length - (DataOffset + 20); i++) + if (option.Kind != 1) //NOP { - var option = new TCPOption(); - option.Kind = RawData[DataOffset + 20 + i]; + option.Length = RawData[DataOffset + 20 + i + 1]; - if (option.Kind != 1) //NOP + if (option.Length != 2) { - option.Length = RawData[DataOffset + 20 + i + 1]; - - if (option.Length != 2) + option.Data = new byte[option.Length - 2]; + for (int j = 0; j < option.Length - 2; j++) { - option.Data = new byte[option.Length - 2]; - for (int j = 0; j < option.Length - 2; j++) - { - option.Data[j] = RawData[DataOffset + 20 + i + 2 + j]; - } + option.Data[j] = RawData[DataOffset + 20 + i + 2 + j]; } + } - Options.Add(option); + Options.Add(option); - i += option.Length - 1; - } + i += option.Length - 1; } } } From 212f16d0b3547c4789ba0f8dcc1e30a780b08199 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 11 May 2021 16:28:59 +0200 Subject: [PATCH 145/314] Update Network.md --- Docs/articles/Kernel/Network.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index 92d583b09a..043ab4766e 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -1,6 +1,6 @@ # Network -In this article we will discuss about Networking on Cosmos, how to use the Network Stack, send and received packets. For now, available protocols are **ARP**, **IPv4**, **UDP**, **ICMP**, **DHCP** and **DNS** but the team is also working on TCP. Note that Cosmos devkit must be installed for this article. +In this article we will discuss about Networking on Cosmos, how to use the Network Stack, send and received packets. For now, available protocols are **ARP**, **IPv4**, **TCP**, **UDP**, **ICMP**, **DHCP** and **DNS**. Note that Cosmos devkit must be installed for this article. All protocols here don't necessary support every feature described by their RFC and may have some bugs or architecture issues, if you find bugs or something abnormal please [submit an issue](http://https://github.com/CosmosOS/Cosmos/issues/new/choose "repository") on our repository. From be9e5cb1b8e8a6328dad0e798d2caf033f02ee6c Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 12 May 2021 14:14:19 +0200 Subject: [PATCH 146/314] Packet sequencing working on received packets. --- .../Network/IPv4/TCP/TCPClient.cs | 59 +++++++++++++++---- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index af6681eee4..1a6c6c8b7a 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -86,6 +86,8 @@ public class TcpClient : IDisposable private bool WaitingAck = false; + private byte[] data; + /// /// Assign clients dictionary. /// @@ -236,7 +238,7 @@ public void Send(byte[] data) throw new Exception("Client must be connected before sending data."); } - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, 0x18, 0xFAF0, 0, data); + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)(Flags.PSH | Flags.ACK), 0xFAF0, 0, data); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); @@ -263,11 +265,13 @@ public byte[] NonBlockingReceive(ref EndPoint source) return null; } - var packet = new TCPPacket(rxBuffer.Dequeue().RawData); + var packet = rxBuffer.Dequeue(); source.address = packet.SourceIP; source.port = packet.SourcePort; - return packet.TCP_Data; + var tmp = data; + data = null; + return tmp; } /// @@ -285,11 +289,13 @@ public byte[] Receive(ref EndPoint source) } while (rxBuffer.Count < 1); - var packet = new TCPPacket(rxBuffer.Dequeue().RawData); + var packet = rxBuffer.Dequeue(); source.address = packet.SourceIP; source.port = packet.SourcePort; - return packet.TCP_Data; + var tmp = data; + data = null; + return tmp; } /// @@ -351,6 +357,8 @@ internal void ReceiveData(TCPPacket packet) AckNumber = packet.SequenceNumber + 1; SequenceNumber++; + LastSequenceNumber = packet.SequenceNumber; + SendEmptyPacket(Flags.ACK); Status = Status.ESTABLISHED; @@ -399,15 +407,11 @@ internal void ReceiveData(TCPPacket packet) } else { - if (packet.SequenceNumber > AckNumber) + if (packet.SequenceNumber >= AckNumber && packet.TCP_DataLength > 0) //packet sequencing { - SequenceNumber++; - - SendEmptyPacket(Flags.RST); + AckNumber += packet.TCP_DataLength; - Status = Status.CLOSED; - - throw new NotImplementedException("TCP sequencing is not supported yet! (sent packet size is too huge)"); + data = Concat(data, packet.TCP_Data); } } } @@ -439,6 +443,8 @@ internal void ReceiveData(TCPPacket packet) LastSequenceNumber = packet.SequenceNumber; + data = Concat(data, packet.TCP_Data); + rxBuffer.Enqueue(packet); SendEmptyPacket(Flags.ACK); @@ -531,6 +537,35 @@ internal void ReceiveData(TCPPacket packet) #region Utils + /// + /// Contatenate two byte arrays. https://stackoverflow.com/a/45531730 + /// + private byte[] Concat(byte[] a, byte[] b) + { + byte[] output; + int alen; + + if (a == null) + { + output = new byte[b.Length]; + alen = 0; + } + else + { + output = new byte[a.Length + b.Length]; + alen = a.Length; + for (int i = 0; i < a.Length; i++) + { + output[i] = a[i]; + } + } + for (int j = 0; j < b.Length; j++) + { + output[alen + j] = b[j]; + } + return output; + } + /// /// Wait until remote receive ACK of its connection termination request. /// From 0d3eee5cd775f4f6901c64afdde64a3b366d1632 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 12 May 2021 14:50:19 +0200 Subject: [PATCH 147/314] [WIP] Packet sequencing on sent packets. --- .../Network/IPv4/TCP/TCPClient.cs | 49 +++++++++++++++---- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 1a6c6c8b7a..78c5e7493a 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -229,22 +229,36 @@ public void Send(byte[] data) { throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); } + if (Status != Status.ESTABLISHED) + { + throw new Exception("Client must be connected before sending data."); + } if (data.Length > 1500) { throw new NotImplementedException("Data length must be less than 1500 bytes (yet!)"); } - if (Status != Status.ESTABLISHED) + if (data.Length > 1500) //should never go here { - throw new Exception("Client must be connected before sending data."); - } + var chunks = BufferSplit(data, 537); - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)(Flags.PSH | Flags.ACK), 0xFAF0, 0, data); - OutgoingBuffer.AddPacket(packet); - NetworkStack.Update(); + for (int i = 0; i < chunks.Length; i++) + { + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, i == chunks.Length - 2 ? (byte)(Flags.PSH | Flags.ACK) : (byte)(Flags.ACK), 0xFAF0, 0, chunks[i]); + OutgoingBuffer.AddPacket(packet); + NetworkStack.Update(); - WaitingAck = true; + SequenceNumber += (uint)chunks[i].Length; + } + } + else + { + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)(Flags.PSH | Flags.ACK), 0xFAF0, 0, data); + OutgoingBuffer.AddPacket(packet); + NetworkStack.Update(); - SequenceNumber += (uint)data.Length; + SequenceNumber += (uint)data.Length; + } + WaitingAck = true; } /// @@ -543,12 +557,11 @@ internal void ReceiveData(TCPPacket packet) private byte[] Concat(byte[] a, byte[] b) { byte[] output; - int alen; + int alen = 0; if (a == null) { output = new byte[b.Length]; - alen = 0; } else { @@ -566,6 +579,22 @@ private byte[] Concat(byte[] a, byte[] b) return output; } + /// + /// Split byte array into chunks. https://stackoverflow.com/a/50655528 + /// + public static byte[][] BufferSplit(byte[] buffer, int blockSize) + { + byte[][] blocks = new byte[(buffer.Length + blockSize - 1) / blockSize][]; + + for (int i = 0, j = 0; i < blocks.Length; i++, j += blockSize) + { + blocks[i] = new byte[Math.Min(blockSize, buffer.Length - j)]; + Array.Copy(buffer, j, blocks[i], 0, blocks[i].Length); + } + + return blocks; + } + /// /// Wait until remote receive ACK of its connection termination request. /// From 6ae829a8e7ba62e9c6a9ced4619c5ee8ef29235a Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 12 May 2021 16:57:45 +0200 Subject: [PATCH 148/314] TCP Sequencing out working Remember that CRC calculation only wants even number --- .../Cosmos.System2/Network/IPv4/IPPacket.cs | 5 ++- .../Network/IPv4/TCP/TCPClient.cs | 33 +++++++++++-------- .../Network/IPv4/TCP/TCPPacket.cs | 18 ++++------ 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/IPPacket.cs b/source/Cosmos.System2/Network/IPv4/IPPacket.cs index 2e212b1e79..e018948e20 100644 --- a/source/Cosmos.System2/Network/IPv4/IPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/IPPacket.cs @@ -34,9 +34,8 @@ public class IPPacket : EthernetPacket /// Thrown if packetData array length is greater than Int32.MaxValue. internal static void IPv4Handler(byte[] packetData) { - IPPacket ip_packet = new IPPacket(packetData); - //Sys.Console.WriteLine("Received IP Packet"); - //Sys.Console.WriteLine(ip_packet.ToString()); + var ip_packet = new IPPacket(packetData); + if (ip_packet.SourceIP == null) { Global.mDebugger.Send("SourceIP null in IPv4Handler!"); diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 78c5e7493a..88a00f8793 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -233,13 +233,9 @@ public void Send(byte[] data) { throw new Exception("Client must be connected before sending data."); } - if (data.Length > 1500) + if (data.Length > 536) { - throw new NotImplementedException("Data length must be less than 1500 bytes (yet!)"); - } - if (data.Length > 1500) //should never go here - { - var chunks = BufferSplit(data, 537); + var chunks = ArraySplit(data, 536); for (int i = 0; i < chunks.Length; i++) { @@ -580,19 +576,28 @@ private byte[] Concat(byte[] a, byte[] b) } /// - /// Split byte array into chunks. https://stackoverflow.com/a/50655528 + /// Split byte array into chunks of a specified size. /// - public static byte[][] BufferSplit(byte[] buffer, int blockSize) + private byte[][] ArraySplit(byte[] buffer, int chunksize = 1000) { - byte[][] blocks = new byte[(buffer.Length + blockSize - 1) / blockSize][]; + var size = buffer.Length; + var chunkCount = (buffer.Length + chunksize - 1) / chunksize; + var bufferArray = new byte[chunkCount][]; + int index = 0; - for (int i = 0, j = 0; i < blocks.Length; i++, j += blockSize) + for (var i = 0; i < chunkCount; i++) { - blocks[i] = new byte[Math.Min(blockSize, buffer.Length - j)]; - Array.Copy(buffer, j, blocks[i], 0, blocks[i].Length); + bufferArray[i] = new byte[Math.Min(chunksize, buffer.Length - i * chunksize)]; } - - return blocks; + for (var i = 0; i < chunkCount; i++) + { + for (var j = 0; j < bufferArray[i].Length; j++) + { + bufferArray[i][j] = buffer[index]; + index++; + } + } + return bufferArray; } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 1acb3ccbef..d84e6674fa 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -282,7 +282,7 @@ internal void AddRawData(byte[] raw) /// byte array value. internal byte[] MakeHeader() { - byte[] header = new byte[12 + (RawData.Length - DataOffset)]; + byte[] header = new byte[12 + (TCPHeaderLength + TCP_DataLength)]; /* Pseudo Header */ //Addresses @@ -295,13 +295,13 @@ internal byte[] MakeHeader() header[8] = 0x00; //Protocol (TCP) header[9] = 0x06; - ushort tcplen = (ushort)(RawData.Length - DataOffset); + ushort tcplen = (ushort)(TCPHeaderLength + TCP_DataLength); //TCP Length header[10] = (byte)((tcplen >> 8) & 0xFF); header[11] = (byte)((tcplen >> 0) & 0xFF); /* TCP Packet */ - for (int i = 0; i < RawData.Length - DataOffset; i++) + for (int i = 0; i < tcplen; i++) { header[12 + i] = RawData[DataOffset + i]; } @@ -315,16 +315,10 @@ internal byte[] MakeHeader() /// True if checksum correct, False otherwise. private bool CheckCRC() { - /*byte[] header = MakeHeader(); + //byte[] header = MakeHeader(); + + //return CalcOcCRC(header, 0, header.Length) == Checksum; - if (CalcOcCRC(header, 0, header.Length) == checksum) - { - return true; - } - else - { - return false; - }*/ return true; } From ac1d534e0dedd2edce35d52871549fab3957a24b Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 13 May 2021 11:57:00 +0200 Subject: [PATCH 149/314] Fix #1775 + Open existing connection --- .../Cosmos.System2/Network/IPv4/IPPacket.cs | 24 +++++++++++++------ .../Network/IPv4/TCP/TCPClient.cs | 9 +++---- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/IPPacket.cs b/source/Cosmos.System2/Network/IPv4/IPPacket.cs index e018948e20..5761d231d1 100644 --- a/source/Cosmos.System2/Network/IPv4/IPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/IPPacket.cs @@ -192,16 +192,26 @@ public IPPacket(MACAddress srcMAC, MACAddress destMAC, ushort dataLength, byte p /// ushort value. protected static ushort CalcOcCRC(byte[] buffer, ushort offset, int length) { - uint crc = 0; + return (ushort)~SumShortValues(buffer, offset, length); + } + + protected static ushort SumShortValues(byte[] buffer, int offset, int length) + { + uint chksum = 0; + int end = offset + (length & ~1); + int i = offset; - for (ushort w = offset; w < offset + length; w += 2) + while (i != end) { - crc += (ushort)((buffer[w] << 8) | buffer[w + 1]); + chksum += (uint)((((ushort)buffer[i++]) << 8) + (ushort)buffer[i++]); } - - crc = (~((crc & 0xFFFF) + (crc >> 16))); - - return (ushort)crc; + if (i != offset + length) + { + chksum += (uint)(((ushort)buffer[i]) << 8); + } + chksum = (chksum & 0xFFFF) + (chksum >> 16); + chksum = (chksum & 0xFFFF) + (chksum >> 16); + return (ushort)chksum; } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 88a00f8793..9f2c39044f 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -252,7 +252,7 @@ public void Send(byte[] data) OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - SequenceNumber += (uint)data.Length; + SequenceNumber += (uint)data.Length; } WaitingAck = true; } @@ -297,7 +297,7 @@ public byte[] Receive(ref EndPoint source) { throw new Exception("Client must be connected before receiving data."); } - while (rxBuffer.Count < 1); + while (rxBuffer.Count < 1) ; var packet = rxBuffer.Dequeue(); source.address = packet.SourceIP; @@ -387,9 +387,10 @@ internal void ReceiveData(TCPPacket packet) } else if (packet.ACK) { - Status = Status.CLOSED; + AckNumber = packet.SequenceNumber; + SequenceNumber = packet.AckNumber; - throw new NotImplementedException("Connecting to an existing connection is not implemented."); + Status = Status.ESTABLISHED; } else { From 2dee94877e387bdde6495a66fc65a90d6fd3c2fa Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 13 May 2021 19:51:11 +0200 Subject: [PATCH 150/314] Change if forest to switch case --- .../Network/IPv4/TCP/TCPClient.cs | 413 +++++++++++------- 1 file changed, 247 insertions(+), 166 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 9f2c39044f..a4f46b2f2b 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -316,236 +316,317 @@ public byte[] Receive(ref EndPoint source) /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { - if (Status == Status.LISTEN || Status == Status.CLOSED) + switch (Status) { - if (packet.SYN) - { - Status = Status.SYN_RECEIVED; + case Status.LISTEN: + ProcessListen(packet); + break; + case Status.SYN_SENT: + ProcessSynSent(packet); + break; + case Status.SYN_RECEIVED: + ProcessSynReceived(packet); + break; + case Status.ESTABLISHED: + ProcessEstablished(packet); + break; + case Status.FIN_WAIT1: + ProcessFinWait1(packet); + break; + case Status.FIN_WAIT2: + ProcessFinWait2(packet); + break; + case Status.CLOSE_WAIT: + ProcessCloseWait(packet); + break; + case Status.CLOSING: + ProcessClosing(packet); + break; + case Status.LAST_ACK: + ProcessCloseWait(packet); + break; + case Status.TIME_WAIT: + break; + case Status.CLOSED: + ProcessListen(packet); + break; + default: + throw new Exception("Unknown TCP connection state."); + } + } - source = IPConfig.FindNetwork(packet.SourceIP); + #region Process Status - AckNumber = packet.SequenceNumber + 1; + /// + /// Process LISTEN Status. + /// + /// Packet to receive. + public void ProcessListen(TCPPacket packet) + { + if (packet.SYN) + { + Status = Status.SYN_RECEIVED; - var rnd = new Random(); - SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); + source = IPConfig.FindNetwork(packet.SourceIP); - destination = packet.SourceIP; - destinationPort = packet.SourcePort; + AckNumber = packet.SequenceNumber + 1; - SendEmptyPacket(Flags.SYN | Flags.ACK); - } - else - { - Status = Status.CLOSED; + var rnd = new Random(); + SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSED||LISTEN)"); - } + destination = packet.SourceIP; + destinationPort = packet.SourcePort; + + SendEmptyPacket(Flags.SYN | Flags.ACK); } - else if (Status == Status.SYN_RECEIVED) + else { - if (packet.RST) - { - Status = Status.LISTEN; - } - else if (packet.ACK) - { - Status = Status.ESTABLISHED; + Status = Status.CLOSED; - SequenceNumber++; - } - else - { - Status = Status.CLOSED; + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSED||LISTEN)"); + } + } - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_RECEIVED)"); - } + /// + /// Process SYN_RECEIVED Status. + /// + /// Packet to receive. + public void ProcessSynReceived(TCPPacket packet) + { + if (packet.RST) + { + Status = Status.LISTEN; } - else if (Status == Status.SYN_SENT) + else if (packet.ACK) { - if (packet.SYN && packet.ACK) - { - AckNumber = packet.SequenceNumber + 1; - SequenceNumber++; + Status = Status.ESTABLISHED; - LastSequenceNumber = packet.SequenceNumber; + SequenceNumber++; + } + else + { + Status = Status.CLOSED; - SendEmptyPacket(Flags.ACK); + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_RECEIVED)"); + } + } - Status = Status.ESTABLISHED; - } - else if (packet.SYN) - { - Status = Status.CLOSED; + /// + /// Process SYN_SENT Status. + /// + /// Packet to receive. + public void ProcessSynSent(TCPPacket packet) + { + if (packet.SYN && packet.ACK) + { + AckNumber = packet.SequenceNumber + 1; + SequenceNumber++; - throw new NotImplementedException("Simultaneous open not supported."); - } - else if (packet.RST) - { - Status = Status.CLOSED; + LastSequenceNumber = packet.SequenceNumber; - throw new Exception("Connection refused by remote computer."); - } - else if (packet.ACK) - { - AckNumber = packet.SequenceNumber; - SequenceNumber = packet.AckNumber; + SendEmptyPacket(Flags.ACK); - Status = Status.ESTABLISHED; - } - else - { - Status = Status.CLOSED; + Status = Status.ESTABLISHED; + } + else if (packet.SYN) + { + Status = Status.CLOSED; - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_SENT)"); - } + throw new NotImplementedException("Simultaneous open not supported."); } - else if (Status == Status.ESTABLISHED) + else if (packet.RST) { - if (packet.RST) - { - Status = Status.CLOSED; + Status = Status.CLOSED; - throw new Exception("TCP Connection resetted!"); - } - if (packet.TCPFlags == (byte)Flags.ACK) + throw new Exception("Connection refused by remote computer."); + } + else if (packet.ACK) + { + AckNumber = packet.SequenceNumber; + SequenceNumber = packet.AckNumber; + + Status = Status.ESTABLISHED; + } + else + { + Status = Status.CLOSED; + + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_SENT)"); + } + } + + /// + /// Process ESTABLISHED Status. + /// + /// Packet to receive. + public void ProcessEstablished(TCPPacket packet) + { + if (packet.RST) + { + Status = Status.CLOSED; + + throw new Exception("TCP Connection resetted!"); + } + if (packet.TCPFlags == (byte)Flags.ACK) + { + if (WaitingAck) { - if (WaitingAck) + if (SequenceNumber == packet.AckNumber) { - if (SequenceNumber == packet.AckNumber) - { - WaitingAck = false; - } + WaitingAck = false; } - else + } + else + { + if (packet.SequenceNumber >= AckNumber && packet.TCP_DataLength > 0) //packet sequencing { - if (packet.SequenceNumber >= AckNumber && packet.TCP_DataLength > 0) //packet sequencing - { - AckNumber += packet.TCP_DataLength; + AckNumber += packet.TCP_DataLength; - data = Concat(data, packet.TCP_Data); - } + data = Concat(data, packet.TCP_Data); } } - if (packet.FIN && packet.ACK) - { - AckNumber++; + } + if (packet.FIN && packet.ACK) + { + AckNumber++; - SendEmptyPacket(Flags.ACK); + SendEmptyPacket(Flags.ACK); - WaitAndClose(); - } - else if (packet.FIN) - { - AckNumber++; + WaitAndClose(); + } + else if (packet.FIN) + { + AckNumber++; - SendEmptyPacket(Flags.ACK); + SendEmptyPacket(Flags.ACK); - Status = Status.CLOSE_WAIT; + Status = Status.CLOSE_WAIT; - SendEmptyPacket(Flags.FIN); + SendEmptyPacket(Flags.FIN); - Status = Status.LAST_ACK; - } - else if (packet.PSH && packet.ACK) + Status = Status.LAST_ACK; + } + else if (packet.PSH && packet.ACK) + { + if (packet.SequenceNumber > LastSequenceNumber) //dup check { - if (packet.SequenceNumber > LastSequenceNumber) //dup check - { - AckNumber += packet.TCP_DataLength; + AckNumber += packet.TCP_DataLength; - LastSequenceNumber = packet.SequenceNumber; + LastSequenceNumber = packet.SequenceNumber; - data = Concat(data, packet.TCP_Data); + data = Concat(data, packet.TCP_Data); - rxBuffer.Enqueue(packet); + rxBuffer.Enqueue(packet); - SendEmptyPacket(Flags.ACK); - } - } - else if (packet.ACK) - { - //DO NOTHING + SendEmptyPacket(Flags.ACK); } - else - { - Status = Status.CLOSED; + } + else if (packet.ACK) + { + //DO NOTHING + } + else + { + Status = Status.CLOSED; - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=ESTABLISHED)"); - } + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=ESTABLISHED)"); } - else if (Status == Status.FIN_WAIT1) + } + + /// + /// Process FIN_WAIT1 Status. + /// + /// Packet to receive. + public void ProcessFinWait1(TCPPacket packet) + { + if (packet.FIN && packet.ACK) { - if (packet.FIN && packet.ACK) - { - AckNumber++; + AckNumber++; - SendEmptyPacket(Flags.ACK); + SendEmptyPacket(Flags.ACK); - WaitAndClose(); - } - else if (packet.FIN) - { - AckNumber++; + WaitAndClose(); + } + else if (packet.FIN) + { + AckNumber++; - SendEmptyPacket(Flags.ACK); + SendEmptyPacket(Flags.ACK); - Status = Status.CLOSING; - } - else if (packet.ACK) - { - Status = Status.FIN_WAIT2; - } - else - { - Status = Status.CLOSED; + Status = Status.CLOSING; + } + else if (packet.ACK) + { + Status = Status.FIN_WAIT2; + } + else + { + Status = Status.CLOSED; - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT1)"); - } + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT1)"); } - else if (Status == Status.FIN_WAIT2) + } + + /// + /// Process FIN_WAIT2 Status. + /// + /// Packet to receive. + public void ProcessFinWait2(TCPPacket packet) + { + if (packet.FIN) { - if (packet.FIN) - { - AckNumber++; + AckNumber++; - SendEmptyPacket(Flags.ACK); + SendEmptyPacket(Flags.ACK); - WaitAndClose(); - } - else - { - Status = Status.CLOSED; + WaitAndClose(); + } + else + { + Status = Status.CLOSED; - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT2)"); - } + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT2)"); } - else if (Status == Status.CLOSING) + } + + /// + /// Process CLOSING Status. + /// + /// Packet to receive. + public void ProcessClosing(TCPPacket packet) + { + if (packet.ACK) { - if (packet.ACK) - { - WaitAndClose(); - } - else - { - Status = Status.CLOSED; + WaitAndClose(); + } + else + { + Status = Status.CLOSED; - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSING)"); - } + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSING)"); + } + } + + /// + /// Process Close_WAIT Status. + /// + /// Packet to receive. + public void ProcessCloseWait(TCPPacket packet) + { + if (packet.ACK) + { + Status = Status.CLOSED; } - else if (Status == Status.CLOSE_WAIT || Status == Status.LAST_ACK) + else { - if (packet.ACK) - { - Status = Status.CLOSED; - } - else - { - Status = Status.CLOSED; + Status = Status.CLOSED; - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSE_WAIT||LAST_ACK)"); - } + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSE_WAIT||LAST_ACK)"); } } + #endregion + #region Utils /// From d9878c376a36d0c8ec2fce3553c59cf2cf3fe6f1 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 18 May 2021 18:35:54 +0200 Subject: [PATCH 151/314] Add more cases on LISTEN + SYN_SENT + Typo --- .../Network/IPv4/TCP/TCPClient.cs | 91 +++++++++++++------ 1 file changed, 65 insertions(+), 26 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index a4f46b2f2b..ccd009b279 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -348,7 +348,7 @@ internal void ReceiveData(TCPPacket packet) case Status.TIME_WAIT: break; case Status.CLOSED: - ProcessListen(packet); + ProcessListen(packet); //TODO: ProcessClose + TcpListener break; default: throw new Exception("Unknown TCP connection state."); @@ -363,7 +363,27 @@ internal void ReceiveData(TCPPacket packet) /// Packet to receive. public void ProcessListen(TCPPacket packet) { - if (packet.SYN) + if (packet.RST) + { + Status = Status.CLOSED; + + throw new Exception("TCP connection resetted! (RST received on LISTEN state)"); + } + else if (packet.FIN) + { + Status = Status.CLOSED; + + throw new Exception("TCP connection closed! (FIN received on LISTEN state)"); + } + else if (packet.ACK) + { + SendEmptyPacket(Flags.RST); + + Status = Status.CLOSED; + + throw new Exception("TCP connection closed! (ACK received on LISTEN state)"); + } + else if (packet.SYN) { Status = Status.SYN_RECEIVED; @@ -417,22 +437,18 @@ public void ProcessSynReceived(TCPPacket packet) /// Packet to receive. public void ProcessSynSent(TCPPacket packet) { - if (packet.SYN && packet.ACK) + if (packet.FIN) { - AckNumber = packet.SequenceNumber + 1; - SequenceNumber++; - - LastSequenceNumber = packet.SequenceNumber; - - SendEmptyPacket(Flags.ACK); + Status = Status.CLOSED; - Status = Status.ESTABLISHED; + throw new Exception("TCP connection closed! (FIN received on SYN_SENT state)"); } - else if (packet.SYN) + else if (packet.TCPFlags == (byte)Flags.ACK) { - Status = Status.CLOSED; + AckNumber = packet.SequenceNumber; + SequenceNumber = packet.AckNumber; - throw new NotImplementedException("Simultaneous open not supported."); + Status = Status.ESTABLISHED; } else if (packet.RST) { @@ -440,12 +456,31 @@ public void ProcessSynSent(TCPPacket packet) throw new Exception("Connection refused by remote computer."); } - else if (packet.ACK) + else if (packet.SYN) { - AckNumber = packet.SequenceNumber; - SequenceNumber = packet.AckNumber; + if (packet.ACK) + { + AckNumber = packet.SequenceNumber + 1; + SequenceNumber++; - Status = Status.ESTABLISHED; + LastSequenceNumber = packet.SequenceNumber; + + SendEmptyPacket(Flags.ACK); + + Status = Status.ESTABLISHED; + } + else if (packet.TCPFlags == (byte)Flags.SYN) + { + Status = Status.CLOSED; + + throw new NotImplementedException("Simultaneous open not supported."); + } + else + { + Status = Status.CLOSED; + + throw new Exception("TCP connection closed! (Flag " + packet.TCPFlags + " received on SYN_SENT state)"); + } } else { @@ -632,27 +667,29 @@ public void ProcessCloseWait(TCPPacket packet) /// /// Contatenate two byte arrays. https://stackoverflow.com/a/45531730 /// - private byte[] Concat(byte[] a, byte[] b) + /// First byte array. + /// Byte array to concatenate. + private byte[] Concat(byte[] first, byte[] second) { byte[] output; int alen = 0; - if (a == null) + if (first == null) { - output = new byte[b.Length]; + output = new byte[second.Length]; } else { - output = new byte[a.Length + b.Length]; - alen = a.Length; - for (int i = 0; i < a.Length; i++) + output = new byte[first.Length + second.Length]; + alen = first.Length; + for (int i = 0; i < first.Length; i++) { - output[i] = a[i]; + output[i] = first[i]; } } - for (int j = 0; j < b.Length; j++) + for (int j = 0; j < second.Length; j++) { - output[alen + j] = b[j]; + output[alen + j] = second[j]; } return output; } @@ -660,6 +697,8 @@ private byte[] Concat(byte[] a, byte[] b) /// /// Split byte array into chunks of a specified size. /// + /// Byte array to split. + /// Chunk size. private byte[][] ArraySplit(byte[] buffer, int chunksize = 1000) { var size = buffer.Length; From 90573b5ac30dca92f239f8b20617dab2d1780f7b Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Thu, 20 May 2021 17:24:32 -0400 Subject: [PATCH 152/314] Add basic ATAPI support --- source/Cosmos.Core/IOGroup/ATA.cs | 107 ++++------ source/Cosmos.HAL2/BlockDevice/ATAPI.cs | 244 +++++++++++++++++++++++ source/Cosmos.HAL2/BlockDevice/AtaPio.cs | 2 +- source/Cosmos.HAL2/BlockDevice/IDE.cs | 21 +- 4 files changed, 297 insertions(+), 77 deletions(-) create mode 100644 source/Cosmos.HAL2/BlockDevice/ATAPI.cs diff --git a/source/Cosmos.Core/IOGroup/ATA.cs b/source/Cosmos.Core/IOGroup/ATA.cs index 3375fac6c5..157e2be6bc 100644 --- a/source/Cosmos.Core/IOGroup/ATA.cs +++ b/source/Cosmos.Core/IOGroup/ATA.cs @@ -7,61 +7,26 @@ namespace Cosmos.Core.IOGroup { - /// - /// IOGruop ATA. - /// public class ATA : IOGroup { - /// - /// Data IOPort. - /// - public readonly IOPort Data; - //* Error Register: BAR0 + 1; // Read Only - //* Features Register: BAR0 + 1; // Write Only - /// - /// Sector count IOPort. - /// - public readonly IOPortWrite SectorCount; - // ATA_REG_SECCOUNT1 0x08 - HOB - /// - /// LBA0 IOPort. - /// - public readonly IOPort LBA0; - /// - /// LBA1 IOPort. - /// - public readonly IOPort LBA1; - /// - /// LBA2 IOPort. - /// - public readonly IOPort LBA2; - // ATA_REG_LBA3 0x09 - HOB - // ATA_REG_LBA4 0x0A - HOB - // ATA_REG_LBA5 0x0B - HOB - /// - /// Device select IOPort. - /// - public readonly IOPortWrite DeviceSelect; - /// - /// Command IOPort. - /// - public readonly IOPortWrite Command; - /// - /// Status IOPort. - /// - public readonly IOPortRead Status; - //* Alternate Status Register: BAR1 + 2; // Read Only. - /// - /// Control IOPort. - /// - public readonly IOPortWrite Control; - //* DEVADDRESS: BAR1 + 2; // I don't know what is the benefit from this register + public readonly IOPort Error; // BAR0 + 1 - read only + public readonly IOPortWrite Features; // BAR0 + 1 - write only + public readonly IOPort Data; // BAR0 + public readonly IOPort SectorCount; // BAR0 + 2 + public readonly IOPort LBA0; // BAR0 + 3 + public readonly IOPort LBA1; // BAR0 + 4 + public readonly IOPort LBA2; // BAR0 + 5 + public readonly IOPort DeviceSelect; // BAR0 + 6 + public readonly IOPortWrite Command; // BAR0 + 7 - write only + public readonly IOPortRead Status; // BAR0 + 7 - read only + public readonly IOPort SectorCountLBA48; // BAR0 + 8 + public readonly IOPort LBA3; // BAR0 + 9 + public readonly IOPort LBA4; // BAR0 + 10 + public readonly IOPort LBA5; // BAR0 + 11 + public readonly IOPortRead AlternateStatus; // BAR1 + 2 - read only + public readonly IOPortWrite Control; // BAR1 + 2 - write only - /// - /// Create new instance of the class. - /// - /// True if secondary ATA. - internal ATA(bool aSecondary) + public ATA(bool aSecondary) { if (aSecondary) { @@ -74,36 +39,44 @@ internal ATA(bool aSecondary) var xBAR0 = GetBAR0(aSecondary); var xBAR1 = GetBAR1(aSecondary); + Error = new IOPort(xBAR0, 1); + Features = new IOPortWrite(xBAR0, 1); Data = new IOPort(xBAR0); - SectorCount = new IOPortWrite(xBAR0, 2); + SectorCount = new IOPort(xBAR0, 2); LBA0 = new IOPort(xBAR0, 3); LBA1 = new IOPort(xBAR0, 4); LBA2 = new IOPort(xBAR0, 5); - Command = new IOPortWrite(xBAR0, 7); + DeviceSelect = new IOPort(xBAR0, 6); Status = new IOPortRead(xBAR0, 7); - DeviceSelect = new IOPortWrite(xBAR0, 6); + Command = new IOPortWrite(xBAR0, 7); + SectorCountLBA48 = new IOPort(xBAR0, 8); + LBA3 = new IOPort(xBAR0, 9); + LBA4 = new IOPort(xBAR0, 10); + LBA5 = new IOPort(xBAR0, 11); + AlternateStatus = new IOPortRead(xBAR1, 2); Control = new IOPortWrite(xBAR1, 2); } - /// - /// Get control base address. - /// - /// True if secondary ATA. - /// ushort value. + public void Wait() + { + // Used for the PATA and IOPort latency + // Widely accepted method is to read the status register 4 times - approx. 400ns delay. + byte wait; + wait = Status.Byte; + wait = Status.Byte; + wait = Status.Byte; + wait = Status.Byte; + } + private static ushort GetBAR1(bool aSecondary) { - UInt16 xBAR1 = (UInt16)(aSecondary ? 0x0374 : 0x03F4); + ushort xBAR1 = (ushort)(aSecondary ? 0x0374 : 0x03F4); return xBAR1; } - /// - /// Get command base address. - /// - /// True if secondary ATA. - /// ushort value. private static ushort GetBAR0(bool aSecondary) { - UInt16 xBAR0 = (UInt16)(aSecondary ? 0x0170 : 0x01F0); + ushort xBAR0 = (ushort)(aSecondary ? 0x0170 : 0x01F0); return xBAR0; } } diff --git a/source/Cosmos.HAL2/BlockDevice/ATAPI.cs b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs new file mode 100644 index 0000000000..f5fcb743d3 --- /dev/null +++ b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs @@ -0,0 +1,244 @@ +using System; +using System.Collections.Generic; +using Cosmos.Core; +using static Cosmos.HAL.BlockDevice.Ata; +using static Cosmos.HAL.BlockDevice.AtaPio; + +namespace Cosmos.HAL.BlockDevice +{ + public class ATAPI : BlockDevice + { + public static List ATAPIDevices = new List(); + protected static Core.IOGroup.ATA IO; + public const ushort SectorSize = 2048; + private bool Primary { get; set; } + private BusPositionEnum BusPosition { get; set; } + + public class PacketCommands + { + public static byte[] ReadSector = { (byte)AtaPio.Cmd.Read, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; + public static byte[] Unload = { (byte)AtaPio.Cmd.Eject, 0, 0, 0, 0x02, 0, 0, 0, 0, 0, 0, 0 }; + } + + public ATAPI(AtaPio parentDevice) + { + this.BusPosition = parentDevice.BusPosition; + this.Primary = parentDevice.ControllerID == ControllerIdEnum.Primary; + mBlockSize = SectorSize; + IO = new Core.IOGroup.ATA(!Primary); + + Devices.Add(this); + ATAPIDevices.Add(this); + + Init(); + } + + + public void Init() + { + if (Primary) + { + INTs.SetIrqHandler(0x0E, HandleIRQ); + } + else + { + INTs.SetIrqHandler(0x0F, HandleIRQ); + } + + IO.Control.Byte = 0; //Enable IRQs + IO.DeviceSelect.Byte = (byte)((byte)(DvcSelVal.Default | DvcSelVal.LBA | (BusPosition == BusPositionEnum.Slave ? DvcSelVal.Slave : 0)) | 0); + } + + public void Test() + { + Init(); + var b = new byte[] { 0, 0, 0 }; + ReadBlock(0, 1, ref b); + // PrintBytes(b); + Console.WriteLine("press enter for full test"); + Console.ReadLine(); + for (ulong i = 10; i < 100; i++) + { + ReadBlock(i, 1, ref b); + PrintBytes(b); + } + } + + private void HandleIRQ(ref INTs.IRQContext aContext) + { + Console.WriteLine("*****RECIVED IRQ*****"); + } + + public void PrintBytes(byte[] b) + { + for (int p = 0; p < b.Length - 1; p++) + { + Console.Write(b[p].ToString() + ","); + } + } + + public override void ReadBlock(ulong SectorNum, ulong SectorCount, ref byte[] aData) + { + if (SectorCount != 1) + { + throw new NotImplementedException("Reading more than one sectors is not supported. SectorCount: " + SectorCount); + } + + byte[] packet = new byte[12]; + packet[0] = (byte)AtaPio.Cmd.Read;//Read Sector + packet[1] = 0; + packet[2] = (byte)((SectorNum >> 24) & 0xFF);//MSB + packet[3] = (byte)((SectorNum >> 16) & 0xFF); + packet[4] = (byte)((SectorNum >> 8) & 0xFF); + packet[5] = (byte)((SectorNum >> 0) & 0xFF);//LSB + packet[6] = 0; + packet[7] = 0; + packet[8] = 0; + packet[9] = (byte)SectorCount;//Sector Count + packet[10] = 0; + packet[11] = 0; + + + + var buffer = new ushort[SectorSize / 2]; //Divide by 2 because we are reading words + SendCmd(packet, SectorSize, ref buffer); + + CheckForErrors(); + + //Poll + Poll(false); + + //Convert the buffer into bytes + byte[] array = new byte[SectorSize]; + int counter = 0; + for (int i = 0; i < (SectorSize / 2); i++) + { + var item = buffer[i]; + var bytes = BitConverter.GetBytes(item); + + //TODO: Is this correct order. + array[counter++] = bytes[0]; + array[counter++] = bytes[1]; + } + + //Return + aData = array; + } + + public override void WriteBlock(ulong aBlockNo, ulong aBlockCount, ref byte[] aData) + { + throw new NotImplementedException(); + } + + private void SendCmd(byte[] AtapiPacket, int size, ref ushort[] outputData) + { + Console.WriteLine("[ATAPI] Sending command"); + IO.Features.Byte = 0x00; //PIO Mode + IO.LBA1.Byte = (byte)((SectorSize) & 0xFF); + IO.LBA2.Byte = (byte)((SectorSize >> 8) & 0xFF); + IO.Command.Byte = (byte)AtaPio.Cmd.Packet; + AtaWait(true); + + for (int i = 0; i < AtapiPacket.Length; i++) + { + var b1 = AtapiPacket[i]; + var b2 = AtapiPacket[i + 1]; + + var toSend = BitConverter.ToUInt16(new byte[] { b1, b2 }, 0); + IO.Data.Word = toSend; + + i++; + } + CheckForErrors(); + var a = (IO.LBA2.Byte << 8); + + var size2 = a | IO.LBA1.Byte; + if (size != size2) + { + throw new Exception("[ATAPI] Packet size mismatch. Expected: " + size + " but got " + size2); + } + + outputData = new ushort[size2 / 2]; + if (size2 != 0) + { + IO.Data.Read16(outputData); + } + } + + private void AtaWait(bool drq = false) + { + //Read status register 4 times + var junk = IO.Status.Byte; + junk = IO.Status.Byte; + junk = IO.Status.Byte; + junk = IO.Status.Byte; + + + while (true) + { + if ((IO.Status.Byte & (byte)AtaPio.Status.Busy) == 0) break; + } + + if (drq) + { + while (true) + { + if ((IO.Status.Byte & (byte)AtaPio.Status.DRQ) != 0) break; + } + } + } + + public void Eject() + { + ushort[] output = new ushort[SectorSize]; + SendCmd(ATAPI.PacketCommands.Unload, SectorSize, ref output); + } + + private void Poll(bool checkDRQ = true) + { + // 400ns until BSR is set + IO.Wait(); + Console.WriteLine("[ATAPI] Polling"); + + while (true) + { + // Wait for the ATAPI Device to no longer be busy... + if (checkDRQ) + { + if ((IO.Status.Byte & (byte)AtaPio.Status.Busy) == 0 && (IO.Status.Byte & (byte)AtaPio.Status.DRQ) != 0) + { + break; + } + } + else + { + if ((IO.Status.Byte & (byte)AtaPio.Status.Busy) == 0) + { + break; + } + } + } + Console.WriteLine("[ATAPI] Finished Polling"); + } + + private void CheckForErrors() + { + if ((IO.Status.Byte & (byte)AtaPio.Status.Error) != 0) + { + Console.WriteLine("ATA Error"); + throw new Exception("ATA Error occured!"); + } + + if ((IO.Status.Byte & (byte)AtaPio.Status.ATA_SR_DF) != 0) + { + Console.WriteLine("ATA Device Fault"); + throw new Exception("ATA device fault encountered!"); + } + if ((IO.Status.Byte & (byte)AtaPio.Status.DRQ) == 0) + { + Console.WriteLine("ATAPI DRQ not set"); + //throw new Exception("ATAPI DRQ not set"); + } + } + } +} diff --git a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs b/source/Cosmos.HAL2/BlockDevice/AtaPio.cs index b69757ccdc..87ee7465cf 100644 --- a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs +++ b/source/Cosmos.HAL2/BlockDevice/AtaPio.cs @@ -73,7 +73,7 @@ enum Error : byte }; [Flags] - enum DvcSelVal : byte + public enum DvcSelVal : byte { // Bits 0-3: Head Number for CHS. // Bit 4: Slave Bit. (0: Selecting Master Drive, 1: Selecting Slave Drive). diff --git a/source/Cosmos.HAL2/BlockDevice/IDE.cs b/source/Cosmos.HAL2/BlockDevice/IDE.cs index fb2bdeadb8..08f387f02f 100644 --- a/source/Cosmos.HAL2/BlockDevice/IDE.cs +++ b/source/Cosmos.HAL2/BlockDevice/IDE.cs @@ -28,7 +28,9 @@ private static void Initialize(Ata.ControllerIdEnum aControllerID, Ata.BusPositi var xIO = aControllerID == Ata.ControllerIdEnum.Primary ? Core.Global.BaseIOGroups.ATA1 : Core.Global.BaseIOGroups.ATA2; var xATA = new AtaPio(xIO, aControllerID, aBusPosition); if (xATA.DriveType == AtaPio.SpecLevel.Null) + { return; + } else if (xATA.DriveType == AtaPio.SpecLevel.ATA) { BlockDevice.Devices.Add(xATA); @@ -36,7 +38,9 @@ private static void Initialize(Ata.ControllerIdEnum aControllerID, Ata.BusPositi } else if (xATA.DriveType == AtaPio.SpecLevel.ATAPI) { - Ata.AtaDebugger.Send("ATA device with speclevel ATAPI found, which is not supported yet!"); + var atapi = new ATAPI(xATA); + BlockDevice.Devices.Add(atapi); + Ata.AtaDebugger.Send("ATA device with speclevel ATAPI found"); return; } @@ -81,23 +85,22 @@ private static void Initialize(Ata.ControllerIdEnum aControllerID, Ata.BusPositi //BlockDevice.BlockDevice.Devices.Add(xPartDevice); } } - - // TODO Change this to foreach when foreach is supported Ata.AtaDebugger.Send("Number of MBR partitions found:"); Ata.AtaDebugger.SendNumber(xMBR.Partitions.Count); - for (int i = 0; i < xMBR.Partitions.Count; i++) + int partNumb = 0; + foreach (var part in xMBR.Partitions) { - var xPart = xMBR.Partitions[i]; - if (xPart == null) + if (part == null) { - Console.WriteLine("Null partition found at idx: " + i); + Console.WriteLine("Null partition found at idx: " + partNumb); } else { - var xPartDevice = new Partition(xATA, xPart.StartSector, xPart.SectorCount); + var xPartDevice = new Partition(xATA, part.StartSector, part.SectorCount); BlockDevice.Devices.Add(xPartDevice); - Console.WriteLine("Found partition at idx: " + i); + Console.WriteLine("Found partition at idx: " + partNumb); } + partNumb++; } } } From 808f6d5ff0106d5d4f58b1226287c4600f7d0e26 Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Thu, 20 May 2021 18:01:01 -0400 Subject: [PATCH 153/314] Fix a hang up --- source/Cosmos.HAL2/BlockDevice/ATAPI.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.HAL2/BlockDevice/ATAPI.cs b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs index f5fcb743d3..1e5b565890 100644 --- a/source/Cosmos.HAL2/BlockDevice/ATAPI.cs +++ b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs @@ -24,8 +24,11 @@ public ATAPI(AtaPio parentDevice) { this.BusPosition = parentDevice.BusPosition; this.Primary = parentDevice.ControllerID == ControllerIdEnum.Primary; + mBlockSize = SectorSize; IO = new Core.IOGroup.ATA(!Primary); + var p = BusPosition == BusPositionEnum.Master; + Ata.AtaDebugger.Send("ATAPI: Primary controller: "+ this.Primary+" Bus postion: IsMaster: "+ p); Devices.Add(this); ATAPIDevices.Add(this); @@ -45,8 +48,7 @@ public void Init() INTs.SetIrqHandler(0x0F, HandleIRQ); } - IO.Control.Byte = 0; //Enable IRQs - IO.DeviceSelect.Byte = (byte)((byte)(DvcSelVal.Default | DvcSelVal.LBA | (BusPosition == BusPositionEnum.Slave ? DvcSelVal.Slave : 0)) | 0); + IO.Control.Byte = 0; //Enable IRQs } public void Test() @@ -84,6 +86,9 @@ public override void ReadBlock(ulong SectorNum, ulong SectorCount, ref byte[] aD throw new NotImplementedException("Reading more than one sectors is not supported. SectorCount: " + SectorCount); } + Ata.AtaDebugger.Send("ATAPI: Reading block. Sector: " + SectorNum + " SectorCount: " + SectorCount); + + byte[] packet = new byte[12]; packet[0] = (byte)AtaPio.Cmd.Read;//Read Sector packet[1] = 0; @@ -132,12 +137,21 @@ public override void WriteBlock(ulong aBlockNo, ulong aBlockCount, ref byte[] aD private void SendCmd(byte[] AtapiPacket, int size, ref ushort[] outputData) { + //Select the ATAPI device + IO.DeviceSelect.Byte = (byte)((byte)(DvcSelVal.Default | DvcSelVal.LBA | (BusPosition == BusPositionEnum.Slave ? DvcSelVal.Slave : 0)) | 0); + + //Wait for the select complete + IO.Wait(); + Console.WriteLine("[ATAPI] Sending command"); IO.Features.Byte = 0x00; //PIO Mode IO.LBA1.Byte = (byte)((SectorSize) & 0xFF); IO.LBA2.Byte = (byte)((SectorSize >> 8) & 0xFF); IO.Command.Byte = (byte)AtaPio.Cmd.Packet; + Ata.AtaDebugger.Send("ATAPI: Polling"); + AtaWait(true); + Ata.AtaDebugger.Send("ATAPI: Polling complete"); for (int i = 0; i < AtapiPacket.Length; i++) { From 71c59fb00e4d825fc927321201f705a5e8923db9 Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Thu, 20 May 2021 18:05:21 -0400 Subject: [PATCH 154/314] Add the comments back --- source/Cosmos.Core/IOGroup/ATA.cs | 50 ++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/source/Cosmos.Core/IOGroup/ATA.cs b/source/Cosmos.Core/IOGroup/ATA.cs index 157e2be6bc..25d40c5928 100644 --- a/source/Cosmos.Core/IOGroup/ATA.cs +++ b/source/Cosmos.Core/IOGroup/ATA.cs @@ -9,21 +9,69 @@ namespace Cosmos.Core.IOGroup { public class ATA : IOGroup { + /// + /// Error IOPort + /// public readonly IOPort Error; // BAR0 + 1 - read only + /// + /// Features IOPort. + /// public readonly IOPortWrite Features; // BAR0 + 1 - write only + /// + /// Data IOPort. + /// public readonly IOPort Data; // BAR0 + /// + /// Sector Count IOPort. + /// public readonly IOPort SectorCount; // BAR0 + 2 + /// + /// LBA0 IOPort. + /// public readonly IOPort LBA0; // BAR0 + 3 + /// + /// LBA1 IOPort. + /// public readonly IOPort LBA1; // BAR0 + 4 + /// + /// LBA2 IOPort. + /// public readonly IOPort LBA2; // BAR0 + 5 + /// + /// Device select IOPort. + /// public readonly IOPort DeviceSelect; // BAR0 + 6 + /// + /// Command IOPort. + /// public readonly IOPortWrite Command; // BAR0 + 7 - write only + /// + /// Status IOPort. + /// public readonly IOPortRead Status; // BAR0 + 7 - read only + /// + /// Sector count IOPort. + /// public readonly IOPort SectorCountLBA48; // BAR0 + 8 + /// + /// LBA3 IOPort. + /// public readonly IOPort LBA3; // BAR0 + 9 + /// + /// LBA4 IOPort. + /// public readonly IOPort LBA4; // BAR0 + 10 + /// + /// LBA5 IOPort. + /// public readonly IOPort LBA5; // BAR0 + 11 - public readonly IOPortRead AlternateStatus; // BAR1 + 2 - read only + /// + /// Alternate Status IOPort. + /// + public readonly IOPortRead AlternateStatus; // BAR1 + 2 - read only + /// + /// Control IOPort. + /// public readonly IOPortWrite Control; // BAR1 + 2 - write only public ATA(bool aSecondary) From d1459fcb6b9c4bb42e2bbc4b02f20879ad78bfa3 Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Thu, 20 May 2021 18:46:15 -0400 Subject: [PATCH 155/314] Small fix --- source/Cosmos.HAL2/BlockDevice/ATAPI.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/Cosmos.HAL2/BlockDevice/ATAPI.cs b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs index 1e5b565890..6a13c38b30 100644 --- a/source/Cosmos.HAL2/BlockDevice/ATAPI.cs +++ b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs @@ -121,7 +121,6 @@ public override void ReadBlock(ulong SectorNum, ulong SectorCount, ref byte[] aD var item = buffer[i]; var bytes = BitConverter.GetBytes(item); - //TODO: Is this correct order. array[counter++] = bytes[0]; array[counter++] = bytes[1]; } @@ -204,7 +203,7 @@ private void AtaWait(bool drq = false) public void Eject() { - ushort[] output = new ushort[SectorSize]; + ushort[] output = new ushort[12]; SendCmd(ATAPI.PacketCommands.Unload, SectorSize, ref output); } From 76bbb83b73d93ffec5a7e19d37f7dc1430f62935 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 21 May 2021 14:08:02 +0200 Subject: [PATCH 156/314] Pass packets if CLOSED --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index ccd009b279..3b6b524a5e 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -348,7 +348,6 @@ internal void ReceiveData(TCPPacket packet) case Status.TIME_WAIT: break; case Status.CLOSED: - ProcessListen(packet); //TODO: ProcessClose + TcpListener break; default: throw new Exception("Unknown TCP connection state."); From edf7074a2b4249a7ad1ed0bd9318bd7fe037dfa2 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 24 May 2021 14:55:55 +0200 Subject: [PATCH 157/314] Typo --- Docs/articles/Kernel/Network.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index 043ab4766e..f1b7fad92e 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -1,6 +1,6 @@ # Network -In this article we will discuss about Networking on Cosmos, how to use the Network Stack, send and received packets. For now, available protocols are **ARP**, **IPv4**, **TCP**, **UDP**, **ICMP**, **DHCP** and **DNS**. Note that Cosmos devkit must be installed for this article. +In this article we will discuss about Networking on Cosmos, how to use the Network Stack, send and receive packets. For now, available protocols are **ARP**, **IPv4**, **TCP**, **UDP**, **ICMP**, **DHCP** and **DNS**. Note that Cosmos devkit must be installed for this article. All protocols here don't necessary support every feature described by their RFC and may have some bugs or architecture issues, if you find bugs or something abnormal please [submit an issue](http://https://github.com/CosmosOS/Cosmos/issues/new/choose "repository") on our repository. @@ -69,7 +69,7 @@ using(var xClient = new TcpClient(4242)) ``` ## ICMP -For ICMP, we will only 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. +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 using(var xClient = new ICMPClient()) { @@ -102,7 +102,7 @@ using(var xClient = new DnsClient()) } ``` ## Utils -## Get local IP +## Get local IP address ```csharp Console.WriteLine(NetworkConfig.CurrentConfig.Value.IPAddress.ToString()); ``` From a5f877067405427cf90e2c84272bb227d8230021 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 26 May 2021 19:20:29 +0200 Subject: [PATCH 158/314] Bad link --- Docs/articles/Kernel/Network.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index f1b7fad92e..c7bbd4c880 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -2,7 +2,7 @@ In this article we will discuss about Networking on Cosmos, how to use the Network Stack, send and receive packets. For now, available protocols are **ARP**, **IPv4**, **TCP**, **UDP**, **ICMP**, **DHCP** and **DNS**. Note that Cosmos devkit must be installed for this article. -All protocols here don't necessary support every feature described by their RFC and may have some bugs or architecture issues, if you find bugs or something abnormal please [submit an issue](http://https://github.com/CosmosOS/Cosmos/issues/new/choose "repository") on our repository. +All protocols here don't necessary support every feature described by their RFC and may have some bugs or architecture issues, if you find bugs or something abnormal please [submit an issue](https://github.com/CosmosOS/Cosmos/issues/new/choose) on our repository. 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(). From 67c96e16c4ddf924d9e3876635cb73c4f06adfe5 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 27 May 2021 15:24:51 +0200 Subject: [PATCH 159/314] Add TcpListener class + Move tcp state machine to Tcp.cs --- .../Network/IPv4/TCP/TCPClient.cs | 614 ++---------------- .../Network/IPv4/TCP/TCPPacket.cs | 14 +- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 539 +++++++++++++++ .../Network/IPv4/TCP/TcpListener.cs | 83 +++ 4 files changed, 682 insertions(+), 568 deletions(-) create mode 100644 source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs create mode 100644 source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 3b6b524a5e..4bdbe77aeb 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -15,78 +15,19 @@ namespace Cosmos.System.Network.IPv4.TCP { /// - /// TCP Connection status - /// - public enum Status - { - LISTEN, - SYN_SENT, - SYN_RECEIVED, - ESTABLISHED, - FIN_WAIT1, - FIN_WAIT2, - CLOSE_WAIT, - CLOSING, - LAST_ACK, - TIME_WAIT, - CLOSED - } - - /// - /// TCPClient class. Used to manage the TCP connection to a client. + /// TcpClient class. Used to manage the TCP connection to a server. /// public class TcpClient : IDisposable { /// - /// Clients dictionary. + /// Tcp State machine. /// - private static Dictionary clients; + internal Tcp StateMachine; /// - /// Local port. - /// - private int localPort; - /// - /// Source address. - /// - internal Address source; - /// - /// Destination address. - /// - internal Address destination; - /// - /// Destination port. - /// - private int destinationPort; - - /// - /// RX buffer queue. - /// - internal Queue rxBuffer; - - /// - /// Connection status. - /// - internal Status Status; - - /// - /// Connection Acknowledgement number. - /// - internal uint AckNumber; - - /// - /// Connection Sequence number. - /// - internal uint SequenceNumber; - - /// - /// Last recveived Connection Sequence number. + /// Clients dictionary. /// - private uint LastSequenceNumber; - - private bool WaitingAck = false; - - private byte[] data; + private static Dictionary clients; /// /// Assign clients dictionary. @@ -120,11 +61,14 @@ internal static TcpClient GetClient(ushort destPort) /// Thrown if localPort already exists. public TcpClient(int localPort) { - rxBuffer = new Queue(8); - Status = Status.CLOSED; - LastSequenceNumber = 0; + StateMachine.rxBuffer = new Queue(8); + + StateMachine = new Tcp(); - this.localPort = localPort; + StateMachine.Status = Status.CLOSED; + StateMachine.LastSequenceNumber = 0; + + StateMachine.localPort = localPort; if (localPort > 0) { clients.Add((uint)localPort, this); @@ -141,8 +85,8 @@ public TcpClient(int localPort) public TcpClient(Address dest, int destPort) : this(0) { - destination = dest; - destinationPort = destPort; + StateMachine.destination = dest; + StateMachine.destinationPort = destPort; } /// @@ -153,29 +97,29 @@ public TcpClient(Address dest, int destPort) /// Thrown if TCP Status is not CLOSED. public void Connect(Address dest, int destPort, int timeout = 5000) { - if (Status != Status.CLOSED) + if (StateMachine.Status != Status.CLOSED) { throw new Exception("Client must be closed before setting a new connection."); } - destination = dest; - destinationPort = destPort; + StateMachine.destination = dest; + StateMachine.destinationPort = destPort; - source = IPConfig.FindNetwork(dest); + StateMachine.source = IPConfig.FindNetwork(dest); //Generate Random Sequence Number var rnd = new Random(); - SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); + StateMachine.SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); // Flags=0x02 -> Syn - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destPort, SequenceNumber, 0, 20, (byte)Flags.SYN, 0xFAF0, 0); + var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)destPort, StateMachine.SequenceNumber, 0, 20, (byte)Flags.SYN, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - Status = Status.SYN_SENT; + StateMachine.Status = Status.SYN_SENT; - if (WaitStatus(Status.ESTABLISHED, timeout) == false) + if (StateMachine.WaitStatus(Status.ESTABLISHED, timeout) == false) { throw new Exception("Failed to open TCP connection!"); } @@ -188,29 +132,29 @@ public void Connect(Address dest, int destPort, int timeout = 5000) /// Thrown if TCP Status is CLOSED. public void Close() { - if (Status == Status.CLOSED) + if (StateMachine.Status == Status.CLOSED) { throw new Exception("Client already closed."); } - if (Status == Status.ESTABLISHED) + if (StateMachine.Status == Status.ESTABLISHED) { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)(Flags.FIN | Flags.ACK), 0xFAF0, 0); + var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)StateMachine.destinationPort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, (byte)(Flags.FIN | Flags.ACK), 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - SequenceNumber++; + StateMachine.SequenceNumber++; - Status = Status.FIN_WAIT1; + StateMachine.Status = Status.FIN_WAIT1; - if (WaitStatus(Status.CLOSED, 5000) == false) + if (StateMachine.WaitStatus(Status.CLOSED, 5000) == false) { throw new Exception("Failed to close TCP connection!"); } } - if (clients.ContainsKey((uint)localPort)) + if (clients.ContainsKey((uint)StateMachine.localPort)) { - clients.Remove((uint)localPort); + clients.Remove((uint)StateMachine.localPort); } } @@ -225,36 +169,36 @@ public void Close() /// Thrown if TCP Status is not ESTABLISHED. public void Send(byte[] data) { - if ((destination == null) || (destinationPort == 0)) + if ((StateMachine.destination == null) || (StateMachine.destinationPort == 0)) { throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); } - if (Status != Status.ESTABLISHED) + if (StateMachine.Status != Status.ESTABLISHED) { throw new Exception("Client must be connected before sending data."); } if (data.Length > 536) { - var chunks = ArraySplit(data, 536); + var chunks = StateMachine.ArraySplit(data, 536); for (int i = 0; i < chunks.Length; i++) { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, i == chunks.Length - 2 ? (byte)(Flags.PSH | Flags.ACK) : (byte)(Flags.ACK), 0xFAF0, 0, chunks[i]); + var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)StateMachine.destinationPort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, i == chunks.Length - 2 ? (byte)(Flags.PSH | Flags.ACK) : (byte)(Flags.ACK), 0xFAF0, 0, chunks[i]); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - SequenceNumber += (uint)chunks[i].Length; + StateMachine.SequenceNumber += (uint)chunks[i].Length; } } else { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)(Flags.PSH | Flags.ACK), 0xFAF0, 0, data); + var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)StateMachine.destinationPort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, (byte)(Flags.PSH | Flags.ACK), 0xFAF0, 0, data); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - SequenceNumber += (uint)data.Length; + StateMachine.SequenceNumber += (uint)data.Length; } - WaitingAck = true; + StateMachine.WaitingAck = true; } /// @@ -266,21 +210,21 @@ public void Send(byte[] data) /// Thrown if TCP Status is not ESTABLISHED. public byte[] NonBlockingReceive(ref EndPoint source) { - if (Status != Status.ESTABLISHED) + if (StateMachine.Status != Status.ESTABLISHED) { throw new Exception("Client must be connected before receiving data."); } - if (rxBuffer.Count < 1) + if (StateMachine.rxBuffer.Count < 1) { return null; } - var packet = rxBuffer.Dequeue(); + var packet = StateMachine.rxBuffer.Dequeue(); source.address = packet.SourceIP; source.port = packet.SourcePort; - var tmp = data; - data = null; + var tmp = StateMachine.data; + StateMachine.data = null; return tmp; } @@ -293,488 +237,28 @@ public byte[] NonBlockingReceive(ref EndPoint source) /// Thrown if TCP Status is not ESTABLISHED. public byte[] Receive(ref EndPoint source) { - if (Status != Status.ESTABLISHED) + if (StateMachine.Status != Status.ESTABLISHED) { throw new Exception("Client must be connected before receiving data."); } - while (rxBuffer.Count < 1) ; + while (StateMachine.rxBuffer.Count < 1) ; - var packet = rxBuffer.Dequeue(); + var packet = StateMachine.rxBuffer.Dequeue(); source.address = packet.SourceIP; source.port = packet.SourcePort; - var tmp = data; - data = null; + var tmp = StateMachine.data; + StateMachine.data = null; return tmp; } - /// - /// Handle TCP discussions and data. - /// - /// Packet to receive. - /// Thrown on fatal error (contact support). - /// Thrown on IO error. - internal void ReceiveData(TCPPacket packet) - { - switch (Status) - { - case Status.LISTEN: - ProcessListen(packet); - break; - case Status.SYN_SENT: - ProcessSynSent(packet); - break; - case Status.SYN_RECEIVED: - ProcessSynReceived(packet); - break; - case Status.ESTABLISHED: - ProcessEstablished(packet); - break; - case Status.FIN_WAIT1: - ProcessFinWait1(packet); - break; - case Status.FIN_WAIT2: - ProcessFinWait2(packet); - break; - case Status.CLOSE_WAIT: - ProcessCloseWait(packet); - break; - case Status.CLOSING: - ProcessClosing(packet); - break; - case Status.LAST_ACK: - ProcessCloseWait(packet); - break; - case Status.TIME_WAIT: - break; - case Status.CLOSED: - break; - default: - throw new Exception("Unknown TCP connection state."); - } - } - - #region Process Status - - /// - /// Process LISTEN Status. - /// - /// Packet to receive. - public void ProcessListen(TCPPacket packet) - { - if (packet.RST) - { - Status = Status.CLOSED; - - throw new Exception("TCP connection resetted! (RST received on LISTEN state)"); - } - else if (packet.FIN) - { - Status = Status.CLOSED; - - throw new Exception("TCP connection closed! (FIN received on LISTEN state)"); - } - else if (packet.ACK) - { - SendEmptyPacket(Flags.RST); - - Status = Status.CLOSED; - - throw new Exception("TCP connection closed! (ACK received on LISTEN state)"); - } - else if (packet.SYN) - { - Status = Status.SYN_RECEIVED; - - source = IPConfig.FindNetwork(packet.SourceIP); - - AckNumber = packet.SequenceNumber + 1; - - var rnd = new Random(); - SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); - - destination = packet.SourceIP; - destinationPort = packet.SourcePort; - - SendEmptyPacket(Flags.SYN | Flags.ACK); - } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSED||LISTEN)"); - } - } - - /// - /// Process SYN_RECEIVED Status. - /// - /// Packet to receive. - public void ProcessSynReceived(TCPPacket packet) - { - if (packet.RST) - { - Status = Status.LISTEN; - } - else if (packet.ACK) - { - Status = Status.ESTABLISHED; - - SequenceNumber++; - } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_RECEIVED)"); - } - } - - /// - /// Process SYN_SENT Status. - /// - /// Packet to receive. - public void ProcessSynSent(TCPPacket packet) - { - if (packet.FIN) - { - Status = Status.CLOSED; - - throw new Exception("TCP connection closed! (FIN received on SYN_SENT state)"); - } - else if (packet.TCPFlags == (byte)Flags.ACK) - { - AckNumber = packet.SequenceNumber; - SequenceNumber = packet.AckNumber; - - Status = Status.ESTABLISHED; - } - else if (packet.RST) - { - Status = Status.CLOSED; - - throw new Exception("Connection refused by remote computer."); - } - else if (packet.SYN) - { - if (packet.ACK) - { - AckNumber = packet.SequenceNumber + 1; - SequenceNumber++; - - LastSequenceNumber = packet.SequenceNumber; - - SendEmptyPacket(Flags.ACK); - - Status = Status.ESTABLISHED; - } - else if (packet.TCPFlags == (byte)Flags.SYN) - { - Status = Status.CLOSED; - - throw new NotImplementedException("Simultaneous open not supported."); - } - else - { - Status = Status.CLOSED; - - throw new Exception("TCP connection closed! (Flag " + packet.TCPFlags + " received on SYN_SENT state)"); - } - } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_SENT)"); - } - } - - /// - /// Process ESTABLISHED Status. - /// - /// Packet to receive. - public void ProcessEstablished(TCPPacket packet) - { - if (packet.RST) - { - Status = Status.CLOSED; - - throw new Exception("TCP Connection resetted!"); - } - if (packet.TCPFlags == (byte)Flags.ACK) - { - if (WaitingAck) - { - if (SequenceNumber == packet.AckNumber) - { - WaitingAck = false; - } - } - else - { - if (packet.SequenceNumber >= AckNumber && packet.TCP_DataLength > 0) //packet sequencing - { - AckNumber += packet.TCP_DataLength; - - data = Concat(data, packet.TCP_Data); - } - } - } - if (packet.FIN && packet.ACK) - { - AckNumber++; - - SendEmptyPacket(Flags.ACK); - - WaitAndClose(); - } - else if (packet.FIN) - { - AckNumber++; - - SendEmptyPacket(Flags.ACK); - - Status = Status.CLOSE_WAIT; - - SendEmptyPacket(Flags.FIN); - - Status = Status.LAST_ACK; - } - else if (packet.PSH && packet.ACK) - { - if (packet.SequenceNumber > LastSequenceNumber) //dup check - { - AckNumber += packet.TCP_DataLength; - - LastSequenceNumber = packet.SequenceNumber; - - data = Concat(data, packet.TCP_Data); - - rxBuffer.Enqueue(packet); - - SendEmptyPacket(Flags.ACK); - } - } - else if (packet.ACK) - { - //DO NOTHING - } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=ESTABLISHED)"); - } - } - - /// - /// Process FIN_WAIT1 Status. - /// - /// Packet to receive. - public void ProcessFinWait1(TCPPacket packet) - { - if (packet.FIN && packet.ACK) - { - AckNumber++; - - SendEmptyPacket(Flags.ACK); - - WaitAndClose(); - } - else if (packet.FIN) - { - AckNumber++; - - SendEmptyPacket(Flags.ACK); - - Status = Status.CLOSING; - } - else if (packet.ACK) - { - Status = Status.FIN_WAIT2; - } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT1)"); - } - } - - /// - /// Process FIN_WAIT2 Status. - /// - /// Packet to receive. - public void ProcessFinWait2(TCPPacket packet) - { - if (packet.FIN) - { - AckNumber++; - - SendEmptyPacket(Flags.ACK); - - WaitAndClose(); - } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT2)"); - } - } - - /// - /// Process CLOSING Status. - /// - /// Packet to receive. - public void ProcessClosing(TCPPacket packet) - { - if (packet.ACK) - { - WaitAndClose(); - } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSING)"); - } - } - - /// - /// Process Close_WAIT Status. - /// - /// Packet to receive. - public void ProcessCloseWait(TCPPacket packet) - { - if (packet.ACK) - { - Status = Status.CLOSED; - } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSE_WAIT||LAST_ACK)"); - } - } - - #endregion - - #region Utils - - /// - /// Contatenate two byte arrays. https://stackoverflow.com/a/45531730 - /// - /// First byte array. - /// Byte array to concatenate. - private byte[] Concat(byte[] first, byte[] second) - { - byte[] output; - int alen = 0; - - if (first == null) - { - output = new byte[second.Length]; - } - else - { - output = new byte[first.Length + second.Length]; - alen = first.Length; - for (int i = 0; i < first.Length; i++) - { - output[i] = first[i]; - } - } - for (int j = 0; j < second.Length; j++) - { - output[alen + j] = second[j]; - } - return output; - } - - /// - /// Split byte array into chunks of a specified size. - /// - /// Byte array to split. - /// Chunk size. - private byte[][] ArraySplit(byte[] buffer, int chunksize = 1000) - { - var size = buffer.Length; - var chunkCount = (buffer.Length + chunksize - 1) / chunksize; - var bufferArray = new byte[chunkCount][]; - int index = 0; - - for (var i = 0; i < chunkCount; i++) - { - bufferArray[i] = new byte[Math.Min(chunksize, buffer.Length - i * chunksize)]; - } - for (var i = 0; i < chunkCount; i++) - { - for (var j = 0; j < bufferArray[i].Length; j++) - { - bufferArray[i][j] = buffer[index]; - index++; - } - } - return bufferArray; - } - - /// - /// Wait until remote receive ACK of its connection termination request. - /// - private void WaitAndClose() - { - Status = Status.TIME_WAIT; - - HAL.Global.PIT.Wait(300); //TODO: Calculate time value - - Status = Status.CLOSED; - } - - /// - /// Wait for new TCP connection status. - /// - private bool WaitStatus(Status status, int timeout) - { - int second = 0; - int _deltaT = 0; - - while (Status != status) - { - if (second > (timeout / 1000)) - { - return false; - } - if (_deltaT != RTC.Second) - { - second++; - _deltaT = RTC.Second; - } - } - return true; - } - - /// - /// Send acknowledgement packet - /// - private void SendEmptyPacket(Flags flag) - { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)flag, 0xFAF0, 0); - - OutgoingBuffer.AddPacket(packet); - NetworkStack.Update(); - } - - #endregion - /// /// Is TCP Connected. /// /// Boolean value. public bool IsConnected() { - return Status == Status.ESTABLISHED; + return StateMachine.Status == Status.ESTABLISHED; } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index d84e6674fa..4cf1ce1cad 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -56,10 +56,18 @@ internal static void TCPHandler(byte[] packetData) if (packet.CheckCRC()) { - var receiver = TcpClient.GetClient(packet.DestinationPort); - if (receiver != null) + var client = TcpClient.GetClient(packet.DestinationPort); + if (client != null) { - receiver.ReceiveData(packet); + client.StateMachine.ReceiveData(packet); + return; + } + + var listener = TcpListener.GetClient(packet.DestinationPort); + if (listener != null) + { + listener.StateMachine.ReceiveData(packet); + return; } } else diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs new file mode 100644 index 0000000000..b3af2c3abc --- /dev/null +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -0,0 +1,539 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Cosmos.HAL; +using Cosmos.System.Network.Config; + +namespace Cosmos.System.Network.IPv4.TCP +{ + /// + /// TCP Connection status + /// + public enum Status + { + LISTEN, + SYN_SENT, + SYN_RECEIVED, + ESTABLISHED, + FIN_WAIT1, + FIN_WAIT2, + CLOSE_WAIT, + CLOSING, + LAST_ACK, + TIME_WAIT, + CLOSED + } + + /// + /// Tcp class. Used to manage the TCP state machine + /// See RFC 793 for more information. + /// + internal class Tcp + { + /// + /// Local port. + /// + internal int localPort; + /// + /// Source address. + /// + internal Address source; + /// + /// Destination address. + /// + internal Address destination; + /// + /// Destination port. + /// + internal int destinationPort; + + /// + /// RX buffer queue. + /// + internal Queue rxBuffer; + + /// + /// Connection status. + /// + internal Status Status; + + /// + /// Connection Acknowledgement number. + /// + internal uint AckNumber; + + /// + /// Connection Sequence number. + /// + internal uint SequenceNumber; + + /// + /// Last recveived Connection Sequence number. + /// + internal uint LastSequenceNumber; + + internal bool WaitingAck = false; + + internal byte[] data; + + /// + /// Handle TCP discussions and data. + /// + /// Packet to receive. + /// Thrown on fatal error (contact support). + /// Thrown on IO error. + internal void ReceiveData(TCPPacket packet) + { + switch (Status) + { + case Status.LISTEN: + ProcessListen(packet); + break; + case Status.SYN_SENT: + ProcessSynSent(packet); + break; + case Status.SYN_RECEIVED: + ProcessSynReceived(packet); + break; + case Status.ESTABLISHED: + ProcessEstablished(packet); + break; + case Status.FIN_WAIT1: + ProcessFinWait1(packet); + break; + case Status.FIN_WAIT2: + ProcessFinWait2(packet); + break; + case Status.CLOSE_WAIT: + ProcessCloseWait(packet); + break; + case Status.CLOSING: + ProcessClosing(packet); + break; + case Status.LAST_ACK: + ProcessCloseWait(packet); + break; + case Status.TIME_WAIT: + break; + case Status.CLOSED: + break; + default: + throw new Exception("Unknown TCP connection state."); + } + } + + #region Process Status + + /// + /// Process LISTEN Status. + /// + /// Packet to receive. + public void ProcessListen(TCPPacket packet) + { + if (packet.RST) + { + Status = Status.CLOSED; + + throw new Exception("TCP connection resetted! (RST received on LISTEN state)"); + } + else if (packet.FIN) + { + Status = Status.CLOSED; + + throw new Exception("TCP connection closed! (FIN received on LISTEN state)"); + } + else if (packet.ACK) + { + SendEmptyPacket(Flags.RST); + + Status = Status.CLOSED; + + throw new Exception("TCP connection closed! (ACK received on LISTEN state)"); + } + else if (packet.SYN) + { + Status = Status.SYN_RECEIVED; + + source = IPConfig.FindNetwork(packet.SourceIP); + + AckNumber = packet.SequenceNumber + 1; + + var rnd = new Random(); + SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); + + destination = packet.SourceIP; + destinationPort = packet.SourcePort; + + SendEmptyPacket(Flags.SYN | Flags.ACK); + } + else + { + Status = Status.CLOSED; + + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSED||LISTEN)"); + } + } + + /// + /// Process SYN_RECEIVED Status. + /// + /// Packet to receive. + public void ProcessSynReceived(TCPPacket packet) + { + if (packet.RST) + { + Status = Status.LISTEN; + } + else if (packet.ACK) + { + Status = Status.ESTABLISHED; + + SequenceNumber++; + } + else + { + Status = Status.CLOSED; + + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_RECEIVED)"); + } + } + + /// + /// Process SYN_SENT Status. + /// + /// Packet to receive. + public void ProcessSynSent(TCPPacket packet) + { + if (packet.FIN) + { + Status = Status.CLOSED; + + throw new Exception("TCP connection closed! (FIN received on SYN_SENT state)"); + } + else if (packet.TCPFlags == (byte)Flags.ACK) + { + AckNumber = packet.SequenceNumber; + SequenceNumber = packet.AckNumber; + + Status = Status.ESTABLISHED; + } + else if (packet.RST) + { + Status = Status.CLOSED; + + throw new Exception("Connection refused by remote computer."); + } + else if (packet.SYN) + { + if (packet.ACK) + { + AckNumber = packet.SequenceNumber + 1; + SequenceNumber++; + + LastSequenceNumber = packet.SequenceNumber; + + SendEmptyPacket(Flags.ACK); + + Status = Status.ESTABLISHED; + } + else if (packet.TCPFlags == (byte)Flags.SYN) + { + Status = Status.CLOSED; + + throw new NotImplementedException("Simultaneous open not supported."); + } + else + { + Status = Status.CLOSED; + + throw new Exception("TCP connection closed! (Flag " + packet.TCPFlags + " received on SYN_SENT state)"); + } + } + else + { + Status = Status.CLOSED; + + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_SENT)"); + } + } + + /// + /// Process ESTABLISHED Status. + /// + /// Packet to receive. + public void ProcessEstablished(TCPPacket packet) + { + if (packet.RST) + { + Status = Status.CLOSED; + + throw new Exception("TCP Connection resetted!"); + } + if (packet.TCPFlags == (byte)Flags.ACK) + { + if (WaitingAck) + { + if (SequenceNumber == packet.AckNumber) + { + WaitingAck = false; + } + } + else + { + if (packet.SequenceNumber >= AckNumber && packet.TCP_DataLength > 0) //packet sequencing + { + AckNumber += packet.TCP_DataLength; + + data = Concat(data, packet.TCP_Data); + } + } + } + if (packet.FIN && packet.ACK) + { + AckNumber++; + + SendEmptyPacket(Flags.ACK); + + WaitAndClose(); + } + else if (packet.FIN) + { + AckNumber++; + + SendEmptyPacket(Flags.ACK); + + Status = Status.CLOSE_WAIT; + + SendEmptyPacket(Flags.FIN); + + Status = Status.LAST_ACK; + } + else if (packet.PSH && packet.ACK) + { + if (packet.SequenceNumber > LastSequenceNumber) //dup check + { + AckNumber += packet.TCP_DataLength; + + LastSequenceNumber = packet.SequenceNumber; + + data = Concat(data, packet.TCP_Data); + + rxBuffer.Enqueue(packet); + + SendEmptyPacket(Flags.ACK); + } + } + else if (packet.ACK) + { + //DO NOTHING + } + else + { + Status = Status.CLOSED; + + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=ESTABLISHED)"); + } + } + + /// + /// Process FIN_WAIT1 Status. + /// + /// Packet to receive. + public void ProcessFinWait1(TCPPacket packet) + { + if (packet.FIN && packet.ACK) + { + AckNumber++; + + SendEmptyPacket(Flags.ACK); + + WaitAndClose(); + } + else if (packet.FIN) + { + AckNumber++; + + SendEmptyPacket(Flags.ACK); + + Status = Status.CLOSING; + } + else if (packet.ACK) + { + Status = Status.FIN_WAIT2; + } + else + { + Status = Status.CLOSED; + + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT1)"); + } + } + + /// + /// Process FIN_WAIT2 Status. + /// + /// Packet to receive. + public void ProcessFinWait2(TCPPacket packet) + { + if (packet.FIN) + { + AckNumber++; + + SendEmptyPacket(Flags.ACK); + + WaitAndClose(); + } + else + { + Status = Status.CLOSED; + + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT2)"); + } + } + + /// + /// Process CLOSING Status. + /// + /// Packet to receive. + public void ProcessClosing(TCPPacket packet) + { + if (packet.ACK) + { + WaitAndClose(); + } + else + { + Status = Status.CLOSED; + + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSING)"); + } + } + + /// + /// Process Close_WAIT Status. + /// + /// Packet to receive. + public void ProcessCloseWait(TCPPacket packet) + { + if (packet.ACK) + { + Status = Status.CLOSED; + } + else + { + Status = Status.CLOSED; + + throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSE_WAIT||LAST_ACK)"); + } + } + + #endregion + + #region Utils + + /// + /// Contatenate two byte arrays. https://stackoverflow.com/a/45531730 + /// + /// First byte array. + /// Byte array to concatenate. + private byte[] Concat(byte[] first, byte[] second) + { + byte[] output; + int alen = 0; + + if (first == null) + { + output = new byte[second.Length]; + } + else + { + output = new byte[first.Length + second.Length]; + alen = first.Length; + for (int i = 0; i < first.Length; i++) + { + output[i] = first[i]; + } + } + for (int j = 0; j < second.Length; j++) + { + output[alen + j] = second[j]; + } + return output; + } + + /// + /// Split byte array into chunks of a specified size. + /// + /// Byte array to split. + /// Chunk size. + internal byte[][] ArraySplit(byte[] buffer, int chunksize = 1000) + { + var size = buffer.Length; + var chunkCount = (buffer.Length + chunksize - 1) / chunksize; + var bufferArray = new byte[chunkCount][]; + int index = 0; + + for (var i = 0; i < chunkCount; i++) + { + bufferArray[i] = new byte[Math.Min(chunksize, buffer.Length - i * chunksize)]; + } + for (var i = 0; i < chunkCount; i++) + { + for (var j = 0; j < bufferArray[i].Length; j++) + { + bufferArray[i][j] = buffer[index]; + index++; + } + } + return bufferArray; + } + + /// + /// Wait until remote receive ACK of its connection termination request. + /// + private void WaitAndClose() + { + Status = Status.TIME_WAIT; + + HAL.Global.PIT.Wait(300); //TODO: Calculate time value + + Status = Status.CLOSED; + } + + /// + /// Wait for new TCP connection status. + /// + internal bool WaitStatus(Status status, int timeout) + { + int second = 0; + int _deltaT = 0; + + while (Status != status) + { + if (second > (timeout / 1000)) + { + return false; + } + if (_deltaT != RTC.Second) + { + second++; + _deltaT = RTC.Second; + } + } + return true; + } + + /// + /// Send acknowledgement packet + /// + private void SendEmptyPacket(Flags flag) + { + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)flag, 0xFAF0, 0); + + OutgoingBuffer.AddPacket(packet); + NetworkStack.Update(); + } + + #endregion + } +} diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs new file mode 100644 index 0000000000..31c1e71331 --- /dev/null +++ b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Cosmos.System.Network.Config; + +namespace Cosmos.System.Network.IPv4.TCP +{ + /// + /// TcpListener class. Used to manage the TCP connection to a client. + /// + public class TcpListener + { + /// + /// Tcp State machine. + /// + internal Tcp StateMachine; + + // + /// Clients dictionary. + /// + private static Dictionary clients; + + public bool ExclusiveAddressUse { get; set; } + public EndPoint LocalEndpoint { get; } + protected bool Active { get; } + + /// + /// Get client. + /// + /// Destination port. + /// TcpClient + internal static TcpListener GetClient(ushort destPort) + { + if (clients.ContainsKey((uint)destPort)) + { + return clients[(uint)destPort]; + } + + return null; + } + + public TcpListener(int localPort) + { + StateMachine.localPort = localPort; + + if (localPort > 0) + { + clients.Add((uint)localPort, this); + } + } + + public TcpListener(Address localaddr, int localPort) + { + StateMachine.source = localaddr; + StateMachine.localPort = localPort; + + if (localPort > 0) + { + clients.Add((uint)localPort, this); + } + } + + public static TcpListener Create(int port) + { + throw new NotImplementedException(); + } + + public TcpClient AcceptTcpClient() + { + return new TcpClient(StateMachine.localPort); + } + + public void Start() + { + StateMachine.Status = Status.LISTEN; + } + + public void Stop() + { + StateMachine.Status = Status.CLOSED; + } + } +} From e9c1fcdb63809a3ed61bd8bc24858ef979654f60 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 27 May 2021 15:53:29 +0200 Subject: [PATCH 160/314] TcpListener fixes --- .../Network/IPv4/TCP/TCPClient.cs | 18 ++++++++++ .../Network/IPv4/TCP/TCPPacket.cs | 2 +- .../Network/IPv4/TCP/TcpListener.cs | 34 +++++-------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 4bdbe77aeb..659728f240 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -53,6 +53,24 @@ internal static TcpClient GetClient(ushort destPort) return null; } + /// + /// Create new instance of the class. + /// + /// Tcp state machine. + /// Thrown on fatal error (contact support). + /// Thrown if localPort already exists. + internal TcpClient(Tcp stateMachine) + { + StateMachine.rxBuffer = new Queue(8); + + StateMachine = stateMachine; + + if (StateMachine.localPort > 0) + { + clients.Add((uint)StateMachine.localPort, this); + } + } + /// /// Create new instance of the class. /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 4cf1ce1cad..6d23ad9584 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -63,7 +63,7 @@ internal static void TCPHandler(byte[] packetData) return; } - var listener = TcpListener.GetClient(packet.DestinationPort); + var listener = TcpListener.GetListener(packet.DestinationPort); if (listener != null) { listener.StateMachine.ReceiveData(packet); diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs index 31c1e71331..595030d302 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs @@ -18,22 +18,18 @@ public class TcpListener // /// Clients dictionary. /// - private static Dictionary clients; - - public bool ExclusiveAddressUse { get; set; } - public EndPoint LocalEndpoint { get; } - protected bool Active { get; } + private static Dictionary listeners; /// /// Get client. /// /// Destination port. /// TcpClient - internal static TcpListener GetClient(ushort destPort) + internal static TcpListener GetListener(ushort destPort) { - if (clients.ContainsKey((uint)destPort)) + if (listeners.ContainsKey((uint)destPort)) { - return clients[(uint)destPort]; + return listeners[(uint)destPort]; } return null; @@ -45,29 +41,15 @@ public TcpListener(int localPort) if (localPort > 0) { - clients.Add((uint)localPort, this); + listeners.Add((uint)localPort, this); } } - public TcpListener(Address localaddr, int localPort) - { - StateMachine.source = localaddr; - StateMachine.localPort = localPort; - - if (localPort > 0) - { - clients.Add((uint)localPort, this); - } - } - - public static TcpListener Create(int port) - { - throw new NotImplementedException(); - } - public TcpClient AcceptTcpClient() { - return new TcpClient(StateMachine.localPort); + while (StateMachine.WaitStatus(Status.ESTABLISHED, 5000) != true); + + return new TcpClient(StateMachine); } public void Start() From 2d1467d7212eb8521a50d389ac6e4bd7ce032668 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 27 May 2021 16:17:57 +0200 Subject: [PATCH 161/314] NRE fix on TcpClient + listeners list creation --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 4 ++-- source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 659728f240..5a0d1cac48 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -79,10 +79,10 @@ internal TcpClient(Tcp stateMachine) /// Thrown if localPort already exists. public TcpClient(int localPort) { - StateMachine.rxBuffer = new Queue(8); - StateMachine = new Tcp(); + StateMachine.rxBuffer = new Queue(8); + StateMachine.Status = Status.CLOSED; StateMachine.LastSequenceNumber = 0; diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs index 595030d302..e0c9774d6b 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs @@ -20,6 +20,15 @@ public class TcpListener /// private static Dictionary listeners; + /// + /// Assign listeners dictionary. + /// + /// Thrown on fatal error (contact support). + static TcpListener() + { + listeners = new Dictionary(); + } + /// /// Get client. /// @@ -37,6 +46,8 @@ internal static TcpListener GetListener(ushort destPort) public TcpListener(int localPort) { + StateMachine = new Tcp(); + StateMachine.localPort = localPort; if (localPort > 0) From 6207fbbce7c76737f273f280cf27c168f1f3671a Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 27 May 2021 16:25:23 +0200 Subject: [PATCH 162/314] Add Dispose to TcpListener class + Documentation comments --- .../Network/IPv4/TCP/TcpListener.cs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs index e0c9774d6b..ec1801d0c4 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs @@ -8,7 +8,7 @@ namespace Cosmos.System.Network.IPv4.TCP /// /// TcpListener class. Used to manage the TCP connection to a client. /// - public class TcpListener + public class TcpListener : IDisposable { /// /// Tcp State machine. @@ -44,6 +44,12 @@ internal static TcpListener GetListener(ushort destPort) return null; } + /// + /// Create new instance of the class. + /// + /// Local port. + /// Thrown on fatal error (contact support). + /// Thrown if localPort already exists. public TcpListener(int localPort) { StateMachine = new Tcp(); @@ -56,6 +62,10 @@ public TcpListener(int localPort) } } + /// + /// Receive TcpClient from remote computer. This function is blocking. + /// + /// Accepted TcpClient public TcpClient AcceptTcpClient() { while (StateMachine.WaitStatus(Status.ESTABLISHED, 5000) != true); @@ -63,14 +73,32 @@ public TcpClient AcceptTcpClient() return new TcpClient(StateMachine); } + /// + /// Start listening for new TCP connections. + /// + /// Thrown on fatal error (contact support). + /// Thrown on IO error. public void Start() { StateMachine.Status = Status.LISTEN; } + /// + /// Stop listening for new TCP connections. + /// + /// Thrown on fatal error (contact support). + /// Thrown on IO error. public void Stop() { StateMachine.Status = Status.CLOSED; } + + /// + /// Close listener + /// + public void Dispose() + { + Stop(); + } } } From 680a0e96bade29bdcb4671793aa640b04470da8d Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 27 May 2021 17:24:51 +0200 Subject: [PATCH 163/314] PSH/ACK fix after SYN_RECEIVED --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 2 -- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 4 +++- source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 5a0d1cac48..f315a3db45 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -61,8 +61,6 @@ internal static TcpClient GetClient(ushort destPort) /// Thrown if localPort already exists. internal TcpClient(Tcp stateMachine) { - StateMachine.rxBuffer = new Queue(8); - StateMachine = stateMachine; if (StateMachine.localPort > 0) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index b3af2c3abc..380f7354ea 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -186,9 +186,11 @@ public void ProcessSynReceived(TCPPacket packet) } else if (packet.ACK) { - Status = Status.ESTABLISHED; + LastSequenceNumber = packet.SequenceNumber - 1; //TODO: Fix this trick (for dup check when PSH ACK) SequenceNumber++; + + Status = Status.ESTABLISHED; } else { diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs index ec1801d0c4..7e3267588d 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs @@ -54,6 +54,8 @@ public TcpListener(int localPort) { StateMachine = new Tcp(); + StateMachine.rxBuffer = new Queue(8); + StateMachine.localPort = localPort; if (localPort > 0) @@ -63,7 +65,7 @@ public TcpListener(int localPort) } /// - /// Receive TcpClient from remote computer. This function is blocking. + /// Receive TcpClient from remote computer. /// /// Accepted TcpClient public TcpClient AcceptTcpClient() From 7c68dfe7c1b28272a7433318c2f0f3a09a832b87 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 27 May 2021 19:20:51 +0200 Subject: [PATCH 164/314] Add TcpListener to documentation --- Docs/articles/Kernel/Network.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index c7bbd4c880..3a1130e0d4 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -51,6 +51,26 @@ using(var xClient = new UdpClient(4242)) ## TCP Like UDP, TCP has to create a client and call Connect() to specify the remote machine address before sending or receiving data. + +Server : +```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)); +} +``` + +Client : ```csharp using(var xClient = new TcpClient(4242)) { From b6c1756fc498b20d1298d7595b7d73073532ce4f Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 28 May 2021 11:59:38 +0200 Subject: [PATCH 165/314] Make AcceptTcpClient blocking + PSH ACK fixes + Remove listener when Stop() --- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 66 +++++++++++-------- .../Network/IPv4/TCP/TcpListener.cs | 16 ++++- 2 files changed, 51 insertions(+), 31 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index 380f7354ea..fc472a9ab7 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -265,22 +265,32 @@ public void ProcessSynSent(TCPPacket packet) /// Packet to receive. public void ProcessEstablished(TCPPacket packet) { - if (packet.RST) + if (packet.ACK) { - Status = Status.CLOSED; + if (packet.PSH) + { + if (packet.SequenceNumber > LastSequenceNumber) //dup check + { + AckNumber += packet.TCP_DataLength; + + LastSequenceNumber = packet.SequenceNumber; + + data = Concat(data, packet.TCP_Data); + + rxBuffer.Enqueue(packet); + + SendEmptyPacket(Flags.ACK); + } + } - throw new Exception("TCP Connection resetted!"); - } - if (packet.TCPFlags == (byte)Flags.ACK) - { if (WaitingAck) { - if (SequenceNumber == packet.AckNumber) + if (packet.AckNumber == SequenceNumber) { WaitingAck = false; } } - else + else if (!packet.PSH) { if (packet.SequenceNumber >= AckNumber && packet.TCP_DataLength > 0) //packet sequencing { @@ -289,8 +299,15 @@ public void ProcessEstablished(TCPPacket packet) data = Concat(data, packet.TCP_Data); } } + return; } - if (packet.FIN && packet.ACK) + if (packet.RST) + { + Status = Status.CLOSED; + + throw new Exception("TCP Connection resetted!"); + } + else if (packet.FIN && packet.ACK) { AckNumber++; @@ -306,29 +323,12 @@ public void ProcessEstablished(TCPPacket packet) Status = Status.CLOSE_WAIT; + HAL.Global.PIT.Wait(300); + SendEmptyPacket(Flags.FIN); Status = Status.LAST_ACK; } - else if (packet.PSH && packet.ACK) - { - if (packet.SequenceNumber > LastSequenceNumber) //dup check - { - AckNumber += packet.TCP_DataLength; - - LastSequenceNumber = packet.SequenceNumber; - - data = Concat(data, packet.TCP_Data); - - rxBuffer.Enqueue(packet); - - SendEmptyPacket(Flags.ACK); - } - } - else if (packet.ACK) - { - //DO NOTHING - } else { Status = Status.CLOSED; @@ -525,6 +525,16 @@ internal bool WaitStatus(Status status, int timeout) return true; } + /// + /// Wait for new TCP connection status (blocking). + /// + internal bool WaitStatus(Status status) + { + while (Status != status); + + return true; + } + /// /// Send acknowledgement packet /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs index 7e3267588d..2e5c628b2c 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs @@ -68,9 +68,16 @@ public TcpListener(int localPort) /// Receive TcpClient from remote computer. /// /// Accepted TcpClient - public TcpClient AcceptTcpClient() + public TcpClient AcceptTcpClient(int timeout = -1) { - while (StateMachine.WaitStatus(Status.ESTABLISHED, 5000) != true); + if (timeout == -1) + { + while (StateMachine.WaitStatus(Status.ESTABLISHED) != true) ; + } + else + { + while (StateMachine.WaitStatus(Status.ESTABLISHED, timeout) != true) ; + } return new TcpClient(StateMachine); } @@ -92,7 +99,10 @@ public void Start() /// Thrown on IO error. public void Stop() { - StateMachine.Status = Status.CLOSED; + if (listeners.ContainsKey((uint)StateMachine.localPort)) + { + listeners.Remove((uint)StateMachine.localPort); + } } /// From 67b3486affd6d0053113f9ef4c34b66648c342a0 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 28 May 2021 16:30:59 +0200 Subject: [PATCH 166/314] Add debug --- .../Network/IPv4/TCP/TCPPacket.cs | 20 +++++++++++-- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 29 +++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 6d23ad9584..ea4520e25b 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -52,7 +52,7 @@ internal static void TCPHandler(byte[] packetData) { var packet = new TCPPacket(packetData); - Global.mDebugger.Send("[Received] TCP packet from " + packet.SourceIP.ToString() + ":" + packet.SourcePort.ToString()); + Global.mDebugger.Send("[Received] " + packet.ToString()); if (packet.CheckCRC()) { @@ -417,14 +417,28 @@ internal byte[] TCP_Data } } + /// + /// Convert a byte to a hexidecimal char + /// + /// + /// + private static char ToHex(byte b) + { + if (b < 0 || b > 15) + { + throw new Exception("IntToHexChar: input out of range for Hex value"); + } + return b < 10 ? (char)(b + 48) : (char)(b + 55); + } + /// /// To string. /// /// string value. public override string ToString() { - return "TCP Packet Src=" + SourceIP + ":" + SourcePort + "," + - "Dest=" + DestinationIP + ":" + DestinationPort + ", DataLen=" + TCP_DataLength; + return "TCP Packet src=" + SourceIP + ":" + SourcePort + ", " + "dst=" + DestinationIP + ":" + DestinationPort + + ", flags=0x" + ToHex(TCPFlags) + ", seq=" + SequenceNumber + ", ack=" + AckNumber; } } } diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index fc472a9ab7..1e20cbaefb 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -72,10 +72,33 @@ internal class Tcp /// internal uint LastSequenceNumber; - internal bool WaitingAck = false; + internal bool WaitingAck; internal byte[] data; + /// + /// String / enum correspondance (used for debugging) + /// + internal string[] table; + + public Tcp() + { + WaitingAck = false; + + table = new string[11]; + table[0] = "LISTEN"; + table[1] = "SYN_SENT"; + table[2] = "SYN_RECEIVED"; + table[3] = "ESTABLISHED"; + table[4] = "FIN_WAIT1"; + table[5] = "FIN_WAIT2"; + table[6] = "CLOSE_WAIT"; + table[7] = "CLOSING"; + table[8] = "LAST_ACK"; + table[9] = "TIME_WAIT"; + table[10] = "CLOSED"; + } + /// /// Handle TCP discussions and data. /// @@ -84,6 +107,8 @@ internal class Tcp /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { + Global.mDebugger.Send("[Status] " + table[(int)Status]); + switch (Status) { case Status.LISTEN: @@ -265,7 +290,7 @@ public void ProcessSynSent(TCPPacket packet) /// Packet to receive. public void ProcessEstablished(TCPPacket packet) { - if (packet.ACK) + if (packet.ACK && !packet.FIN) { if (packet.PSH) { From d6591127c586caab1265f39eb4cba117dc023f95 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 28 May 2021 16:58:40 +0200 Subject: [PATCH 167/314] Better byte conversion to hex + Remove useless exceptions --- .../Network/IPv4/TCP/TCPPacket.cs | 20 +-- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 162 ++++++------------ .../Network/IPv4/TCP/TcpListener.cs | 4 +- 3 files changed, 68 insertions(+), 118 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index ea4520e25b..222c98ca83 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -15,7 +15,7 @@ namespace Cosmos.System.Network.IPv4.TCP /// /// TCP Flags /// - public enum Flags + public enum Flags : byte { FIN = (1 << 0), SYN = (1 << 1), @@ -52,8 +52,6 @@ internal static void TCPHandler(byte[] packetData) { var packet = new TCPPacket(packetData); - Global.mDebugger.Send("[Received] " + packet.ToString()); - if (packet.CheckCRC()) { var client = TcpClient.GetClient(packet.DestinationPort); @@ -418,17 +416,17 @@ internal byte[] TCP_Data } /// - /// Convert a byte to a hexidecimal char + /// Convert a byte to a hexadecimal char. /// /// - /// - private static char ToHex(byte b) + /// Hex string. + static string ToHex(byte b) { - if (b < 0 || b > 15) - { - throw new Exception("IntToHexChar: input out of range for Hex value"); - } - return b < 10 ? (char)(b + 48) : (char)(b + 55); + string r = ""; + string chars = "0123456789ABCDEF"; + + r += chars[b >> 4]; + return r += chars[b &= 0x0F]; } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index 1e20cbaefb..2e9c1d2645 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -107,7 +107,7 @@ public Tcp() /// Thrown on IO error. internal void ReceiveData(TCPPacket packet) { - Global.mDebugger.Send("[Status] " + table[(int)Status]); + Global.mDebugger.Send("[" + table[(int)Status] + "] " + packet.ToString()); switch (Status) { @@ -191,12 +191,6 @@ public void ProcessListen(TCPPacket packet) SendEmptyPacket(Flags.SYN | Flags.ACK); } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSED||LISTEN)"); - } } /// @@ -217,12 +211,6 @@ public void ProcessSynReceived(TCPPacket packet) Status = Status.ESTABLISHED; } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_RECEIVED)"); - } } /// @@ -276,12 +264,6 @@ public void ProcessSynSent(TCPPacket packet) throw new Exception("TCP connection closed! (Flag " + packet.TCPFlags + " received on SYN_SENT state)"); } } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=SYN_SENT)"); - } } /// @@ -354,12 +336,6 @@ public void ProcessEstablished(TCPPacket packet) Status = Status.LAST_ACK; } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=ESTABLISHED)"); - } } /// @@ -388,12 +364,6 @@ public void ProcessFinWait1(TCPPacket packet) { Status = Status.FIN_WAIT2; } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT1)"); - } } /// @@ -410,12 +380,6 @@ public void ProcessFinWait2(TCPPacket packet) WaitAndClose(); } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=FIN_WAIT2)"); - } } /// @@ -428,12 +392,6 @@ public void ProcessClosing(TCPPacket packet) { WaitAndClose(); } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSING)"); - } } /// @@ -446,18 +404,68 @@ public void ProcessCloseWait(TCPPacket packet) { Status = Status.CLOSED; } - else - { - Status = Status.CLOSED; - - throw new Exception("Received packet not supported. Is this an error? (Flag=" + packet.TCPFlags + ", Status=CLOSE_WAIT||LAST_ACK)"); - } } #endregion #region Utils + /// + /// Wait until remote receive ACK of its connection termination request. + /// + private void WaitAndClose() + { + Status = Status.TIME_WAIT; + + HAL.Global.PIT.Wait(300); //TODO: Calculate time value + + Status = Status.CLOSED; + } + + /// + /// Wait for new TCP connection status. + /// + internal bool WaitStatus(Status status, int timeout) + { + int second = 0; + int _deltaT = 0; + + while (Status != status) + { + if (second > (timeout / 1000)) + { + return false; + } + if (_deltaT != RTC.Second) + { + second++; + _deltaT = RTC.Second; + } + } + return true; + } + + /// + /// Wait for new TCP connection status (blocking). + /// + internal bool WaitStatus(Status status) + { + while (Status != status); + + return true; + } + + /// + /// Send acknowledgement packet + /// + private void SendEmptyPacket(Flags flag) + { + var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)flag, 0xFAF0, 0); + + OutgoingBuffer.AddPacket(packet); + NetworkStack.Update(); + } + /// /// Contatenate two byte arrays. https://stackoverflow.com/a/45531730 /// @@ -515,62 +523,6 @@ internal byte[][] ArraySplit(byte[] buffer, int chunksize = 1000) return bufferArray; } - /// - /// Wait until remote receive ACK of its connection termination request. - /// - private void WaitAndClose() - { - Status = Status.TIME_WAIT; - - HAL.Global.PIT.Wait(300); //TODO: Calculate time value - - Status = Status.CLOSED; - } - - /// - /// Wait for new TCP connection status. - /// - internal bool WaitStatus(Status status, int timeout) - { - int second = 0; - int _deltaT = 0; - - while (Status != status) - { - if (second > (timeout / 1000)) - { - return false; - } - if (_deltaT != RTC.Second) - { - second++; - _deltaT = RTC.Second; - } - } - return true; - } - - /// - /// Wait for new TCP connection status (blocking). - /// - internal bool WaitStatus(Status status) - { - while (Status != status); - - return true; - } - - /// - /// Send acknowledgement packet - /// - private void SendEmptyPacket(Flags flag) - { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)flag, 0xFAF0, 0); - - OutgoingBuffer.AddPacket(packet); - NetworkStack.Update(); - } - #endregion } } diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs index 2e5c628b2c..7f60917909 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs @@ -72,11 +72,11 @@ public TcpClient AcceptTcpClient(int timeout = -1) { if (timeout == -1) { - while (StateMachine.WaitStatus(Status.ESTABLISHED) != true) ; + while (StateMachine.WaitStatus(Status.ESTABLISHED) != true); } else { - while (StateMachine.WaitStatus(Status.ESTABLISHED, timeout) != true) ; + while (StateMachine.WaitStatus(Status.ESTABLISHED, timeout) != true); } return new TcpClient(StateMachine); From ac3b9d862ca26af69494df0ea9afe859d3304700 Mon Sep 17 00:00:00 2001 From: margaretsoler Date: Fri, 28 May 2021 23:51:30 +0200 Subject: [PATCH 168/314] Move utils to ArrayHelper.cs --- source/Cosmos.System2/Helpers/ArrayHelper.cs | 69 +++++++++++++++++++ .../Network/IPv4/TCP/TCPClient.cs | 3 +- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 62 +---------------- 3 files changed, 74 insertions(+), 60 deletions(-) create mode 100644 source/Cosmos.System2/Helpers/ArrayHelper.cs diff --git a/source/Cosmos.System2/Helpers/ArrayHelper.cs b/source/Cosmos.System2/Helpers/ArrayHelper.cs new file mode 100644 index 0000000000..9d42c749e1 --- /dev/null +++ b/source/Cosmos.System2/Helpers/ArrayHelper.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Cosmos.System.Helpers +{ + /// + /// Array Helper class (contains useful functions about array manipulation). + /// + public class ArrayHelper + { + /// + /// Contatenate two byte arrays. https://stackoverflow.com/a/45531730 + /// + /// First byte array. + /// Byte array to concatenate. + public static byte[] Concat(byte[] first, byte[] second) + { + byte[] output; + int alen = 0; + + if (first == null) + { + output = new byte[second.Length]; + } + else + { + output = new byte[first.Length + second.Length]; + alen = first.Length; + for (int i = 0; i < first.Length; i++) + { + output[i] = first[i]; + } + } + for (int j = 0; j < second.Length; j++) + { + output[alen + j] = second[j]; + } + return output; + } + + /// + /// Split byte array into chunks of a specified size. + /// + /// Byte array to split. + /// Chunk size. + public static byte[][] ArraySplit(byte[] buffer, int chunksize = 1000) + { + var size = buffer.Length; + var chunkCount = (buffer.Length + chunksize - 1) / chunksize; + var bufferArray = new byte[chunkCount][]; + int index = 0; + + for (var i = 0; i < chunkCount; i++) + { + bufferArray[i] = new byte[Math.Min(chunksize, buffer.Length - i * chunksize)]; + } + for (var i = 0; i < chunkCount; i++) + { + for (var j = 0; j < bufferArray[i].Length; j++) + { + bufferArray[i][j] = buffer[index]; + index++; + } + } + return bufferArray; + } + } +} diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index f315a3db45..276f80ea1a 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -10,6 +10,7 @@ using System.Text; using System.Threading; using Cosmos.HAL; +using Cosmos.System.Helpers; using Cosmos.System.Network.Config; namespace Cosmos.System.Network.IPv4.TCP @@ -195,7 +196,7 @@ public void Send(byte[] data) } if (data.Length > 536) { - var chunks = StateMachine.ArraySplit(data, 536); + var chunks = ArrayHelper.ArraySplit(data, 536); for (int i = 0; i < chunks.Length; i++) { diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index 2e9c1d2645..151ce25024 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Text; using Cosmos.HAL; +using Cosmos.System.Helpers; using Cosmos.System.Network.Config; namespace Cosmos.System.Network.IPv4.TCP @@ -282,7 +283,7 @@ public void ProcessEstablished(TCPPacket packet) LastSequenceNumber = packet.SequenceNumber; - data = Concat(data, packet.TCP_Data); + data = ArrayHelper.Concat(data, packet.TCP_Data); rxBuffer.Enqueue(packet); @@ -303,7 +304,7 @@ public void ProcessEstablished(TCPPacket packet) { AckNumber += packet.TCP_DataLength; - data = Concat(data, packet.TCP_Data); + data = ArrayHelper.Concat(data, packet.TCP_Data); } } return; @@ -466,63 +467,6 @@ private void SendEmptyPacket(Flags flag) NetworkStack.Update(); } - /// - /// Contatenate two byte arrays. https://stackoverflow.com/a/45531730 - /// - /// First byte array. - /// Byte array to concatenate. - private byte[] Concat(byte[] first, byte[] second) - { - byte[] output; - int alen = 0; - - if (first == null) - { - output = new byte[second.Length]; - } - else - { - output = new byte[first.Length + second.Length]; - alen = first.Length; - for (int i = 0; i < first.Length; i++) - { - output[i] = first[i]; - } - } - for (int j = 0; j < second.Length; j++) - { - output[alen + j] = second[j]; - } - return output; - } - - /// - /// Split byte array into chunks of a specified size. - /// - /// Byte array to split. - /// Chunk size. - internal byte[][] ArraySplit(byte[] buffer, int chunksize = 1000) - { - var size = buffer.Length; - var chunkCount = (buffer.Length + chunksize - 1) / chunksize; - var bufferArray = new byte[chunkCount][]; - int index = 0; - - for (var i = 0; i < chunkCount; i++) - { - bufferArray[i] = new byte[Math.Min(chunksize, buffer.Length - i * chunksize)]; - } - for (var i = 0; i < chunkCount; i++) - { - for (var j = 0; j < bufferArray[i].Length; j++) - { - bufferArray[i][j] = buffer[index]; - index++; - } - } - return bufferArray; - } - #endregion } } From 5e3152924b31d8d88ce3179d769921567aa77c23 Mon Sep 17 00:00:00 2001 From: KM198912 <55886806+KM198912@users.noreply.github.com> Date: Sat, 29 May 2021 02:16:16 -0700 Subject: [PATCH 169/314] Update Cosmos.iss Quick Typofix --- Setup/Cosmos.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Setup/Cosmos.iss b/Setup/Cosmos.iss index 75ed8c4d01..a9c83b243d 100644 --- a/Setup/Cosmos.iss +++ b/Setup/Cosmos.iss @@ -105,7 +105,7 @@ Source: ".\Artwork\Cosmos.ico"; DestDir: "{app}"; Flags: ignoreversion uninsremo ; XSharp Source: ".\Artwork\XSharp\XSharp.ico"; DestDir: "{app}\XSharp\"; Flags: ignoreversion uninsremovereadonly Source: "..\IL2CPU\source\Cosmos.Core.DebugStub\*.xs"; DestDir: "{app}\XSharp\DebugStub\"; Flags: ignoreversion uninsremovereadonly -; VMware +; HyperV Source: ".\Build\HyperV\*"; DestDir: "{app}\Build\HyperV"; Flags: ignoreversion uninsremovereadonly overwritereadonly recursesubdirs ; VMware Source: ".\Build\VMware\*"; DestDir: "{app}\Build\VMware"; Flags: ignoreversion uninsremovereadonly overwritereadonly recursesubdirs From 6181522a71ee92514a374fc4fb7c211bec5f5bee Mon Sep 17 00:00:00 2001 From: KM198912 <55886806+KM198912@users.noreply.github.com> Date: Sat, 29 May 2021 03:17:44 -0700 Subject: [PATCH 170/314] Update VFS.md Fix wrong 0:/ Documentation --- Docs/articles/Kernel/VFS.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Docs/articles/Kernel/VFS.md b/Docs/articles/Kernel/VFS.md index e75ced1811..09e306a681 100644 --- a/Docs/articles/Kernel/VFS.md +++ b/Docs/articles/Kernel/VFS.md @@ -30,7 +30,7 @@ After our VFS has been initialized, we can use more interesting functions, lets We use this function to get the size of the available free space in our file system, in bytes. ```C# -long available_space = fs.GetAvailableFreeSpace("0:/"); +long available_space = fs.GetAvailableFreeSpace(@"0:\"); Console.WriteLine("Available Free Space: " + available_space); ``` @@ -46,7 +46,7 @@ This will let us know what is the file system type that we are using. ![System Type](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Type.PNG) ```C# -string fs_type = fs.GetFileSystemType("0:/"); +string fs_type = fs.GetFileSystemType(@"0:\"); Console.WriteLine("File System Type: " + fs_type); ``` @@ -55,7 +55,7 @@ Console.WriteLine("File System Type: " + fs_type); We start by getting the directory entrys list, using: ```C# -var directory_list = fs.GetDirectoryListing("0:/"); +var directory_list = fs.GetDirectoryListing(@"0:\"); ``` Once we have it, we can get the names of our files: @@ -77,7 +77,7 @@ We need to get a directoryEntryList, find files in the list and print the conten of course, we start with geting the directory listing; ```C# -var directory_list = fs.GetDirectoryListing("0:/"); +var directory_list = fs.GetDirectoryListing(@"0:\"); ``` Now we can go through our list, and and print the txt file content. From 6a891226b83515edf77810c4fbb61f4a2d60d1f9 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 31 May 2021 15:59:38 +0200 Subject: [PATCH 171/314] Add comments --- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 8 ++++---- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 12 +++++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 276f80ea1a..7662220891 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -240,8 +240,8 @@ public byte[] NonBlockingReceive(ref EndPoint source) source.address = packet.SourceIP; source.port = packet.SourcePort; - var tmp = StateMachine.data; - StateMachine.data = null; + var tmp = StateMachine.Data; + StateMachine.Data = null; return tmp; } @@ -264,8 +264,8 @@ public byte[] Receive(ref EndPoint source) source.address = packet.SourceIP; source.port = packet.SourcePort; - var tmp = StateMachine.data; - StateMachine.data = null; + var tmp = StateMachine.Data; + StateMachine.Data = null; return tmp; } diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index 151ce25024..75141d9959 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -73,9 +73,15 @@ internal class Tcp /// internal uint LastSequenceNumber; + /// + /// Is waiting for an acknowledgement packet. + /// internal bool WaitingAck; - internal byte[] data; + /// + /// TCP Received Data. + /// + internal byte[] Data; /// /// String / enum correspondance (used for debugging) @@ -283,7 +289,7 @@ public void ProcessEstablished(TCPPacket packet) LastSequenceNumber = packet.SequenceNumber; - data = ArrayHelper.Concat(data, packet.TCP_Data); + Data = ArrayHelper.Concat(Data, packet.TCP_Data); rxBuffer.Enqueue(packet); @@ -304,7 +310,7 @@ public void ProcessEstablished(TCPPacket packet) { AckNumber += packet.TCP_DataLength; - data = ArrayHelper.Concat(data, packet.TCP_Data); + Data = ArrayHelper.Concat(Data, packet.TCP_Data); } } return; From 7221a381d28af033ad4d56f96841e6ce50a9c869 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 31 May 2021 16:35:46 +0200 Subject: [PATCH 172/314] Add URG boolean value to TcpPacket class + Add getFlags method + Use string interpolation + Better comments --- .../Network/IPv4/TCP/TCPPacket.cs | 44 ++++++++++++++++++- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 5 ++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index 222c98ca83..b8f3f549eb 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -228,6 +228,7 @@ protected override void InitFields() FIN = (RawData[47] & (byte)Flags.FIN) != 0; PSH = (RawData[47] & (byte)Flags.PSH) != 0; RST = (RawData[47] & (byte)Flags.RST) != 0; + URG = (RawData[47] & (byte)Flags.URG) != 0; if (TCPHeaderLength > 20) //options { @@ -353,6 +354,10 @@ private bool CheckCRC() /// Is RST Flag set. /// internal bool RST; + /// + /// Is URG Flag set. + /// + internal bool URG; /// /// Get destination port. @@ -429,14 +434,49 @@ static string ToHex(byte b) return r += chars[b &= 0x0F]; } + /// + /// Get string representation of TCP flags. + /// + /// string value. + public string getFlags() + { + string flags = ""; + + if (FIN) + { + flags += "FIN|"; + } + if (SYN) + { + flags += "SYN|"; + } + if (RST) + { + flags += "RST|"; + } + if (PSH) + { + flags += "PSH|"; + } + if (ACK) + { + flags += "ACK|"; + } + if (URG) + { + flags += "URG|"; + } + + return flags.Remove(flags.Length - 1); + } + /// /// To string. /// /// string value. public override string ToString() { - return "TCP Packet src=" + SourceIP + ":" + SourcePort + ", " + "dst=" + DestinationIP + ":" + DestinationPort + - ", flags=0x" + ToHex(TCPFlags) + ", seq=" + SequenceNumber + ", ack=" + AckNumber; + return $"TCP Packet {SourceIP}:{SourcePort} -> {DestinationIP}:{DestinationPort} (flags={getFlags()}, seq={SequenceNumber}, ack={AckNumber})"; } } } diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index 75141d9959..593603ee9a 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -26,7 +26,8 @@ public enum Status } /// - /// Tcp class. Used to manage the TCP state machine + /// Tcp class. Used to manage the TCP state machine. + /// Handle received packets according to current TCP connection Status. Also contains TCB (Transmission Control Block) information. /// See RFC 793 for more information. /// internal class Tcp @@ -107,7 +108,7 @@ public Tcp() } /// - /// Handle TCP discussions and data. + /// Handle incoming TCP packets according to current connection status. /// /// Packet to receive. /// Thrown on fatal error (contact support). From d567a46da59026f594bfef2e5bf78d10652c1d15 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Mon, 31 May 2021 16:55:35 +0200 Subject: [PATCH 173/314] Use TryGetValue instead of ContainsKey --- source/Cosmos.System2/Network/IPv4/ICMPClient.cs | 12 ++++++++---- source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs | 12 ++++++++---- .../Cosmos.System2/Network/IPv4/TCP/TcpListener.cs | 12 ++++++++---- source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs | 12 ++++++++---- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/ICMPClient.cs b/source/Cosmos.System2/Network/IPv4/ICMPClient.cs index 293906b713..f915836277 100644 --- a/source/Cosmos.System2/Network/IPv4/ICMPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/ICMPClient.cs @@ -49,12 +49,16 @@ static ICMPClient() /// ICMPClient internal static ICMPClient GetClient(uint iphash) { - if (clients.ContainsKey(iphash) == true) + ICMPClient client; + + if (clients.TryGetValue(iphash, out client)) { - return clients[iphash]; + return client; + } + else + { + return null; } - - return null; } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 7662220891..eee5d7cc9c 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -46,12 +46,16 @@ static TcpClient() /// TcpClient internal static TcpClient GetClient(ushort destPort) { - if (clients.ContainsKey((uint)destPort)) + TcpClient client; + + if (clients.TryGetValue(destPort, out client)) { - return clients[(uint)destPort]; + return client; + } + else + { + return null; } - - return null; } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs index 7f60917909..10ebf2ba5d 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs @@ -36,12 +36,16 @@ static TcpListener() /// TcpClient internal static TcpListener GetListener(ushort destPort) { - if (listeners.ContainsKey((uint)destPort)) + TcpListener listener; + + if (listeners.TryGetValue(destPort, out listener)) { - return listeners[(uint)destPort]; + return listener; + } + else + { + return null; } - - return null; } /// diff --git a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs index 1d350d4c42..ce5ec611fb 100644 --- a/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs +++ b/source/Cosmos.System2/Network/IPv4/UDP/UdpClient.cs @@ -56,12 +56,16 @@ static UdpClient() /// UdpClient internal static UdpClient GetClient(ushort destPort) { - if (clients.ContainsKey((uint)destPort) == true) + UdpClient client; + + if (clients.TryGetValue(destPort, out client)) { - return clients[(uint)destPort]; + return client; + } + else + { + return null; } - - return null; } /// From 3b65d71a3229fe61ed31c6782107f65a55db4d87 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 1 Jun 2021 14:41:59 +0200 Subject: [PATCH 174/314] Handle ACK when LISTEN (happens when distant client not closed) --- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index 593603ee9a..2479df363e 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -177,11 +177,10 @@ public void ProcessListen(TCPPacket packet) } else if (packet.ACK) { - SendEmptyPacket(Flags.RST); - - Status = Status.CLOSED; + AckNumber = packet.SequenceNumber; + SequenceNumber = packet.AckNumber; - throw new Exception("TCP connection closed! (ACK received on LISTEN state)"); + Status = Status.ESTABLISHED; } else if (packet.SYN) { From 4c55c6cbd94d45bcdc3401f17c2251d3a6abc09a Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 2 Jun 2021 14:21:49 +0200 Subject: [PATCH 175/314] Start FTP server over TCP --- .../Network/IPv4/TCP/FTP/FtpServer.cs | 281 ++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs new file mode 100644 index 0000000000..18288fecea --- /dev/null +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -0,0 +1,281 @@ +/* +* PROJECT: Cosmos Operating System Development +* CONTENT: FTP Client +* PROGRAMMERS: Valentin Charbonnier +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading; +using Console = global::System.Console; + +namespace Cosmos.System.Network.IPv4.TCP.FTP +{ + public enum FtpCommandType + { + USER, //Specify user for authentication + PASS, //Specify password for authentication + CWD, //Change working directory + CDUP, //Change working directory to parent directory + QUIT, //Disconnection + DELE, //Delete file on the server + PWD, //Print working directory + PASV, //Enable "passive" mode for data transfer + PORT, //Enable "active" mode for data transfer + HELP, //List available commands + NOOP, //Do nothing + RETR, //Download file from server to client + STOR, //Upload file from client to server + LIST //List files in the current working directory + } + + public class FtpCommand + { + public string Command; + public string Content; + } + + public class FtpClient + { + public TcpClient Server; + public TcpClient Client; + + public string Username; + public string Password; + + public bool Connected; + + public bool IsConnected() + { + if (Connected == false) + { + SendReply(530, "Login incorrect."); + return Connected; + } + else + { + return Connected; + } + } + + /// + /// Process CWD command. + /// + /// Reply code. + /// Reply content. + public void SendReply(int code, string message) + { + Client.Send(Encoding.ASCII.GetBytes(code + " " + message + "\r\n")); + } + } + + /// + /// FtpServer class. Used to handle FTP client connections. + /// + public class FtpServer : IDisposable + { + public TcpListener tcpListener; + + private bool Listening; + + public List ftpClients; + + public string CurrentDirectory { get; set; } + + /// + /// Create new instance of the class. + /// + /// Thrown on fatal error (contact support). + /// Thrown if UdpClient with localPort 53 exists. + public FtpServer(string directory) + { + Listening = true; + ftpClients = new List(); + + CurrentDirectory = directory; + } + + public void Listen() + { + tcpListener = new TcpListener(21); + tcpListener.Start(); + + while (Listening) + { + var client = tcpListener.AcceptTcpClient(); + + global::System.Console.WriteLine("Client[0] : New connection from " + client.StateMachine.source.ToString()); + + ReceiveNewClient(client); + } + } + + public void ReceiveNewClient(TcpClient client) + { + var ftpClient = new FtpClient(); + ftpClient.Client = client; + ftpClient.Connected = false; + + ftpClient.SendReply(220, "Service ready for new user."); + + while (ftpClient.Client.IsConnected()) + { + ReceiveRequest(ftpClient); + } + + ftpClient.SendReply(221, "Service closing control connection."); + + ftpClient.Client.Close(); + + ftpClients.Add(ftpClient); + } + + public void ReceiveRequest(FtpClient ftpClient) + { + var ep = new EndPoint(Address.Zero, 0); + var data = Encoding.ASCII.GetString(ftpClient.Client.Receive(ref ep)); + + global::System.Console.WriteLine("Client[0] : " + data); + + var splitted = data.Split(' '); + + var command = new FtpCommand(); + command.Command = splitted[0]; + command.Content = splitted[1]; + command.Content.Remove(command.Content.Length - 3, 2); + + ProcessRequest(ftpClient, command); + } + + public void ProcessRequest(FtpClient ftpClient, FtpCommand command) + { + switch (command.Command) + { + case "USER": + ProcessUser(ftpClient, command); + break; + case "PASS": + ProcessPass(ftpClient, command); + break; + case "CWD": + ProcessCwd(ftpClient, command); + break; + case "CDUP": + break; + case "QUIT": + break; + case "DELE": + break; + case "PWD": + break; + case "PASV": + break; + case "PORT": + break; + case "HELP": + break; + case "NOOP": + break; + case "RETR": + break; + case "STOR": + break; + case "LIST": + break; + default: + ftpClient.SendReply(200, "Unknown command."); + break; + } + } + + /// + /// Process USER command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessUser(FtpClient ftpClient, FtpCommand command) + { + if (String.IsNullOrEmpty(ftpClient.Username)) { + ftpClient.Username = command.Content; + ftpClient.SendReply(331, "User name okay, need password."); + } + else if (command.Content == "anonymous") + { + ftpClient.Username = command.Content; + ftpClient.Connected = true; + ftpClient.SendReply(230, "User logged in, proceed."); + } + } + + /// + /// Process PASS command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessPass(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.Username == "anonymous") + { + ftpClient.SendReply(530, "Login incorrect."); + } + else if (String.IsNullOrEmpty(ftpClient.Username)) + { + ftpClient.SendReply(332, "Need account for login."); + } + else + { + ftpClient.Password = command.Content; + ftpClient.Connected = true; + ftpClient.SendReply(230, "User logged in, proceed."); + } + } + + /// + /// Process CWD command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessCwd(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + try + { + if (Directory.Exists(CurrentDirectory + command.Content)) + { + Directory.SetCurrentDirectory(CurrentDirectory); + CurrentDirectory = CurrentDirectory + command.Content + @"\"; + } + else if (File.Exists(CurrentDirectory + command.Content)) + { + ftpClient.SendReply(550, "Requested action not taken."); + } + else + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + } + + public void Close() + { + Listening = false; + tcpListener.Stop(); + } + + /// + /// Close Client + /// + public void Dispose() + { + Close(); + } + } +} From ecd6a49981fea6c9161a7d6d5f489e56dab495cb Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 2 Jun 2021 15:46:09 +0200 Subject: [PATCH 176/314] Add SYST, PWD, PSV and LIST commands --- .../Network/IPv4/TCP/FTP/FtpServer.cs | 141 +++++++++++++++--- 1 file changed, 124 insertions(+), 17 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index 18288fecea..acfa40a9c3 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -9,6 +9,7 @@ using System.IO; using System.Text; using System.Threading; +using Cosmos.System.FileSystem; using Console = global::System.Console; namespace Cosmos.System.Network.IPv4.TCP.FTP @@ -31,6 +32,13 @@ public enum FtpCommandType LIST //List files in the current working directory } + public enum TransferMode + { + NONE, + ACTV, + PASV + } + public class FtpCommand { public string Command; @@ -39,14 +47,25 @@ public class FtpCommand public class FtpClient { - public TcpClient Server; - public TcpClient Client; + public TcpClient Discussion; + + public TcpClient Data; + public TcpListener DataListener; + + public TransferMode Mode; public string Username; public string Password; public bool Connected; + public FtpClient(TcpClient client) + { + Discussion = client; + Connected = false; + Mode = TransferMode.NONE; + } + public bool IsConnected() { if (Connected == false) @@ -67,7 +86,7 @@ public bool IsConnected() /// Reply content. public void SendReply(int code, string message) { - Client.Send(Encoding.ASCII.GetBytes(code + " " + message + "\r\n")); + Discussion.Send(Encoding.ASCII.GetBytes(code + " " + message + "\r\n")); } } @@ -84,17 +103,20 @@ public class FtpServer : IDisposable public string CurrentDirectory { get; set; } + CosmosVFS FileSystem { get; set; } + /// /// Create new instance of the class. /// /// Thrown on fatal error (contact support). /// Thrown if UdpClient with localPort 53 exists. - public FtpServer(string directory) + public FtpServer(CosmosVFS fs, string directory) { Listening = true; ftpClients = new List(); CurrentDirectory = directory; + FileSystem = fs; } public void Listen() @@ -114,20 +136,18 @@ public void Listen() public void ReceiveNewClient(TcpClient client) { - var ftpClient = new FtpClient(); - ftpClient.Client = client; - ftpClient.Connected = false; + var ftpClient = new FtpClient(client); ftpClient.SendReply(220, "Service ready for new user."); - while (ftpClient.Client.IsConnected()) + while (ftpClient.Discussion.IsConnected()) { ReceiveRequest(ftpClient); } ftpClient.SendReply(221, "Service closing control connection."); - ftpClient.Client.Close(); + ftpClient.Discussion.Close(); ftpClients.Add(ftpClient); } @@ -135,7 +155,8 @@ public void ReceiveNewClient(TcpClient client) public void ReceiveRequest(FtpClient ftpClient) { var ep = new EndPoint(Address.Zero, 0); - var data = Encoding.ASCII.GetString(ftpClient.Client.Receive(ref ep)); + var data = Encoding.ASCII.GetString(ftpClient.Discussion.Receive(ref ep)); + data = data.Remove(data.Length - 2, 2); global::System.Console.WriteLine("Client[0] : " + data); @@ -143,8 +164,11 @@ public void ReceiveRequest(FtpClient ftpClient) var command = new FtpCommand(); command.Command = splitted[0]; - command.Content = splitted[1]; - command.Content.Remove(command.Content.Length - 3, 2); + + if (splitted.Length > 1) + { + command.Content = splitted[1]; + } ProcessRequest(ftpClient, command); } @@ -162,6 +186,9 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) case "CWD": ProcessCwd(ftpClient, command); break; + case "SYST": + ftpClient.SendReply(215, "CosmosOS"); + break; case "CDUP": break; case "QUIT": @@ -169,8 +196,10 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) case "DELE": break; case "PWD": + ProcessPwd(ftpClient, command); break; case "PASV": + ProcessPasv(ftpClient, command); break; case "PORT": break; @@ -183,6 +212,7 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) case "STOR": break; case "LIST": + ProcessList(ftpClient, command); break; default: ftpClient.SendReply(200, "Unknown command."); @@ -197,16 +227,20 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) /// FTP Command. public void ProcessUser(FtpClient ftpClient, FtpCommand command) { - if (String.IsNullOrEmpty(ftpClient.Username)) { - ftpClient.Username = command.Content; - ftpClient.SendReply(331, "User name okay, need password."); - } - else if (command.Content == "anonymous") + if (command.Content == "anonymous") { ftpClient.Username = command.Content; ftpClient.Connected = true; ftpClient.SendReply(230, "User logged in, proceed."); } + else if (String.IsNullOrEmpty(ftpClient.Username)) { + ftpClient.Username = command.Content; + ftpClient.SendReply(331, "User name okay, need password."); + } + else + { + ftpClient.SendReply(550, "Requested action not taken."); + } } /// @@ -264,6 +298,79 @@ public void ProcessCwd(FtpClient ftpClient, FtpCommand command) } } + /// + /// Process PWD command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessPwd(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + ftpClient.SendReply(257, "/" + CurrentDirectory + "/ created."); + } + } + + /// + /// Process PASV command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessPasv(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + //TODO: Find port dynamically. + int port = 20; + var address = ftpClient.Discussion.StateMachine.source.ToByteArray(); + + ftpClient.SendReply(227, $"Entering Passive Mode ({address[0]},{address[1]},{address[2]},{address[3]},{port / 256},{port % 256})"); + + ftpClient.DataListener = new TcpListener(port); + ftpClient.DataListener.Start(); + + ftpClient.Mode = TransferMode.PASV; + } + } + + /// + /// Process LIST command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessList(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (ftpClient.Mode == TransferMode.NONE) + { + ftpClient.SendReply(425, "Can't open data connection."); + } + else if (ftpClient.Mode == TransferMode.ACTV) + { + ftpClient.SendReply(425, "Can't open data connection."); + throw new NotImplementedException("FTP LIST command currently not supported in ACTV mode."); + } + else if (ftpClient.Mode == TransferMode.PASV) + { + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); + + var directory_list = FileSystem.GetDirectoryListing(CurrentDirectory + command.Content); + + var sb = new StringBuilder(); + foreach (var directoryEntry in directory_list) + { + sb.AppendLine(directoryEntry.mName); + } + + ftpClient.Data.Send(Encoding.ASCII.GetBytes(sb.ToString())); + + ftpClient.Data.Close(); + } + } + } + public void Close() { Listening = false; From d4ccdc5d78ae8fe95f0cb01c37511319491504a3 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 2 Jun 2021 16:08:44 +0200 Subject: [PATCH 177/314] Unix style LIST (filezilla support) --- .../Network/IPv4/TCP/FTP/FtpServer.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index acfa40a9c3..0ace5c316d 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -10,6 +10,7 @@ using System.Text; using System.Threading; using Cosmos.System.FileSystem; +using Cosmos.System.FileSystem.Listing; using Console = global::System.Console; namespace Cosmos.System.Network.IPv4.TCP.FTP @@ -361,11 +362,24 @@ public void ProcessList(FtpClient ftpClient, FtpCommand command) var sb = new StringBuilder(); foreach (var directoryEntry in directory_list) { + if (directoryEntry.mEntryType == DirectoryEntryTypeEnum.Directory) + { + sb.Append("d"); + } + else + { + sb.Append("-"); + } + sb.Append("rwxrwxrwx 1 unknown unknown "); + sb.Append(directoryEntry.mSize); + sb.Append(" Jan 1 09:00 "); sb.AppendLine(directoryEntry.mName); } ftpClient.Data.Send(Encoding.ASCII.GetBytes(sb.ToString())); + ftpClient.SendReply(226, "Closing data connection."); + ftpClient.Data.Close(); } } From 7dd1f4a7fc541bb20394f4b1a0ceb17dcbcd5410 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 2 Jun 2021 16:23:48 +0200 Subject: [PATCH 178/314] Add RMD + MKD + DELE commands --- .../Network/IPv4/TCP/FTP/FtpServer.cs | 113 +++++++++++++++++- 1 file changed, 109 insertions(+), 4 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index 0ace5c316d..1ca90b4151 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -195,6 +195,7 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) case "QUIT": break; case "DELE": + ProcessDele(ftpClient, command); break; case "PWD": ProcessPwd(ftpClient, command); @@ -212,6 +213,12 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) break; case "STOR": break; + case "RMD": + ProcessRmd(ftpClient, command); + break; + case "MKD": + ProcessMkd(ftpClient, command); + break; case "LIST": ProcessList(ftpClient, command); break; @@ -308,7 +315,7 @@ public void ProcessPwd(FtpClient ftpClient, FtpCommand command) { if (ftpClient.IsConnected()) { - ftpClient.SendReply(257, "/" + CurrentDirectory + "/ created."); + ftpClient.SendReply(257, CurrentDirectory + " created."); } } @@ -370,9 +377,8 @@ public void ProcessList(FtpClient ftpClient, FtpCommand command) { sb.Append("-"); } - sb.Append("rwxrwxrwx 1 unknown unknown "); - sb.Append(directoryEntry.mSize); - sb.Append(" Jan 1 09:00 "); + sb.Append("rwxrwxrwx "); + sb.Append(directoryEntry.mSize + " "); sb.AppendLine(directoryEntry.mName); } @@ -385,6 +391,105 @@ public void ProcessList(FtpClient ftpClient, FtpCommand command) } } + /// + /// Process DELE command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessDele(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (String.IsNullOrEmpty(command.Command)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (File.Exists(CurrentDirectory + command.Command)) + { + File.Delete(CurrentDirectory + command.Command); + ftpClient.SendReply(250, "Requested file action okay, completed."); + } + else + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + } + + /// + /// Process DELE command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessRmd(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (String.IsNullOrEmpty(command.Command)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (Directory.Exists(CurrentDirectory + command.Command)) + { + Directory.Delete(CurrentDirectory + command.Command, true); + ftpClient.SendReply(200, "Command okay."); + } + else + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + } + + /// + /// Process DELE command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessMkd(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (String.IsNullOrEmpty(command.Command)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (Directory.Exists(CurrentDirectory + command.Command)) + { + ftpClient.SendReply(550, "Requested action not taken."); + } + else + { + Directory.CreateDirectory(CurrentDirectory + command.Command); + ftpClient.SendReply(200, "Command okay."); + } + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + } + public void Close() { Listening = false; From 002993a9db971dc6e849992e93568d391afe9f4b Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 2 Jun 2021 16:27:40 +0200 Subject: [PATCH 179/314] ProcessPwd fix --- source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index 1ca90b4151..bbab1c8ba6 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -315,7 +315,7 @@ public void ProcessPwd(FtpClient ftpClient, FtpCommand command) { if (ftpClient.IsConnected()) { - ftpClient.SendReply(257, CurrentDirectory + " created."); + ftpClient.SendReply(257, "/" + CurrentDirectory + "/ created."); } } @@ -425,7 +425,7 @@ public void ProcessDele(FtpClient ftpClient, FtpCommand command) } /// - /// Process DELE command. + /// Process RMD command. /// /// FTP Client. /// FTP Command. @@ -458,7 +458,7 @@ public void ProcessRmd(FtpClient ftpClient, FtpCommand command) } /// - /// Process DELE command. + /// Process MKD command. /// /// FTP Client. /// FTP Command. From f26328e0e29b6d7158d385b94f0b0d92afb876a5 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 2 Jun 2021 16:34:29 +0200 Subject: [PATCH 180/314] Filesystem fixes --- .../Network/IPv4/TCP/FTP/FtpServer.cs | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index bbab1c8ba6..e51c0b3740 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -285,10 +285,10 @@ public void ProcessCwd(FtpClient ftpClient, FtpCommand command) { try { - if (Directory.Exists(CurrentDirectory + command.Content)) + if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) { + CurrentDirectory = CurrentDirectory + "\\" + command.Content; Directory.SetCurrentDirectory(CurrentDirectory); - CurrentDirectory = CurrentDirectory + command.Content + @"\"; } else if (File.Exists(CurrentDirectory + command.Content)) { @@ -364,7 +364,7 @@ public void ProcessList(FtpClient ftpClient, FtpCommand command) ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); ftpClient.DataListener.Stop(); - var directory_list = FileSystem.GetDirectoryListing(CurrentDirectory + command.Content); + var directory_list = FileSystem.GetDirectoryListing(CurrentDirectory + "\\" + command.Content); var sb = new StringBuilder(); foreach (var directoryEntry in directory_list) @@ -377,8 +377,9 @@ public void ProcessList(FtpClient ftpClient, FtpCommand command) { sb.Append("-"); } - sb.Append("rwxrwxrwx "); - sb.Append(directoryEntry.mSize + " "); + sb.Append("rwxrwxrwx 1 unknown unknown "); + sb.Append(directoryEntry.mSize); + sb.Append(" Jan 1 09:00 "); sb.AppendLine(directoryEntry.mName); } @@ -407,9 +408,9 @@ public void ProcessDele(FtpClient ftpClient, FtpCommand command) } try { - if (File.Exists(CurrentDirectory + command.Command)) + if (File.Exists(CurrentDirectory + "\\" + command.Command)) { - File.Delete(CurrentDirectory + command.Command); + File.Delete(CurrentDirectory + "\\" + command.Command); ftpClient.SendReply(250, "Requested file action okay, completed."); } else @@ -440,9 +441,9 @@ public void ProcessRmd(FtpClient ftpClient, FtpCommand command) } try { - if (Directory.Exists(CurrentDirectory + command.Command)) + if (Directory.Exists(CurrentDirectory + "\\" + command.Command)) { - Directory.Delete(CurrentDirectory + command.Command, true); + Directory.Delete(CurrentDirectory + "\\" + command.Command, true); ftpClient.SendReply(200, "Command okay."); } else @@ -473,13 +474,13 @@ public void ProcessMkd(FtpClient ftpClient, FtpCommand command) } try { - if (Directory.Exists(CurrentDirectory + command.Command)) + if (Directory.Exists(CurrentDirectory + "\\" + command.Command)) { ftpClient.SendReply(550, "Requested action not taken."); } else { - Directory.CreateDirectory(CurrentDirectory + command.Command); + Directory.CreateDirectory(CurrentDirectory + "\\" + command.Command); ftpClient.SendReply(200, "Command okay."); } } From 3a34cb6c433751b6fc8008b73d869d4059a29791 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 2 Jun 2021 16:52:19 +0200 Subject: [PATCH 181/314] Add CDUP + backslash fixes --- .../Network/IPv4/TCP/FTP/FtpServer.cs | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index e51c0b3740..828be90799 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -87,6 +87,7 @@ public bool IsConnected() /// Reply content. public void SendReply(int code, string message) { + message = message.Replace('\\', '/'); Discussion.Send(Encoding.ASCII.GetBytes(code + " " + message + "\r\n")); } } @@ -169,6 +170,7 @@ public void ReceiveRequest(FtpClient ftpClient) if (splitted.Length > 1) { command.Content = splitted[1]; + command.Content = command.Content.Replace('/', '\\'); } ProcessRequest(ftpClient, command); @@ -191,6 +193,7 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) ftpClient.SendReply(215, "CosmosOS"); break; case "CDUP": + ProcessCdup(ftpClient, command); break; case "QUIT": break; @@ -289,6 +292,7 @@ public void ProcessCwd(FtpClient ftpClient, FtpCommand command) { CurrentDirectory = CurrentDirectory + "\\" + command.Content; Directory.SetCurrentDirectory(CurrentDirectory); + ftpClient.SendReply(250, "Requested file action okay."); } else if (File.Exists(CurrentDirectory + command.Content)) { @@ -315,7 +319,7 @@ public void ProcessPwd(FtpClient ftpClient, FtpCommand command) { if (ftpClient.IsConnected()) { - ftpClient.SendReply(257, "/" + CurrentDirectory + "/ created."); + ftpClient.SendReply(257, "/" + CurrentDirectory + " created."); } } @@ -491,6 +495,27 @@ public void ProcessMkd(FtpClient ftpClient, FtpCommand command) } } + /// + /// Process CDUP command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessCdup(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + try + { + CurrentDirectory = new DirectoryInfo(CurrentDirectory).Parent.FullName; + ftpClient.SendReply(250, "Requested file action okay."); + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + } + public void Close() { Listening = false; From a6c2c3eed3479b257bfb176ddc70a188d5ddbf49 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 2 Jun 2021 17:04:04 +0200 Subject: [PATCH 182/314] Command content with space fix --- source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index 828be90799..fa9e3a9ff5 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -169,7 +169,8 @@ public void ReceiveRequest(FtpClient ftpClient) if (splitted.Length > 1) { - command.Content = splitted[1]; + int i = data.IndexOf(" ") + 1; + command.Content = data.Substring(i); command.Content = command.Content.Replace('/', '\\'); } From 1e9c829d73adb8843cf71aec6d8dbd69c9d10c21 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 2 Jun 2021 17:17:11 +0200 Subject: [PATCH 183/314] Add STOR + RETR command --- .../Network/IPv4/TCP/FTP/FtpServer.cs | 119 +++++++++++++++++- 1 file changed, 116 insertions(+), 3 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index fa9e3a9ff5..fe6f7a77d3 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -216,6 +216,7 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) case "RETR": break; case "STOR": + ProcessStor(ftpClient, command); break; case "RMD": ProcessRmd(ftpClient, command); @@ -239,6 +240,11 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) /// FTP Command. public void ProcessUser(FtpClient ftpClient, FtpCommand command) { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } if (command.Content == "anonymous") { ftpClient.Username = command.Content; @@ -262,6 +268,11 @@ public void ProcessUser(FtpClient ftpClient, FtpCommand command) /// FTP Command. public void ProcessPass(FtpClient ftpClient, FtpCommand command) { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } if (ftpClient.Username == "anonymous") { ftpClient.SendReply(530, "Login incorrect."); @@ -287,6 +298,11 @@ public void ProcessCwd(FtpClient ftpClient, FtpCommand command) { if (ftpClient.IsConnected()) { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } try { if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) @@ -355,6 +371,11 @@ public void ProcessList(FtpClient ftpClient, FtpCommand command) { if (ftpClient.IsConnected()) { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } if (ftpClient.Mode == TransferMode.NONE) { ftpClient.SendReply(425, "Can't open data connection."); @@ -406,7 +427,7 @@ public void ProcessDele(FtpClient ftpClient, FtpCommand command) { if (ftpClient.IsConnected()) { - if (String.IsNullOrEmpty(command.Command)) + if (String.IsNullOrEmpty(command.Content)) { ftpClient.SendReply(501, "Syntax error in parameters or arguments."); return; @@ -439,7 +460,7 @@ public void ProcessRmd(FtpClient ftpClient, FtpCommand command) { if (ftpClient.IsConnected()) { - if (String.IsNullOrEmpty(command.Command)) + if (String.IsNullOrEmpty(command.Content)) { ftpClient.SendReply(501, "Syntax error in parameters or arguments."); return; @@ -472,7 +493,7 @@ public void ProcessMkd(FtpClient ftpClient, FtpCommand command) { if (ftpClient.IsConnected()) { - if (String.IsNullOrEmpty(command.Command)) + if (String.IsNullOrEmpty(command.Content)) { ftpClient.SendReply(501, "Syntax error in parameters or arguments."); return; @@ -517,6 +538,98 @@ public void ProcessCdup(FtpClient ftpClient, FtpCommand command) } } + /// + /// Process STOR command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessStor(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + if (ftpClient.Mode == TransferMode.NONE) + { + ftpClient.SendReply(425, "Can't open data connection."); + } + else if (ftpClient.Mode == TransferMode.ACTV) + { + ftpClient.SendReply(425, "Can't open data connection."); + throw new NotImplementedException("FTP STOR command currently not supported in ACTV mode."); + } + else if (ftpClient.Mode == TransferMode.PASV) + { + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); + + var ep = new EndPoint(Address.Zero, 0); + var data = ftpClient.Data.Receive(ref ep); + + try + { + File.WriteAllBytes(CurrentDirectory + "\\" + command.Content, data); + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + + ftpClient.SendReply(226, "Closing data connection."); + + ftpClient.Data.Close(); + } + } + } + + /// + /// Process RETR command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessRetr(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + if (ftpClient.Mode == TransferMode.NONE) + { + ftpClient.SendReply(425, "Can't open data connection."); + } + else if (ftpClient.Mode == TransferMode.ACTV) + { + ftpClient.SendReply(425, "Can't open data connection."); + throw new NotImplementedException("FTP RETR command currently not supported in ACTV mode."); + } + else if (ftpClient.Mode == TransferMode.PASV) + { + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); + + try + { + var data = File.ReadAllBytes(CurrentDirectory + "\\" + command.Content); + ftpClient.Data.Send(data); + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + + ftpClient.SendReply(226, "Closing data connection."); + + ftpClient.Data.Close(); + } + } + } + public void Close() { Listening = false; From b12504a8e62aa3a1d5505f0fa579a62f55a9f3de Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Wed, 2 Jun 2021 17:20:14 +0200 Subject: [PATCH 184/314] Remove arg check on LIST command --- source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index fe6f7a77d3..4da8364952 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -371,11 +371,6 @@ public void ProcessList(FtpClient ftpClient, FtpCommand command) { if (ftpClient.IsConnected()) { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } if (ftpClient.Mode == TransferMode.NONE) { ftpClient.SendReply(425, "Can't open data connection."); From 22225b8b6157abf60dd17e2dbdd72970e9cd549e Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Thu, 3 Jun 2021 16:46:53 +0200 Subject: [PATCH 185/314] Tcp: Allow multiple connection on same port --- .../Network/IPv4/TCP/FTP/FtpServer.cs | 28 +++-- .../Network/IPv4/TCP/TCPClient.cs | 76 +++--------- .../Network/IPv4/TCP/TCPPacket.cs | 13 +- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 114 +++++++++++++----- .../Network/IPv4/TCP/TcpListener.cs | 49 +------- 5 files changed, 131 insertions(+), 149 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index 4da8364952..80a717232e 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -130,7 +130,7 @@ public void Listen() { var client = tcpListener.AcceptTcpClient(); - global::System.Console.WriteLine("Client[0] : New connection from " + client.StateMachine.source.ToString()); + global::System.Console.WriteLine("Client[0] : New connection from " + client.StateMachine.LocalAddress.ToString()); ReceiveNewClient(client); } @@ -171,6 +171,12 @@ public void ReceiveRequest(FtpClient ftpClient) { int i = data.IndexOf(" ") + 1; command.Content = data.Substring(i); + + while (command.Content.StartsWith("/")) + { + command.Content = command.Content.Remove(0, 1); + } + command.Content = command.Content.Replace('/', '\\'); } @@ -351,7 +357,7 @@ public void ProcessPasv(FtpClient ftpClient, FtpCommand command) { //TODO: Find port dynamically. int port = 20; - var address = ftpClient.Discussion.StateMachine.source.ToByteArray(); + var address = ftpClient.Discussion.StateMachine.LocalAddress.ToByteArray(); ftpClient.SendReply(227, $"Entering Passive Mode ({address[0]},{address[1]},{address[2]},{address[3]},{port / 256},{port % 256})"); @@ -382,6 +388,8 @@ public void ProcessList(FtpClient ftpClient, FtpCommand command) } else if (ftpClient.Mode == TransferMode.PASV) { + ftpClient.SendReply(150, "Opening data connection."); + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); ftpClient.DataListener.Stop(); @@ -406,9 +414,9 @@ public void ProcessList(FtpClient ftpClient, FtpCommand command) ftpClient.Data.Send(Encoding.ASCII.GetBytes(sb.ToString())); - ftpClient.SendReply(226, "Closing data connection."); - ftpClient.Data.Close(); + + ftpClient.SendReply(226, "Transfer complete."); } } } @@ -558,6 +566,8 @@ public void ProcessStor(FtpClient ftpClient, FtpCommand command) } else if (ftpClient.Mode == TransferMode.PASV) { + ftpClient.SendReply(150, "Opening data connection."); + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); ftpClient.DataListener.Stop(); @@ -573,9 +583,9 @@ public void ProcessStor(FtpClient ftpClient, FtpCommand command) ftpClient.SendReply(550, "Requested action not taken."); } - ftpClient.SendReply(226, "Closing data connection."); - ftpClient.Data.Close(); + + ftpClient.SendReply(226, "Transfer complete."); } } } @@ -605,6 +615,8 @@ public void ProcessRetr(FtpClient ftpClient, FtpCommand command) } else if (ftpClient.Mode == TransferMode.PASV) { + ftpClient.SendReply(150, "Opening data connection."); + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); ftpClient.DataListener.Stop(); @@ -618,9 +630,9 @@ public void ProcessRetr(FtpClient ftpClient, FtpCommand command) ftpClient.SendReply(550, "Requested action not taken."); } - ftpClient.SendReply(226, "Closing data connection."); - ftpClient.Data.Close(); + + ftpClient.SendReply(226, "Transfer complete."); } } } diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index eee5d7cc9c..b6e01b8b28 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -25,39 +25,6 @@ public class TcpClient : IDisposable /// internal Tcp StateMachine; - /// - /// Clients dictionary. - /// - private static Dictionary clients; - - /// - /// Assign clients dictionary. - /// - /// Thrown on fatal error (contact support). - static TcpClient() - { - clients = new Dictionary(); - } - - /// - /// Get client. - /// - /// Destination port. - /// TcpClient - internal static TcpClient GetClient(ushort destPort) - { - TcpClient client; - - if (clients.TryGetValue(destPort, out client)) - { - return client; - } - else - { - return null; - } - } - /// /// Create new instance of the class. /// @@ -67,11 +34,6 @@ internal static TcpClient GetClient(ushort destPort) internal TcpClient(Tcp stateMachine) { StateMachine = stateMachine; - - if (StateMachine.localPort > 0) - { - clients.Add((uint)StateMachine.localPort, this); - } } /// @@ -82,18 +44,12 @@ internal TcpClient(Tcp stateMachine) /// Thrown if localPort already exists. public TcpClient(int localPort) { - StateMachine = new Tcp(); + StateMachine = new Tcp((ushort)localPort, 0, Address.Zero, Address.Zero); StateMachine.rxBuffer = new Queue(8); StateMachine.Status = Status.CLOSED; StateMachine.LastSequenceNumber = 0; - - StateMachine.localPort = localPort; - if (localPort > 0) - { - clients.Add((uint)localPort, this); - } } /// @@ -106,8 +62,8 @@ public TcpClient(int localPort) public TcpClient(Address dest, int destPort) : this(0) { - StateMachine.destination = dest; - StateMachine.destinationPort = destPort; + StateMachine.RemoteAddress = dest; + StateMachine.RemotePort = (ushort)destPort; } /// @@ -123,17 +79,19 @@ public void Connect(Address dest, int destPort, int timeout = 5000) throw new Exception("Client must be closed before setting a new connection."); } - StateMachine.destination = dest; - StateMachine.destinationPort = destPort; + StateMachine.RemoteAddress = dest; + StateMachine.RemotePort = (ushort)destPort; - StateMachine.source = IPConfig.FindNetwork(dest); + StateMachine.LocalAddress = IPConfig.FindNetwork(dest); //Generate Random Sequence Number var rnd = new Random(); StateMachine.SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); + Tcp.Connections.Add(StateMachine); + // Flags=0x02 -> Syn - var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)destPort, StateMachine.SequenceNumber, 0, 20, (byte)Flags.SYN, 0xFAF0, 0); + var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, (ushort)StateMachine.LocalPort, (ushort)destPort, StateMachine.SequenceNumber, 0, 20, (byte)Flags.SYN, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); @@ -159,7 +117,7 @@ public void Close() } if (StateMachine.Status == Status.ESTABLISHED) { - var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)StateMachine.destinationPort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, (byte)(Flags.FIN | Flags.ACK), 0xFAF0, 0); + var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, (ushort)StateMachine.LocalPort, (ushort)StateMachine.RemotePort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, (byte)(Flags.FIN | Flags.ACK), 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); @@ -173,9 +131,13 @@ public void Close() } } - if (clients.ContainsKey((uint)StateMachine.localPort)) + for (int i = 0; i < Tcp.Connections.Count; i++) { - clients.Remove((uint)StateMachine.localPort); + if (Tcp.Connections[i].Equals(StateMachine.LocalPort, StateMachine.RemotePort, StateMachine.LocalAddress, StateMachine.RemoteAddress)) + { + Tcp.Connections.RemoveAt(i); + return; + } } } @@ -190,7 +152,7 @@ public void Close() /// Thrown if TCP Status is not ESTABLISHED. public void Send(byte[] data) { - if ((StateMachine.destination == null) || (StateMachine.destinationPort == 0)) + if ((StateMachine.RemoteAddress == null) || (StateMachine.RemotePort == 0)) { throw new InvalidOperationException("Must establish a default remote host by calling Connect() before using this Send() overload"); } @@ -204,7 +166,7 @@ public void Send(byte[] data) for (int i = 0; i < chunks.Length; i++) { - var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)StateMachine.destinationPort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, i == chunks.Length - 2 ? (byte)(Flags.PSH | Flags.ACK) : (byte)(Flags.ACK), 0xFAF0, 0, chunks[i]); + var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, (ushort)StateMachine.LocalPort, (ushort)StateMachine.RemotePort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, i == chunks.Length - 2 ? (byte)(Flags.PSH | Flags.ACK) : (byte)(Flags.ACK), 0xFAF0, 0, chunks[i]); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); @@ -213,7 +175,7 @@ public void Send(byte[] data) } else { - var packet = new TCPPacket(StateMachine.source, StateMachine.destination, (ushort)StateMachine.localPort, (ushort)StateMachine.destinationPort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, (byte)(Flags.PSH | Flags.ACK), 0xFAF0, 0, data); + var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, (ushort)StateMachine.LocalPort, (ushort)StateMachine.RemotePort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, (byte)(Flags.PSH | Flags.ACK), 0xFAF0, 0, data); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index b8f3f549eb..d57f12c992 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -54,18 +54,11 @@ internal static void TCPHandler(byte[] packetData) if (packet.CheckCRC()) { - var client = TcpClient.GetClient(packet.DestinationPort); - if (client != null) - { - client.StateMachine.ReceiveData(packet); - return; - } + var connection = Tcp.GetConnection(packet.DestinationPort, packet.SourcePort, packet.DestinationIP, packet.SourceIP); - var listener = TcpListener.GetListener(packet.DestinationPort); - if (listener != null) + if (connection != null) { - listener.StateMachine.ReceiveData(packet); - return; + connection.ReceiveData(packet); } } else diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index 2479df363e..f10df708e0 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -33,21 +33,80 @@ public enum Status internal class Tcp { /// - /// Local port. + /// Connection list. /// - internal int localPort; + internal static List Connections; + /// - /// Source address. + /// String / enum correspondance (used for debugging) /// - internal Address source; + internal static string[] table; + /// - /// Destination address. + /// Assign connection list. + /// + /// Thrown on fatal error (contact support). + static Tcp() + { + Connections = new List(); + + table = new string[11]; + table[0] = "LISTEN"; + table[1] = "SYN_SENT"; + table[2] = "SYN_RECEIVED"; + table[3] = "ESTABLISHED"; + table[4] = "FIN_WAIT1"; + table[5] = "FIN_WAIT2"; + table[6] = "CLOSE_WAIT"; + table[7] = "CLOSING"; + table[8] = "LAST_ACK"; + table[9] = "TIME_WAIT"; + table[10] = "CLOSED"; + } + + /// + /// Get TCP Connection. + /// + /// Local port. + /// Destination port. + /// Local IPv4 Address. + /// Remote IPv4 Address. + /// Tcp + internal static Tcp GetConnection(ushort localPort, ushort remotePort, Address localIp, Address remoteIp) + { + foreach (var con in Connections) + { + if (con.Equals(localPort, remotePort, localIp, remoteIp)) + { + return con; + } + else if (con.LocalPort.Equals(localPort) && con.Status == Status.LISTEN) + { + return con; + } + } + return null; + } + + /// + /// Local port. /// - internal Address destination; + internal ushort LocalPort; + /// /// Destination port. /// - internal int destinationPort; + internal ushort RemotePort; + + /// + /// Source address. + /// + internal Address LocalAddress; + + /// + /// Destination address. + /// + internal Address RemoteAddress; /// /// RX buffer queue. @@ -84,27 +143,14 @@ internal class Tcp /// internal byte[] Data; - /// - /// String / enum correspondance (used for debugging) - /// - internal string[] table; - - public Tcp() + public Tcp(ushort localPort, ushort remotePort, Address localIp, Address remoteIp) { - WaitingAck = false; + LocalPort = localPort; + RemotePort = remotePort; + LocalAddress = localIp; + RemoteAddress = remoteIp; - table = new string[11]; - table[0] = "LISTEN"; - table[1] = "SYN_SENT"; - table[2] = "SYN_RECEIVED"; - table[3] = "ESTABLISHED"; - table[4] = "FIN_WAIT1"; - table[5] = "FIN_WAIT2"; - table[6] = "CLOSE_WAIT"; - table[7] = "CLOSING"; - table[8] = "LAST_ACK"; - table[9] = "TIME_WAIT"; - table[10] = "CLOSED"; + WaitingAck = false; } /// @@ -186,15 +232,15 @@ public void ProcessListen(TCPPacket packet) { Status = Status.SYN_RECEIVED; - source = IPConfig.FindNetwork(packet.SourceIP); + LocalAddress = IPConfig.FindNetwork(packet.SourceIP); AckNumber = packet.SequenceNumber + 1; var rnd = new Random(); SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); - destination = packet.SourceIP; - destinationPort = packet.SourcePort; + RemoteAddress = packet.SourceIP; + RemotePort = packet.SourcePort; SendEmptyPacket(Flags.SYN | Flags.ACK); } @@ -467,12 +513,20 @@ internal bool WaitStatus(Status status) /// private void SendEmptyPacket(Flags flag) { - var packet = new TCPPacket(source, destination, (ushort)localPort, (ushort)destinationPort, SequenceNumber, AckNumber, 20, (byte)flag, 0xFAF0, 0); + var packet = new TCPPacket(LocalAddress, RemoteAddress, (ushort)LocalPort, (ushort)RemotePort, SequenceNumber, AckNumber, 20, (byte)flag, 0xFAF0, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); } + /// + /// Equals connection + /// + internal bool Equals(ushort localPort, ushort remotePort, Address localIp, Address remoteIp) + { + return LocalPort.Equals(localPort) && RemotePort.Equals(remotePort) && LocalAddress.Hash.Equals(localIp.Hash) && RemoteAddress.Hash.Equals(remoteIp.Hash); + } + #endregion } } diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs index 10ebf2ba5d..fd9a237efe 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TcpListener.cs @@ -15,57 +15,20 @@ public class TcpListener : IDisposable /// internal Tcp StateMachine; - // - /// Clients dictionary. - /// - private static Dictionary listeners; - - /// - /// Assign listeners dictionary. - /// - /// Thrown on fatal error (contact support). - static TcpListener() - { - listeners = new Dictionary(); - } - - /// - /// Get client. - /// - /// Destination port. - /// TcpClient - internal static TcpListener GetListener(ushort destPort) - { - TcpListener listener; - - if (listeners.TryGetValue(destPort, out listener)) - { - return listener; - } - else - { - return null; - } - } - /// /// Create new instance of the class. /// + /// Local address. /// Local port. /// Thrown on fatal error (contact support). /// Thrown if localPort already exists. public TcpListener(int localPort) { - StateMachine = new Tcp(); + StateMachine = new Tcp((ushort)localPort, 0, Address.Zero, Address.Zero); StateMachine.rxBuffer = new Queue(8); - StateMachine.localPort = localPort; - - if (localPort > 0) - { - listeners.Add((uint)localPort, this); - } + StateMachine.LocalPort = (ushort)localPort; } /// @@ -94,6 +57,8 @@ public TcpClient AcceptTcpClient(int timeout = -1) public void Start() { StateMachine.Status = Status.LISTEN; + + Tcp.Connections.Add(StateMachine); } /// @@ -103,10 +68,6 @@ public void Start() /// Thrown on IO error. public void Stop() { - if (listeners.ContainsKey((uint)StateMachine.localPort)) - { - listeners.Remove((uint)StateMachine.localPort); - } } /// From c66b9532feefb4c449e8f2a25b73c4051d31e1f1 Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Thu, 3 Jun 2021 11:31:42 -0400 Subject: [PATCH 186/314] Fix bochs and cleanup --- source/Cosmos.HAL2/BlockDevice/ATAPI.cs | 78 +++++-------------------- 1 file changed, 16 insertions(+), 62 deletions(-) diff --git a/source/Cosmos.HAL2/BlockDevice/ATAPI.cs b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs index 6a13c38b30..25c3945c74 100644 --- a/source/Cosmos.HAL2/BlockDevice/ATAPI.cs +++ b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs @@ -1,10 +1,11 @@ -using System; +using Cosmos.Core; +using Cosmos.HAL.BlockDevice; +using System; using System.Collections.Generic; -using Cosmos.Core; using static Cosmos.HAL.BlockDevice.Ata; using static Cosmos.HAL.BlockDevice.AtaPio; -namespace Cosmos.HAL.BlockDevice +namespace Cosmos.HALs { public class ATAPI : BlockDevice { @@ -13,6 +14,7 @@ public class ATAPI : BlockDevice public const ushort SectorSize = 2048; private bool Primary { get; set; } private BusPositionEnum BusPosition { get; set; } + private AtaPio device; public class PacketCommands { @@ -22,13 +24,14 @@ public class PacketCommands public ATAPI(AtaPio parentDevice) { + device = parentDevice; this.BusPosition = parentDevice.BusPosition; this.Primary = parentDevice.ControllerID == ControllerIdEnum.Primary; mBlockSize = SectorSize; IO = new Core.IOGroup.ATA(!Primary); var p = BusPosition == BusPositionEnum.Master; - Ata.AtaDebugger.Send("ATAPI: Primary controller: "+ this.Primary+" Bus postion: IsMaster: "+ p); + Ata.AtaDebugger.Send("ATAPI: Primary controller: " + this.Primary + " Bus postion: IsMaster: " + p); Devices.Add(this); ATAPIDevices.Add(this); @@ -50,33 +53,9 @@ public void Init() IO.Control.Byte = 0; //Enable IRQs } - - public void Test() - { - Init(); - var b = new byte[] { 0, 0, 0 }; - ReadBlock(0, 1, ref b); - // PrintBytes(b); - Console.WriteLine("press enter for full test"); - Console.ReadLine(); - for (ulong i = 10; i < 100; i++) - { - ReadBlock(i, 1, ref b); - PrintBytes(b); - } - } - private void HandleIRQ(ref INTs.IRQContext aContext) { - Console.WriteLine("*****RECIVED IRQ*****"); - } - - public void PrintBytes(byte[] b) - { - for (int p = 0; p < b.Length - 1; p++) - { - Console.Write(b[p].ToString() + ","); - } + Ata.AtaDebugger.Send("ATAPI IRQ"); } public override void ReadBlock(ulong SectorNum, ulong SectorCount, ref byte[] aData) @@ -103,8 +82,6 @@ public override void ReadBlock(ulong SectorNum, ulong SectorCount, ref byte[] aD packet[10] = 0; packet[11] = 0; - - var buffer = new ushort[SectorSize / 2]; //Divide by 2 because we are reading words SendCmd(packet, SectorSize, ref buffer); @@ -142,16 +119,20 @@ private void SendCmd(byte[] AtapiPacket, int size, ref ushort[] outputData) //Wait for the select complete IO.Wait(); - Console.WriteLine("[ATAPI] Sending command"); IO.Features.Byte = 0x00; //PIO Mode + + //Set commmand size IO.LBA1.Byte = (byte)((SectorSize) & 0xFF); IO.LBA2.Byte = (byte)((SectorSize >> 8) & 0xFF); - IO.Command.Byte = (byte)AtaPio.Cmd.Packet; + + //Send ATAPI packet command + device.SendCmd(Cmd.Packet); Ata.AtaDebugger.Send("ATAPI: Polling"); - AtaWait(true); + Poll(true); Ata.AtaDebugger.Send("ATAPI: Polling complete"); + //Send the command as words for (int i = 0; i < AtapiPacket.Length; i++) { var b1 = AtapiPacket[i]; @@ -162,6 +143,7 @@ private void SendCmd(byte[] AtapiPacket, int size, ref ushort[] outputData) i++; } + Poll(true); CheckForErrors(); var a = (IO.LBA2.Byte << 8); @@ -178,29 +160,6 @@ private void SendCmd(byte[] AtapiPacket, int size, ref ushort[] outputData) } } - private void AtaWait(bool drq = false) - { - //Read status register 4 times - var junk = IO.Status.Byte; - junk = IO.Status.Byte; - junk = IO.Status.Byte; - junk = IO.Status.Byte; - - - while (true) - { - if ((IO.Status.Byte & (byte)AtaPio.Status.Busy) == 0) break; - } - - if (drq) - { - while (true) - { - if ((IO.Status.Byte & (byte)AtaPio.Status.DRQ) != 0) break; - } - } - } - public void Eject() { ushort[] output = new ushort[12]; @@ -211,7 +170,6 @@ private void Poll(bool checkDRQ = true) { // 400ns until BSR is set IO.Wait(); - Console.WriteLine("[ATAPI] Polling"); while (true) { @@ -231,25 +189,21 @@ private void Poll(bool checkDRQ = true) } } } - Console.WriteLine("[ATAPI] Finished Polling"); } private void CheckForErrors() { if ((IO.Status.Byte & (byte)AtaPio.Status.Error) != 0) { - Console.WriteLine("ATA Error"); throw new Exception("ATA Error occured!"); } if ((IO.Status.Byte & (byte)AtaPio.Status.ATA_SR_DF) != 0) { - Console.WriteLine("ATA Device Fault"); throw new Exception("ATA device fault encountered!"); } if ((IO.Status.Byte & (byte)AtaPio.Status.DRQ) == 0) { - Console.WriteLine("ATAPI DRQ not set"); //throw new Exception("ATAPI DRQ not set"); } } From 7ebd7b9fa26bdeabf9d5a7092e6dfb77b7fa7d5f Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Thu, 3 Jun 2021 11:34:20 -0400 Subject: [PATCH 187/314] Add the remaining documentation back --- source/Cosmos.Core/IOGroup/ATA.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/source/Cosmos.Core/IOGroup/ATA.cs b/source/Cosmos.Core/IOGroup/ATA.cs index 25d40c5928..51e5e11423 100644 --- a/source/Cosmos.Core/IOGroup/ATA.cs +++ b/source/Cosmos.Core/IOGroup/ATA.cs @@ -104,7 +104,9 @@ public ATA(bool aSecondary) AlternateStatus = new IOPortRead(xBAR1, 2); Control = new IOPortWrite(xBAR1, 2); } - + /// + /// Waits for IO operations to complete. + /// public void Wait() { // Used for the PATA and IOPort latency @@ -115,13 +117,21 @@ public void Wait() wait = Status.Byte; wait = Status.Byte; } - + /// + /// Get control base address. + /// + /// True if secondary ATA. + /// ushort value. private static ushort GetBAR1(bool aSecondary) { ushort xBAR1 = (ushort)(aSecondary ? 0x0374 : 0x03F4); return xBAR1; } - + /// + /// Get command base address. + /// + /// True if secondary ATA. + /// ushort value. private static ushort GetBAR0(bool aSecondary) { ushort xBAR0 = (ushort)(aSecondary ? 0x0170 : 0x01F0); From a2f13248f02cdec258c3027834d2a448ba18b7ca Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Thu, 3 Jun 2021 11:37:10 -0400 Subject: [PATCH 188/314] Fix a error --- source/Cosmos.HAL2/BlockDevice/ATAPI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Cosmos.HAL2/BlockDevice/ATAPI.cs b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs index 25c3945c74..1caeec5bee 100644 --- a/source/Cosmos.HAL2/BlockDevice/ATAPI.cs +++ b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs @@ -5,7 +5,7 @@ using static Cosmos.HAL.BlockDevice.Ata; using static Cosmos.HAL.BlockDevice.AtaPio; -namespace Cosmos.HALs +namespace Cosmos.HAL.BlockDevice { public class ATAPI : BlockDevice { From 2b27ae8828cebe52f4c84db9afdcdb81487d40d6 Mon Sep 17 00:00:00 2001 From: Arawn Davies Date: Thu, 3 Jun 2021 23:13:40 +0100 Subject: [PATCH 189/314] Update LICENSE.txt New decade of Cosmos :) --- LICENSE.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 60a301dfab..6034fa5e96 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,21 +1,21 @@ BSD 3-Clause License -Copyright (c) 2019, COSMOS Project +Copyright (c) 2021, CosmosOS, COSMOS Project All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE From c9fb31ed5db145e7c22308b01ac0ed4d765f5e43 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 4 Jun 2021 14:17:08 +0200 Subject: [PATCH 190/314] Add FTP active mode --- .../Network/IPv4/TCP/FTP/FtpServer.cs | 240 +++++++++++------- .../Network/IPv4/TCP/TCPClient.cs | 4 - 2 files changed, 154 insertions(+), 90 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index 80a717232e..0379ca0608 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -48,9 +48,12 @@ public class FtpCommand public class FtpClient { - public TcpClient Discussion; + public Address Address; + public int port; + public TcpClient Control; public TcpClient Data; + public TcpListener DataListener; public TransferMode Mode; @@ -62,7 +65,7 @@ public class FtpClient public FtpClient(TcpClient client) { - Discussion = client; + Control = client; Connected = false; Mode = TransferMode.NONE; } @@ -81,14 +84,14 @@ public bool IsConnected() } /// - /// Process CWD command. + /// Send text to control socket (usually port 21) /// /// Reply code. /// Reply content. public void SendReply(int code, string message) { message = message.Replace('\\', '/'); - Discussion.Send(Encoding.ASCII.GetBytes(code + " " + message + "\r\n")); + Control.Send(Encoding.ASCII.GetBytes(code + " " + message + "\r\n")); } } @@ -142,14 +145,14 @@ public void ReceiveNewClient(TcpClient client) ftpClient.SendReply(220, "Service ready for new user."); - while (ftpClient.Discussion.IsConnected()) + while (ftpClient.Control.IsConnected()) { ReceiveRequest(ftpClient); } ftpClient.SendReply(221, "Service closing control connection."); - ftpClient.Discussion.Close(); + ftpClient.Control.Close(); ftpClients.Add(ftpClient); } @@ -157,7 +160,7 @@ public void ReceiveNewClient(TcpClient client) public void ReceiveRequest(FtpClient ftpClient) { var ep = new EndPoint(Address.Zero, 0); - var data = Encoding.ASCII.GetString(ftpClient.Discussion.Receive(ref ep)); + var data = Encoding.ASCII.GetString(ftpClient.Control.Receive(ref ep)); data = data.Remove(data.Length - 2, 2); global::System.Console.WriteLine("Client[0] : " + data); @@ -214,6 +217,7 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) ProcessPasv(ftpClient, command); break; case "PORT": + ProcessPort(ftpClient, command); break; case "HELP": break; @@ -357,7 +361,7 @@ public void ProcessPasv(FtpClient ftpClient, FtpCommand command) { //TODO: Find port dynamically. int port = 20; - var address = ftpClient.Discussion.StateMachine.LocalAddress.ToByteArray(); + var address = ftpClient.Control.StateMachine.LocalAddress.ToByteArray(); ftpClient.SendReply(227, $"Entering Passive Mode ({address[0]},{address[1]},{address[2]},{address[3]},{port / 256},{port % 256})"); @@ -368,6 +372,25 @@ public void ProcessPasv(FtpClient ftpClient, FtpCommand command) } } + /// + /// Process PORT command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessPort(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + var splitted = command.Content.Split(','); + ftpClient.Address = new Address(Byte.Parse(splitted[0]), Byte.Parse(splitted[1]), Byte.Parse(splitted[2]), Byte.Parse(splitted[3])); + ftpClient.port = Int32.Parse(splitted[4]) * 256 + Int32.Parse(splitted[5]); + + ftpClient.SendReply(227, "Entering Active Mode."); + + ftpClient.Mode = TransferMode.ACTV; + } + } + /// /// Process LIST command. /// @@ -377,48 +400,59 @@ public void ProcessList(FtpClient ftpClient, FtpCommand command) { if (ftpClient.IsConnected()) { - if (ftpClient.Mode == TransferMode.NONE) + try { - ftpClient.SendReply(425, "Can't open data connection."); + if (ftpClient.Mode == TransferMode.NONE) + { + ftpClient.SendReply(425, "Can't open data connection."); + } + else if (ftpClient.Mode == TransferMode.ACTV) + { + ftpClient.Data.Connect(ftpClient.Address, ftpClient.port); + + DoList(ftpClient, command); + } + else if (ftpClient.Mode == TransferMode.PASV) + { + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); + + DoList(ftpClient, command); + } } - else if (ftpClient.Mode == TransferMode.ACTV) + catch { ftpClient.SendReply(425, "Can't open data connection."); - throw new NotImplementedException("FTP LIST command currently not supported in ACTV mode."); } - else if (ftpClient.Mode == TransferMode.PASV) - { - ftpClient.SendReply(150, "Opening data connection."); - - ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); - ftpClient.DataListener.Stop(); + } + } - var directory_list = FileSystem.GetDirectoryListing(CurrentDirectory + "\\" + command.Content); + private void DoList(FtpClient ftpClient, FtpCommand command) + { + var directory_list = FileSystem.GetDirectoryListing(CurrentDirectory + "\\" + command.Content); - var sb = new StringBuilder(); - foreach (var directoryEntry in directory_list) - { - if (directoryEntry.mEntryType == DirectoryEntryTypeEnum.Directory) - { - sb.Append("d"); - } - else - { - sb.Append("-"); - } - sb.Append("rwxrwxrwx 1 unknown unknown "); - sb.Append(directoryEntry.mSize); - sb.Append(" Jan 1 09:00 "); - sb.AppendLine(directoryEntry.mName); - } + var sb = new StringBuilder(); + foreach (var directoryEntry in directory_list) + { + if (directoryEntry.mEntryType == DirectoryEntryTypeEnum.Directory) + { + sb.Append("d"); + } + else + { + sb.Append("-"); + } + sb.Append("rwxrwxrwx 1 unknown unknown "); + sb.Append(directoryEntry.mSize); + sb.Append(" Jan 1 09:00 "); + sb.AppendLine(directoryEntry.mName); + } - ftpClient.Data.Send(Encoding.ASCII.GetBytes(sb.ToString())); + ftpClient.Data.Send(Encoding.ASCII.GetBytes(sb.ToString())); - ftpClient.Data.Close(); + ftpClient.Data.Close(); - ftpClient.SendReply(226, "Transfer complete."); - } - } + ftpClient.SendReply(226, "Transfer complete."); } /// @@ -555,39 +589,62 @@ public void ProcessStor(FtpClient ftpClient, FtpCommand command) ftpClient.SendReply(501, "Syntax error in parameters or arguments."); return; } - if (ftpClient.Mode == TransferMode.NONE) + try { - ftpClient.SendReply(425, "Can't open data connection."); + if (ftpClient.Mode == TransferMode.NONE) + { + ftpClient.SendReply(425, "Can't open data connection."); + } + else if (ftpClient.Mode == TransferMode.ACTV) + { + ftpClient.Data.Connect(ftpClient.Address, ftpClient.port); + + DoStor(ftpClient, command); + } + else if (ftpClient.Mode == TransferMode.PASV) + { + Global.mDebugger.Send("Test."); + + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); + + DoStor(ftpClient, command); + } } - else if (ftpClient.Mode == TransferMode.ACTV) + catch { ftpClient.SendReply(425, "Can't open data connection."); - throw new NotImplementedException("FTP STOR command currently not supported in ACTV mode."); } - else if (ftpClient.Mode == TransferMode.PASV) - { - ftpClient.SendReply(150, "Opening data connection."); - - ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); - ftpClient.DataListener.Stop(); + } + } - var ep = new EndPoint(Address.Zero, 0); - var data = ftpClient.Data.Receive(ref ep); + private void DoStor(FtpClient ftpClient, FtpCommand command) + { + Global.mDebugger.Send("Preparing to receive..."); - try - { - File.WriteAllBytes(CurrentDirectory + "\\" + command.Content, data); - } - catch - { - ftpClient.SendReply(550, "Requested action not taken."); - } + var ep = new EndPoint(Address.Zero, 0); + var data = ftpClient.Data.Receive(ref ep); - ftpClient.Data.Close(); + Global.mDebugger.Send("Data received!"); - ftpClient.SendReply(226, "Transfer complete."); - } + try + { + Global.mDebugger.Send("CurrentDirectory=" + CurrentDirectory); + Global.mDebugger.Send("File path =" + CurrentDirectory + "\\" + command.Content); + File.WriteAllBytes(CurrentDirectory + "\\" + command.Content, data); + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); } + + Global.mDebugger.Send("Closing..."); + + ftpClient.Data.Close(); + + Global.mDebugger.Send("CLOSED"); + + ftpClient.SendReply(226, "Transfer complete."); } /// @@ -604,37 +661,48 @@ public void ProcessRetr(FtpClient ftpClient, FtpCommand command) ftpClient.SendReply(501, "Syntax error in parameters or arguments."); return; } - if (ftpClient.Mode == TransferMode.NONE) - { - ftpClient.SendReply(425, "Can't open data connection."); - } - else if (ftpClient.Mode == TransferMode.ACTV) - { - ftpClient.SendReply(425, "Can't open data connection."); - throw new NotImplementedException("FTP RETR command currently not supported in ACTV mode."); - } - else if (ftpClient.Mode == TransferMode.PASV) + try { - ftpClient.SendReply(150, "Opening data connection."); - - ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); - ftpClient.DataListener.Stop(); - - try + if (ftpClient.Mode == TransferMode.NONE) { - var data = File.ReadAllBytes(CurrentDirectory + "\\" + command.Content); - ftpClient.Data.Send(data); + ftpClient.SendReply(425, "Can't open data connection."); } - catch + else if (ftpClient.Mode == TransferMode.ACTV) { - ftpClient.SendReply(550, "Requested action not taken."); - } + ftpClient.Data.Connect(ftpClient.Address, ftpClient.port); - ftpClient.Data.Close(); + DoRetr(ftpClient, command); + } + else if (ftpClient.Mode == TransferMode.PASV) + { + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); - ftpClient.SendReply(226, "Transfer complete."); + DoRetr(ftpClient, command); + } } + catch + { + ftpClient.SendReply(425, "Can't open data connection."); + } + } + } + + public void DoRetr(FtpClient ftpClient, FtpCommand command) + { + try + { + var data = File.ReadAllBytes(CurrentDirectory + "\\" + command.Content); + ftpClient.Data.Send(data); + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); } + + ftpClient.Data.Close(); + + ftpClient.SendReply(226, "Transfer complete."); } public void Close() diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index b6e01b8b28..8d65dfb48e 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -111,10 +111,6 @@ public void Connect(Address dest, int destPort, int timeout = 5000) /// Thrown if TCP Status is CLOSED. public void Close() { - if (StateMachine.Status == Status.CLOSED) - { - throw new Exception("Client already closed."); - } if (StateMachine.Status == Status.ESTABLISHED) { var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, (ushort)StateMachine.LocalPort, (ushort)StateMachine.RemotePort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, (byte)(Flags.FIN | Flags.ACK), 0xFAF0, 0); From c937aaa8adc4dd4d36c5bec4e6d7acfdcb1d3888 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 4 Jun 2021 15:31:41 +0200 Subject: [PATCH 191/314] Add QUIT command + PORT fix --- .../Network/IPv4/TCP/FTP/FtpServer.cs | 45 ++++++++++--------- .../Network/IPv4/TCP/TCPClient.cs | 2 +- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index 0379ca0608..2ab770c547 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -126,11 +126,10 @@ public FtpServer(CosmosVFS fs, string directory) public void Listen() { - tcpListener = new TcpListener(21); - tcpListener.Start(); - while (Listening) { + tcpListener = new TcpListener(21); + tcpListener.Start(); var client = tcpListener.AcceptTcpClient(); global::System.Console.WriteLine("Client[0] : New connection from " + client.StateMachine.LocalAddress.ToString()); @@ -149,12 +148,6 @@ public void ReceiveNewClient(TcpClient client) { ReceiveRequest(ftpClient); } - - ftpClient.SendReply(221, "Service closing control connection."); - - ftpClient.Control.Close(); - - ftpClients.Add(ftpClient); } public void ReceiveRequest(FtpClient ftpClient) @@ -206,6 +199,7 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) ProcessCdup(ftpClient, command); break; case "QUIT": + ProcessQuit(ftpClient, command); break; case "DELE": ProcessDele(ftpClient, command); @@ -220,10 +214,13 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) ProcessPort(ftpClient, command); break; case "HELP": + ftpClient.SendReply(200, "Help done."); break; case "NOOP": + ftpClient.SendReply(200, "Command okay."); break; case "RETR": + ProcessRetr(ftpClient, command); break; case "STOR": ProcessStor(ftpClient, command); @@ -238,7 +235,7 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) ProcessList(ftpClient, command); break; default: - ftpClient.SendReply(200, "Unknown command."); + ftpClient.SendReply(500, "Unknown command."); break; } } @@ -382,11 +379,14 @@ public void ProcessPort(FtpClient ftpClient, FtpCommand command) if (ftpClient.IsConnected()) { var splitted = command.Content.Split(','); - ftpClient.Address = new Address(Byte.Parse(splitted[0]), Byte.Parse(splitted[1]), Byte.Parse(splitted[2]), Byte.Parse(splitted[3])); + + ftpClient.Address = new Address((byte)int.Parse(splitted[0]), (byte)int.Parse(splitted[1]), (byte)int.Parse(splitted[2]), (byte)int.Parse(splitted[3])); ftpClient.port = Int32.Parse(splitted[4]) * 256 + Int32.Parse(splitted[5]); ftpClient.SendReply(227, "Entering Active Mode."); + ftpClient.Data = new TcpClient(ftpClient.port); + ftpClient.Mode = TransferMode.ACTV; } } @@ -620,17 +620,11 @@ public void ProcessStor(FtpClient ftpClient, FtpCommand command) private void DoStor(FtpClient ftpClient, FtpCommand command) { - Global.mDebugger.Send("Preparing to receive..."); - var ep = new EndPoint(Address.Zero, 0); var data = ftpClient.Data.Receive(ref ep); - Global.mDebugger.Send("Data received!"); - try { - Global.mDebugger.Send("CurrentDirectory=" + CurrentDirectory); - Global.mDebugger.Send("File path =" + CurrentDirectory + "\\" + command.Content); File.WriteAllBytes(CurrentDirectory + "\\" + command.Content, data); } catch @@ -638,12 +632,8 @@ private void DoStor(FtpClient ftpClient, FtpCommand command) ftpClient.SendReply(550, "Requested action not taken."); } - Global.mDebugger.Send("Closing..."); - ftpClient.Data.Close(); - Global.mDebugger.Send("CLOSED"); - ftpClient.SendReply(226, "Transfer complete."); } @@ -693,6 +683,7 @@ public void DoRetr(FtpClient ftpClient, FtpCommand command) try { var data = File.ReadAllBytes(CurrentDirectory + "\\" + command.Content); + ftpClient.Data.Send(data); } catch @@ -705,6 +696,18 @@ public void DoRetr(FtpClient ftpClient, FtpCommand command) ftpClient.SendReply(226, "Transfer complete."); } + /// + /// Process QUIT command. + /// + /// FTP Client. + /// FTP Command. + public void ProcessQuit(FtpClient ftpClient, FtpCommand command) + { + ftpClient.SendReply(221, "Service closing control connection."); + + ftpClient.Control.Close(); + } + public void Close() { Listening = false; diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 8d65dfb48e..893929d545 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -74,7 +74,7 @@ public TcpClient(Address dest, int destPort) /// Thrown if TCP Status is not CLOSED. public void Connect(Address dest, int destPort, int timeout = 5000) { - if (StateMachine.Status != Status.CLOSED) + if (StateMachine.Status == Status.ESTABLISHED) { throw new Exception("Client must be closed before setting a new connection."); } From 708f62b879d7af25752957258656242d13b96f80 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 4 Jun 2021 15:41:31 +0200 Subject: [PATCH 192/314] Add TYPE command (to support FileZilla) --- source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index 2ab770c547..f84cf341d3 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -234,6 +234,9 @@ public void ProcessRequest(FtpClient ftpClient, FtpCommand command) case "LIST": ProcessList(ftpClient, command); break; + case "TYPE": + ftpClient.SendReply(200, "Command okay."); + break; default: ftpClient.SendReply(500, "Unknown command."); break; From 3615506cb68a7e0965e89e21c98541a66fbdf97e Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 4 Jun 2021 16:14:37 +0200 Subject: [PATCH 193/314] Move FTP client + Command Manager to other files + add code doc --- .../Network/IPv4/TCP/FTP/FtpClient.cs | 100 +++ .../Network/IPv4/TCP/FTP/FtpCommandManager.cs | 593 +++++++++++++++ .../Network/IPv4/TCP/FTP/FtpServer.cs | 673 ++---------------- 3 files changed, 748 insertions(+), 618 deletions(-) create mode 100644 source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpClient.cs create mode 100644 source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpClient.cs new file mode 100644 index 0000000000..4c81fb9987 --- /dev/null +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpClient.cs @@ -0,0 +1,100 @@ +/* +* PROJECT: Cosmos Operating System Development +* CONTENT: FTP Client +* PROGRAMMERS: Valentin Charbonnier +*/ + +using System.Text; + +namespace Cosmos.System.Network.IPv4.TCP.FTP +{ + /// + /// FtpClient class. + /// + internal class FtpClient + { + /// + /// Client IP Address. + /// + internal Address Address { get; set; } + + /// + /// Client TCP Port. + /// + internal int Port { get; set; } + + /// + /// TCP Control Client. Used to send commands. + /// + internal TcpClient Control { get; set; } + + /// + /// TCP Data Transfer Client. Used to transfer data. + /// + internal TcpClient Data { get; set; } + + /// + /// TCP Data Transfer Listener. Used in PASV mode. + /// + internal TcpListener DataListener { get; set; } + + /// + /// FTP client data transfer mode. + /// + internal TransferMode Mode { get; set; } + + /// + /// FTP client username. + /// + internal string Username { get; set; } + + /// + /// FTP client password. + /// + internal string Password { get; set; } + + /// + /// Is user connected. + /// + internal bool Connected { get; set; } + + /// + /// Create new instance of the class. + /// + /// TcpClient used for control connection. + internal FtpClient(TcpClient client) + { + Control = client; + Connected = false; + Mode = TransferMode.NONE; + } + + /// + /// Is user connected. + /// + /// Boolean value. + internal bool IsConnected() + { + if (Connected == false) + { + SendReply(530, "Login incorrect."); + return Connected; + } + else + { + return Connected; + } + } + + /// + /// Send text to control socket (usually port 21) + /// + /// Reply code. + /// Reply content. + internal void SendReply(int code, string message) + { + message = message.Replace('\\', '/'); + Control.Send(Encoding.ASCII.GetBytes(code + " " + message + "\r\n")); + } + } +} diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs new file mode 100644 index 0000000000..58d822cf38 --- /dev/null +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs @@ -0,0 +1,593 @@ +/* +* PROJECT: Cosmos Operating System Development +* CONTENT: FTP Command Manager +* PROGRAMMERS: Valentin Charbonnier +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Cosmos.System.FileSystem; +using Cosmos.System.FileSystem.Listing; + +namespace Cosmos.System.Network.IPv4.TCP.FTP +{ + /// + /// FtpCommandManager class. Used to handle incoming FTP commands. + /// + internal class FtpCommandManager + { + /// + /// Cosmos Virtual Filesystem. + /// + internal CosmosVFS FileSystem { get; set; } + + /// + /// Current path. + /// + internal string CurrentDirectory { get; set; } + + /// + /// Create new instance of the class. + /// + /// Cosmos Virtual Filesystem. + /// Base directory used by the FTP server. + internal FtpCommandManager(CosmosVFS fs, string directory) + { + FileSystem = fs; + CurrentDirectory = directory; + } + + /// + /// Process incoming FTP command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessRequest(FtpClient ftpClient, FtpCommand command) + { + switch (command.Command) + { + case "USER": + ProcessUser(ftpClient, command); + break; + case "PASS": + ProcessPass(ftpClient, command); + break; + case "CWD": + ProcessCwd(ftpClient, command); + break; + case "SYST": + ftpClient.SendReply(215, "CosmosOS"); + break; + case "CDUP": + ProcessCdup(ftpClient, command); + break; + case "QUIT": + ProcessQuit(ftpClient, command); + break; + case "DELE": + ProcessDele(ftpClient, command); + break; + case "PWD": + ProcessPwd(ftpClient, command); + break; + case "PASV": + ProcessPasv(ftpClient, command); + break; + case "PORT": + ProcessPort(ftpClient, command); + break; + case "HELP": + ftpClient.SendReply(200, "Help done."); + break; + case "NOOP": + ftpClient.SendReply(200, "Command okay."); + break; + case "RETR": + ProcessRetr(ftpClient, command); + break; + case "STOR": + ProcessStor(ftpClient, command); + break; + case "RMD": + ProcessRmd(ftpClient, command); + break; + case "MKD": + ProcessMkd(ftpClient, command); + break; + case "LIST": + ProcessList(ftpClient, command); + break; + case "TYPE": + ftpClient.SendReply(200, "Command okay."); + break; + default: + ftpClient.SendReply(500, "Unknown command."); + break; + } + } + + /// + /// Process USER command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessUser(FtpClient ftpClient, FtpCommand command) + { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + if (command.Content == "anonymous") + { + ftpClient.Username = command.Content; + ftpClient.Connected = true; + ftpClient.SendReply(230, "User logged in, proceed."); + } + else if (String.IsNullOrEmpty(ftpClient.Username)) + { + ftpClient.Username = command.Content; + ftpClient.SendReply(331, "User name okay, need password."); + } + else + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + + /// + /// Process PASS command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessPass(FtpClient ftpClient, FtpCommand command) + { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + if (ftpClient.Username == "anonymous") + { + ftpClient.SendReply(530, "Login incorrect."); + } + else if (String.IsNullOrEmpty(ftpClient.Username)) + { + ftpClient.SendReply(332, "Need account for login."); + } + else + { + ftpClient.Password = command.Content; + ftpClient.Connected = true; + ftpClient.SendReply(230, "User logged in, proceed."); + } + } + + /// + /// Process CWD command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessCwd(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) + { + CurrentDirectory = CurrentDirectory + "\\" + command.Content; + Directory.SetCurrentDirectory(CurrentDirectory); + ftpClient.SendReply(250, "Requested file action okay."); + } + else if (File.Exists(CurrentDirectory + command.Content)) + { + ftpClient.SendReply(550, "Requested action not taken."); + } + else + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + } + + /// + /// Process PWD command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessPwd(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + ftpClient.SendReply(257, "/" + CurrentDirectory + " created."); + } + } + + /// + /// Process PASV command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessPasv(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + //TODO: Find port dynamically. + int port = 20; + var address = ftpClient.Control.StateMachine.LocalAddress.ToByteArray(); + + ftpClient.SendReply(227, $"Entering Passive Mode ({address[0]},{address[1]},{address[2]},{address[3]},{port / 256},{port % 256})"); + + ftpClient.DataListener = new TcpListener(port); + ftpClient.DataListener.Start(); + + ftpClient.Mode = TransferMode.PASV; + } + } + + /// + /// Process PORT command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessPort(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + var splitted = command.Content.Split(','); + + ftpClient.Address = new Address((byte)int.Parse(splitted[0]), (byte)int.Parse(splitted[1]), (byte)int.Parse(splitted[2]), (byte)int.Parse(splitted[3])); + ftpClient.Port = Int32.Parse(splitted[4]) * 256 + Int32.Parse(splitted[5]); + + ftpClient.SendReply(227, "Entering Active Mode."); + + ftpClient.Data = new TcpClient(ftpClient.Port); + + ftpClient.Mode = TransferMode.ACTV; + } + } + + /// + /// Process LIST command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessList(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + try + { + if (ftpClient.Mode == TransferMode.NONE) + { + ftpClient.SendReply(425, "Can't open data connection."); + } + else if (ftpClient.Mode == TransferMode.ACTV) + { + ftpClient.Data.Connect(ftpClient.Address, ftpClient.Port); + + DoList(ftpClient, command); + } + else if (ftpClient.Mode == TransferMode.PASV) + { + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); + + DoList(ftpClient, command); + } + } + catch + { + ftpClient.SendReply(425, "Can't open data connection."); + } + } + } + + /// + /// Make a file/directory listing and send it to FTP data connection. + /// + /// FTP Client. + /// FTP Command. + private void DoList(FtpClient ftpClient, FtpCommand command) + { + var directory_list = FileSystem.GetDirectoryListing(CurrentDirectory + "\\" + command.Content); + + var sb = new StringBuilder(); + foreach (var directoryEntry in directory_list) + { + if (directoryEntry.mEntryType == DirectoryEntryTypeEnum.Directory) + { + sb.Append("d"); + } + else + { + sb.Append("-"); + } + sb.Append("rwxrwxrwx 1 unknown unknown "); + sb.Append(directoryEntry.mSize); + sb.Append(" Jan 1 09:00 "); + sb.AppendLine(directoryEntry.mName); + } + + ftpClient.Data.Send(Encoding.ASCII.GetBytes(sb.ToString())); + + ftpClient.Data.Close(); + + ftpClient.SendReply(226, "Transfer complete."); + } + + /// + /// Process DELE command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessDele(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (File.Exists(CurrentDirectory + "\\" + command.Command)) + { + File.Delete(CurrentDirectory + "\\" + command.Command); + ftpClient.SendReply(250, "Requested file action okay, completed."); + } + else + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + } + + /// + /// Process RMD command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessRmd(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (Directory.Exists(CurrentDirectory + "\\" + command.Command)) + { + Directory.Delete(CurrentDirectory + "\\" + command.Command, true); + ftpClient.SendReply(200, "Command okay."); + } + else + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + } + + /// + /// Process MKD command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessMkd(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (Directory.Exists(CurrentDirectory + "\\" + command.Command)) + { + ftpClient.SendReply(550, "Requested action not taken."); + } + else + { + Directory.CreateDirectory(CurrentDirectory + "\\" + command.Command); + ftpClient.SendReply(200, "Command okay."); + } + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + } + + /// + /// Process CDUP command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessCdup(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + try + { + CurrentDirectory = new DirectoryInfo(CurrentDirectory).Parent.FullName; + ftpClient.SendReply(250, "Requested file action okay."); + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + } + } + + /// + /// Process STOR command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessStor(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (ftpClient.Mode == TransferMode.NONE) + { + ftpClient.SendReply(425, "Can't open data connection."); + } + else if (ftpClient.Mode == TransferMode.ACTV) + { + ftpClient.Data.Connect(ftpClient.Address, ftpClient.Port); + + DoStor(ftpClient, command); + } + else if (ftpClient.Mode == TransferMode.PASV) + { + Global.mDebugger.Send("Test."); + + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); + + DoStor(ftpClient, command); + } + } + catch + { + ftpClient.SendReply(425, "Can't open data connection."); + } + } + } + + /// + /// Receive file from FTP data connection and write it to filesystem. + /// + /// FTP Client. + /// FTP Command. + private void DoStor(FtpClient ftpClient, FtpCommand command) + { + var ep = new EndPoint(Address.Zero, 0); + var data = ftpClient.Data.Receive(ref ep); + + try + { + File.WriteAllBytes(CurrentDirectory + "\\" + command.Content, data); + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + + ftpClient.Data.Close(); + + ftpClient.SendReply(226, "Transfer complete."); + } + + /// + /// Process RETR command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessRetr(FtpClient ftpClient, FtpCommand command) + { + if (ftpClient.IsConnected()) + { + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (ftpClient.Mode == TransferMode.NONE) + { + ftpClient.SendReply(425, "Can't open data connection."); + } + else if (ftpClient.Mode == TransferMode.ACTV) + { + ftpClient.Data.Connect(ftpClient.Address, ftpClient.Port); + + DoRetr(ftpClient, command); + } + else if (ftpClient.Mode == TransferMode.PASV) + { + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); + + DoRetr(ftpClient, command); + } + } + catch + { + ftpClient.SendReply(425, "Can't open data connection."); + } + } + } + + /// + /// Read file from filesystem and send it to FTP data connection. + /// + private void DoRetr(FtpClient ftpClient, FtpCommand command) + { + try + { + var data = File.ReadAllBytes(CurrentDirectory + "\\" + command.Content); + + ftpClient.Data.Send(data); + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } + + ftpClient.Data.Close(); + + ftpClient.SendReply(226, "Transfer complete."); + } + + /// + /// Process QUIT command. + /// + /// FTP Client. + /// FTP Command. + internal void ProcessQuit(FtpClient ftpClient, FtpCommand command) + { + ftpClient.SendReply(221, "Service closing control connection."); + + ftpClient.Control.Close(); + } + } +} diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index f84cf341d3..0ba3b17886 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -1,98 +1,50 @@ /* * PROJECT: Cosmos Operating System Development -* CONTENT: FTP Client +* CONTENT: FTP Server * PROGRAMMERS: Valentin Charbonnier */ using System; -using System.Collections.Generic; -using System.IO; using System.Text; -using System.Threading; using Cosmos.System.FileSystem; -using Cosmos.System.FileSystem.Listing; -using Console = global::System.Console; namespace Cosmos.System.Network.IPv4.TCP.FTP { - public enum FtpCommandType - { - USER, //Specify user for authentication - PASS, //Specify password for authentication - CWD, //Change working directory - CDUP, //Change working directory to parent directory - QUIT, //Disconnection - DELE, //Delete file on the server - PWD, //Print working directory - PASV, //Enable "passive" mode for data transfer - PORT, //Enable "active" mode for data transfer - HELP, //List available commands - NOOP, //Do nothing - RETR, //Download file from server to client - STOR, //Upload file from client to server - LIST //List files in the current working directory - } - + /// + /// FTP data transfer mode. + /// public enum TransferMode { + /// + /// No mode set. + /// NONE, + + /// + /// Active mode. + /// ACTV, - PASV - } - public class FtpCommand - { - public string Command; - public string Content; + /// + /// Passive Mode. + /// + PASV } - public class FtpClient + /// + /// FTPCommand class. + /// + internal class FtpCommand { - public Address Address; - public int port; - - public TcpClient Control; - public TcpClient Data; - - public TcpListener DataListener; - - public TransferMode Mode; - - public string Username; - public string Password; - - public bool Connected; - - public FtpClient(TcpClient client) - { - Control = client; - Connected = false; - Mode = TransferMode.NONE; - } - - public bool IsConnected() - { - if (Connected == false) - { - SendReply(530, "Login incorrect."); - return Connected; - } - else - { - return Connected; - } - } + /// + /// FTP Command Type. + /// + public string Command { get; set; } /// - /// Send text to control socket (usually port 21) + /// FTP Command Content. /// - /// Reply code. - /// Reply content. - public void SendReply(int code, string message) - { - message = message.Replace('\\', '/'); - Control.Send(Encoding.ASCII.GetBytes(code + " " + message + "\r\n")); - } + public string Content { get; set; } } /// @@ -100,15 +52,20 @@ public void SendReply(int code, string message) /// public class FtpServer : IDisposable { - public TcpListener tcpListener; - - private bool Listening; - - public List ftpClients; + /// + /// Command Manager. + /// + internal FtpCommandManager CommandManager { get; set; } - public string CurrentDirectory { get; set; } + /// + /// TCP Listener used to handle new FTP client connection. + /// + internal TcpListener tcpListener; - CosmosVFS FileSystem { get; set; } + /// + /// Is FTP server listening for new FTP clients. + /// + internal bool Listening; /// /// Create new instance of the class. @@ -117,13 +74,14 @@ public class FtpServer : IDisposable /// Thrown if UdpClient with localPort 53 exists. public FtpServer(CosmosVFS fs, string directory) { - Listening = true; - ftpClients = new List(); + CommandManager = new FtpCommandManager(fs, directory); - CurrentDirectory = directory; - FileSystem = fs; + Listening = true; } + /// + /// Listen for new FTP clients. + /// public void Listen() { while (Listening) @@ -138,7 +96,11 @@ public void Listen() } } - public void ReceiveNewClient(TcpClient client) + /// + /// Handle new FTP client. + /// + /// FTP Client. + private void ReceiveNewClient(TcpClient client) { var ftpClient = new FtpClient(client); @@ -150,7 +112,11 @@ public void ReceiveNewClient(TcpClient client) } } - public void ReceiveRequest(FtpClient ftpClient) + /// + /// Parse and execute FTP command. + /// + /// FTP Client. + internal void ReceiveRequest(FtpClient ftpClient) { var ep = new EndPoint(Address.Zero, 0); var data = Encoding.ASCII.GetString(ftpClient.Control.Receive(ref ep)); @@ -176,541 +142,12 @@ public void ReceiveRequest(FtpClient ftpClient) command.Content = command.Content.Replace('/', '\\'); } - ProcessRequest(ftpClient, command); - } - - public void ProcessRequest(FtpClient ftpClient, FtpCommand command) - { - switch (command.Command) - { - case "USER": - ProcessUser(ftpClient, command); - break; - case "PASS": - ProcessPass(ftpClient, command); - break; - case "CWD": - ProcessCwd(ftpClient, command); - break; - case "SYST": - ftpClient.SendReply(215, "CosmosOS"); - break; - case "CDUP": - ProcessCdup(ftpClient, command); - break; - case "QUIT": - ProcessQuit(ftpClient, command); - break; - case "DELE": - ProcessDele(ftpClient, command); - break; - case "PWD": - ProcessPwd(ftpClient, command); - break; - case "PASV": - ProcessPasv(ftpClient, command); - break; - case "PORT": - ProcessPort(ftpClient, command); - break; - case "HELP": - ftpClient.SendReply(200, "Help done."); - break; - case "NOOP": - ftpClient.SendReply(200, "Command okay."); - break; - case "RETR": - ProcessRetr(ftpClient, command); - break; - case "STOR": - ProcessStor(ftpClient, command); - break; - case "RMD": - ProcessRmd(ftpClient, command); - break; - case "MKD": - ProcessMkd(ftpClient, command); - break; - case "LIST": - ProcessList(ftpClient, command); - break; - case "TYPE": - ftpClient.SendReply(200, "Command okay."); - break; - default: - ftpClient.SendReply(500, "Unknown command."); - break; - } - } - - /// - /// Process USER command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessUser(FtpClient ftpClient, FtpCommand command) - { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } - if (command.Content == "anonymous") - { - ftpClient.Username = command.Content; - ftpClient.Connected = true; - ftpClient.SendReply(230, "User logged in, proceed."); - } - else if (String.IsNullOrEmpty(ftpClient.Username)) { - ftpClient.Username = command.Content; - ftpClient.SendReply(331, "User name okay, need password."); - } - else - { - ftpClient.SendReply(550, "Requested action not taken."); - } - } - - /// - /// Process PASS command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessPass(FtpClient ftpClient, FtpCommand command) - { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } - if (ftpClient.Username == "anonymous") - { - ftpClient.SendReply(530, "Login incorrect."); - } - else if (String.IsNullOrEmpty(ftpClient.Username)) - { - ftpClient.SendReply(332, "Need account for login."); - } - else - { - ftpClient.Password = command.Content; - ftpClient.Connected = true; - ftpClient.SendReply(230, "User logged in, proceed."); - } - } - - /// - /// Process CWD command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessCwd(FtpClient ftpClient, FtpCommand command) - { - if (ftpClient.IsConnected()) - { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } - try - { - if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) - { - CurrentDirectory = CurrentDirectory + "\\" + command.Content; - Directory.SetCurrentDirectory(CurrentDirectory); - ftpClient.SendReply(250, "Requested file action okay."); - } - else if (File.Exists(CurrentDirectory + command.Content)) - { - ftpClient.SendReply(550, "Requested action not taken."); - } - else - { - ftpClient.SendReply(550, "Requested action not taken."); - } - } - catch - { - ftpClient.SendReply(550, "Requested action not taken."); - } - } - } - - /// - /// Process PWD command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessPwd(FtpClient ftpClient, FtpCommand command) - { - if (ftpClient.IsConnected()) - { - ftpClient.SendReply(257, "/" + CurrentDirectory + " created."); - } - } - - /// - /// Process PASV command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessPasv(FtpClient ftpClient, FtpCommand command) - { - if (ftpClient.IsConnected()) - { - //TODO: Find port dynamically. - int port = 20; - var address = ftpClient.Control.StateMachine.LocalAddress.ToByteArray(); - - ftpClient.SendReply(227, $"Entering Passive Mode ({address[0]},{address[1]},{address[2]},{address[3]},{port / 256},{port % 256})"); - - ftpClient.DataListener = new TcpListener(port); - ftpClient.DataListener.Start(); - - ftpClient.Mode = TransferMode.PASV; - } - } - - /// - /// Process PORT command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessPort(FtpClient ftpClient, FtpCommand command) - { - if (ftpClient.IsConnected()) - { - var splitted = command.Content.Split(','); - - ftpClient.Address = new Address((byte)int.Parse(splitted[0]), (byte)int.Parse(splitted[1]), (byte)int.Parse(splitted[2]), (byte)int.Parse(splitted[3])); - ftpClient.port = Int32.Parse(splitted[4]) * 256 + Int32.Parse(splitted[5]); - - ftpClient.SendReply(227, "Entering Active Mode."); - - ftpClient.Data = new TcpClient(ftpClient.port); - - ftpClient.Mode = TransferMode.ACTV; - } - } - - /// - /// Process LIST command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessList(FtpClient ftpClient, FtpCommand command) - { - if (ftpClient.IsConnected()) - { - try - { - if (ftpClient.Mode == TransferMode.NONE) - { - ftpClient.SendReply(425, "Can't open data connection."); - } - else if (ftpClient.Mode == TransferMode.ACTV) - { - ftpClient.Data.Connect(ftpClient.Address, ftpClient.port); - - DoList(ftpClient, command); - } - else if (ftpClient.Mode == TransferMode.PASV) - { - ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); - ftpClient.DataListener.Stop(); - - DoList(ftpClient, command); - } - } - catch - { - ftpClient.SendReply(425, "Can't open data connection."); - } - } - } - - private void DoList(FtpClient ftpClient, FtpCommand command) - { - var directory_list = FileSystem.GetDirectoryListing(CurrentDirectory + "\\" + command.Content); - - var sb = new StringBuilder(); - foreach (var directoryEntry in directory_list) - { - if (directoryEntry.mEntryType == DirectoryEntryTypeEnum.Directory) - { - sb.Append("d"); - } - else - { - sb.Append("-"); - } - sb.Append("rwxrwxrwx 1 unknown unknown "); - sb.Append(directoryEntry.mSize); - sb.Append(" Jan 1 09:00 "); - sb.AppendLine(directoryEntry.mName); - } - - ftpClient.Data.Send(Encoding.ASCII.GetBytes(sb.ToString())); - - ftpClient.Data.Close(); - - ftpClient.SendReply(226, "Transfer complete."); - } - - /// - /// Process DELE command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessDele(FtpClient ftpClient, FtpCommand command) - { - if (ftpClient.IsConnected()) - { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } - try - { - if (File.Exists(CurrentDirectory + "\\" + command.Command)) - { - File.Delete(CurrentDirectory + "\\" + command.Command); - ftpClient.SendReply(250, "Requested file action okay, completed."); - } - else - { - ftpClient.SendReply(550, "Requested action not taken."); - } - } - catch - { - ftpClient.SendReply(550, "Requested action not taken."); - } - } - } - - /// - /// Process RMD command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessRmd(FtpClient ftpClient, FtpCommand command) - { - if (ftpClient.IsConnected()) - { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } - try - { - if (Directory.Exists(CurrentDirectory + "\\" + command.Command)) - { - Directory.Delete(CurrentDirectory + "\\" + command.Command, true); - ftpClient.SendReply(200, "Command okay."); - } - else - { - ftpClient.SendReply(550, "Requested action not taken."); - } - } - catch - { - ftpClient.SendReply(550, "Requested action not taken."); - } - } - } - - /// - /// Process MKD command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessMkd(FtpClient ftpClient, FtpCommand command) - { - if (ftpClient.IsConnected()) - { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } - try - { - if (Directory.Exists(CurrentDirectory + "\\" + command.Command)) - { - ftpClient.SendReply(550, "Requested action not taken."); - } - else - { - Directory.CreateDirectory(CurrentDirectory + "\\" + command.Command); - ftpClient.SendReply(200, "Command okay."); - } - } - catch - { - ftpClient.SendReply(550, "Requested action not taken."); - } - } - } - - /// - /// Process CDUP command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessCdup(FtpClient ftpClient, FtpCommand command) - { - if (ftpClient.IsConnected()) - { - try - { - CurrentDirectory = new DirectoryInfo(CurrentDirectory).Parent.FullName; - ftpClient.SendReply(250, "Requested file action okay."); - } - catch - { - ftpClient.SendReply(550, "Requested action not taken."); - } - } - } - - /// - /// Process STOR command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessStor(FtpClient ftpClient, FtpCommand command) - { - if (ftpClient.IsConnected()) - { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } - try - { - if (ftpClient.Mode == TransferMode.NONE) - { - ftpClient.SendReply(425, "Can't open data connection."); - } - else if (ftpClient.Mode == TransferMode.ACTV) - { - ftpClient.Data.Connect(ftpClient.Address, ftpClient.port); - - DoStor(ftpClient, command); - } - else if (ftpClient.Mode == TransferMode.PASV) - { - Global.mDebugger.Send("Test."); - - ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); - ftpClient.DataListener.Stop(); - - DoStor(ftpClient, command); - } - } - catch - { - ftpClient.SendReply(425, "Can't open data connection."); - } - } - } - - private void DoStor(FtpClient ftpClient, FtpCommand command) - { - var ep = new EndPoint(Address.Zero, 0); - var data = ftpClient.Data.Receive(ref ep); - - try - { - File.WriteAllBytes(CurrentDirectory + "\\" + command.Content, data); - } - catch - { - ftpClient.SendReply(550, "Requested action not taken."); - } - - ftpClient.Data.Close(); - - ftpClient.SendReply(226, "Transfer complete."); - } - - /// - /// Process RETR command. - /// - /// FTP Client. - /// FTP Command. - public void ProcessRetr(FtpClient ftpClient, FtpCommand command) - { - if (ftpClient.IsConnected()) - { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } - try - { - if (ftpClient.Mode == TransferMode.NONE) - { - ftpClient.SendReply(425, "Can't open data connection."); - } - else if (ftpClient.Mode == TransferMode.ACTV) - { - ftpClient.Data.Connect(ftpClient.Address, ftpClient.port); - - DoRetr(ftpClient, command); - } - else if (ftpClient.Mode == TransferMode.PASV) - { - ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); - ftpClient.DataListener.Stop(); - - DoRetr(ftpClient, command); - } - } - catch - { - ftpClient.SendReply(425, "Can't open data connection."); - } - } - } - - public void DoRetr(FtpClient ftpClient, FtpCommand command) - { - try - { - var data = File.ReadAllBytes(CurrentDirectory + "\\" + command.Content); - - ftpClient.Data.Send(data); - } - catch - { - ftpClient.SendReply(550, "Requested action not taken."); - } - - ftpClient.Data.Close(); - - ftpClient.SendReply(226, "Transfer complete."); + CommandManager.ProcessRequest(ftpClient, command); } /// - /// Process QUIT command. + /// Close FTP server. /// - /// FTP Client. - /// FTP Command. - public void ProcessQuit(FtpClient ftpClient, FtpCommand command) - { - ftpClient.SendReply(221, "Service closing control connection."); - - ftpClient.Control.Close(); - } - public void Close() { Listening = false; @@ -718,7 +155,7 @@ public void Close() } /// - /// Close Client + /// Dispose /// public void Dispose() { From 950ad5cbb6ae42f1c97f1a46b09d440a2cdc02b8 Mon Sep 17 00:00:00 2001 From: ShiningLea <49339966+AnErrupTion@users.noreply.github.com> Date: Fri, 4 Jun 2021 16:40:31 +0200 Subject: [PATCH 194/314] Remove useless Close() calls --- Docs/articles/Kernel/Network.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Docs/articles/Kernel/Network.md b/Docs/articles/Kernel/Network.md index 3a1130e0d4..d5eeab58ea 100644 --- a/Docs/articles/Kernel/Network.md +++ b/Docs/articles/Kernel/Network.md @@ -25,8 +25,6 @@ using(var xClient = new DHCPClient()) /** Send a DHCP Discover packet **/ //This will automatically set the IP config after DHCP response xClient.SendDiscoverPacket(); - - xClient.Close(); //don't forget to close! } ``` @@ -44,8 +42,6 @@ using(var xClient = new UdpClient(4242)) 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 - - xClient.Close(); } ``` @@ -83,8 +79,6 @@ using(var xClient = new TcpClient(4242)) 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 - - xClient.Close(); } ``` @@ -100,8 +94,6 @@ using(var xClient = new ICMPClient()) /** Receive ICMP Response **/ int time = xClient.Receive(ref endpoint); //return elapsed time / timeout if no response - - xClient.Close(); } ``` @@ -117,8 +109,6 @@ using(var xClient = new DnsClient()) /** Receive DNS Response **/ Address destination = xClient.Receive(); //can set a timeout value - - xClient.Close(); } ``` ## Utils From 1f7d3f8c93c128f350a68495ebb748d54f187ed2 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 4 Jun 2021 16:41:24 +0200 Subject: [PATCH 195/314] CWD fix + DELE/MKD/RMD fix Add root check --- .../Network/IPv4/TCP/FTP/FtpCommandManager.cs | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs index 58d822cf38..62d4894e7c 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs @@ -181,15 +181,16 @@ internal void ProcessCwd(FtpClient ftpClient, FtpCommand command) } try { - if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) + if (command.Content.Length == 2) //root check { - CurrentDirectory = CurrentDirectory + "\\" + command.Content; - Directory.SetCurrentDirectory(CurrentDirectory); - ftpClient.SendReply(250, "Requested file action okay."); + command.Content += "\\"; } - else if (File.Exists(CurrentDirectory + command.Content)) + + if (Directory.Exists(command.Content)) { - ftpClient.SendReply(550, "Requested action not taken."); + CurrentDirectory = command.Content; + Directory.SetCurrentDirectory(CurrentDirectory); + ftpClient.SendReply(250, "Requested file action okay."); } else { @@ -345,9 +346,9 @@ internal void ProcessDele(FtpClient ftpClient, FtpCommand command) } try { - if (File.Exists(CurrentDirectory + "\\" + command.Command)) + if (File.Exists(CurrentDirectory + "\\" + command.Content)) { - File.Delete(CurrentDirectory + "\\" + command.Command); + File.Delete(CurrentDirectory + "\\" + command.Content); ftpClient.SendReply(250, "Requested file action okay, completed."); } else @@ -378,9 +379,9 @@ internal void ProcessRmd(FtpClient ftpClient, FtpCommand command) } try { - if (Directory.Exists(CurrentDirectory + "\\" + command.Command)) + if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) { - Directory.Delete(CurrentDirectory + "\\" + command.Command, true); + Directory.Delete(CurrentDirectory + "\\" + command.Content, true); ftpClient.SendReply(200, "Command okay."); } else @@ -411,13 +412,13 @@ internal void ProcessMkd(FtpClient ftpClient, FtpCommand command) } try { - if (Directory.Exists(CurrentDirectory + "\\" + command.Command)) + if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) { ftpClient.SendReply(550, "Requested action not taken."); } else { - Directory.CreateDirectory(CurrentDirectory + "\\" + command.Command); + Directory.CreateDirectory(CurrentDirectory + "\\" + command.Content); ftpClient.SendReply(200, "Command okay."); } } From 9873781dea37f8ff822501a632a30cc03f352bf9 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 4 Jun 2021 16:46:47 +0200 Subject: [PATCH 196/314] Clean code --- .../Network/IPv4/TCP/FTP/FtpCommandManager.cs | 441 +++++++++--------- 1 file changed, 208 insertions(+), 233 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs index 62d4894e7c..2129b126da 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs @@ -46,65 +46,73 @@ internal FtpCommandManager(CosmosVFS fs, string directory) /// FTP Command. internal void ProcessRequest(FtpClient ftpClient, FtpCommand command) { - switch (command.Command) - { - case "USER": - ProcessUser(ftpClient, command); - break; - case "PASS": - ProcessPass(ftpClient, command); - break; - case "CWD": - ProcessCwd(ftpClient, command); - break; - case "SYST": - ftpClient.SendReply(215, "CosmosOS"); - break; - case "CDUP": - ProcessCdup(ftpClient, command); - break; - case "QUIT": - ProcessQuit(ftpClient, command); - break; - case "DELE": - ProcessDele(ftpClient, command); - break; - case "PWD": - ProcessPwd(ftpClient, command); - break; - case "PASV": - ProcessPasv(ftpClient, command); - break; - case "PORT": - ProcessPort(ftpClient, command); - break; - case "HELP": - ftpClient.SendReply(200, "Help done."); - break; - case "NOOP": - ftpClient.SendReply(200, "Command okay."); - break; - case "RETR": - ProcessRetr(ftpClient, command); - break; - case "STOR": - ProcessStor(ftpClient, command); - break; - case "RMD": - ProcessRmd(ftpClient, command); - break; - case "MKD": - ProcessMkd(ftpClient, command); - break; - case "LIST": - ProcessList(ftpClient, command); - break; - case "TYPE": - ftpClient.SendReply(200, "Command okay."); - break; - default: - ftpClient.SendReply(500, "Unknown command."); - break; + if (command.Command == "USER") + { + ProcessUser(ftpClient, command); + } + else if (command.Command == "PASS") + { + ProcessPass(ftpClient, command); + } + else + { + if (ftpClient.IsConnected()) + { + switch (command.Command) + { + case "CWD": + ProcessCwd(ftpClient, command); + break; + case "SYST": + ftpClient.SendReply(215, "CosmosOS"); + break; + case "CDUP": + ProcessCdup(ftpClient, command); + break; + case "QUIT": + ProcessQuit(ftpClient, command); + break; + case "DELE": + ProcessDele(ftpClient, command); + break; + case "PWD": + ProcessPwd(ftpClient, command); + break; + case "PASV": + ProcessPasv(ftpClient, command); + break; + case "PORT": + ProcessPort(ftpClient, command); + break; + case "HELP": + ftpClient.SendReply(200, "Help done."); + break; + case "NOOP": + ftpClient.SendReply(200, "Command okay."); + break; + case "RETR": + ProcessRetr(ftpClient, command); + break; + case "STOR": + ProcessStor(ftpClient, command); + break; + case "RMD": + ProcessRmd(ftpClient, command); + break; + case "MKD": + ProcessMkd(ftpClient, command); + break; + case "LIST": + ProcessList(ftpClient, command); + break; + case "TYPE": + ftpClient.SendReply(200, "Command okay."); + break; + default: + ftpClient.SendReply(500, "Unknown command."); + break; + } + } } } @@ -172,36 +180,33 @@ internal void ProcessPass(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessCwd(FtpClient ftpClient, FtpCommand command) { - if (ftpClient.IsConnected()) + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try { - if (String.IsNullOrEmpty(command.Content)) + if (command.Content.Length == 2) //root check { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; + command.Content += "\\"; } - try - { - if (command.Content.Length == 2) //root check - { - command.Content += "\\"; - } - if (Directory.Exists(command.Content)) - { - CurrentDirectory = command.Content; - Directory.SetCurrentDirectory(CurrentDirectory); - ftpClient.SendReply(250, "Requested file action okay."); - } - else - { - ftpClient.SendReply(550, "Requested action not taken."); - } + if (Directory.Exists(command.Content)) + { + CurrentDirectory = command.Content; + Directory.SetCurrentDirectory(CurrentDirectory); + ftpClient.SendReply(250, "Requested file action okay."); } - catch + else { ftpClient.SendReply(550, "Requested action not taken."); } } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } } /// @@ -211,10 +216,7 @@ internal void ProcessCwd(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessPwd(FtpClient ftpClient, FtpCommand command) { - if (ftpClient.IsConnected()) - { - ftpClient.SendReply(257, "/" + CurrentDirectory + " created."); - } + ftpClient.SendReply(257, "/" + CurrentDirectory + " created."); } /// @@ -224,19 +226,16 @@ internal void ProcessPwd(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessPasv(FtpClient ftpClient, FtpCommand command) { - if (ftpClient.IsConnected()) - { - //TODO: Find port dynamically. - int port = 20; - var address = ftpClient.Control.StateMachine.LocalAddress.ToByteArray(); + //TODO: Find port dynamically. + int port = 20; + var address = ftpClient.Control.StateMachine.LocalAddress.ToByteArray(); - ftpClient.SendReply(227, $"Entering Passive Mode ({address[0]},{address[1]},{address[2]},{address[3]},{port / 256},{port % 256})"); + ftpClient.SendReply(227, $"Entering Passive Mode ({address[0]},{address[1]},{address[2]},{address[3]},{port / 256},{port % 256})"); - ftpClient.DataListener = new TcpListener(port); - ftpClient.DataListener.Start(); + ftpClient.DataListener = new TcpListener(port); + ftpClient.DataListener.Start(); - ftpClient.Mode = TransferMode.PASV; - } + ftpClient.Mode = TransferMode.PASV; } /// @@ -246,19 +245,16 @@ internal void ProcessPasv(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessPort(FtpClient ftpClient, FtpCommand command) { - if (ftpClient.IsConnected()) - { - var splitted = command.Content.Split(','); + var splitted = command.Content.Split(','); - ftpClient.Address = new Address((byte)int.Parse(splitted[0]), (byte)int.Parse(splitted[1]), (byte)int.Parse(splitted[2]), (byte)int.Parse(splitted[3])); - ftpClient.Port = Int32.Parse(splitted[4]) * 256 + Int32.Parse(splitted[5]); + ftpClient.Address = new Address((byte)int.Parse(splitted[0]), (byte)int.Parse(splitted[1]), (byte)int.Parse(splitted[2]), (byte)int.Parse(splitted[3])); + ftpClient.Port = Int32.Parse(splitted[4]) * 256 + Int32.Parse(splitted[5]); - ftpClient.SendReply(227, "Entering Active Mode."); + ftpClient.SendReply(227, "Entering Active Mode."); - ftpClient.Data = new TcpClient(ftpClient.Port); + ftpClient.Data = new TcpClient(ftpClient.Port); - ftpClient.Mode = TransferMode.ACTV; - } + ftpClient.Mode = TransferMode.ACTV; } /// @@ -268,33 +264,30 @@ internal void ProcessPort(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessList(FtpClient ftpClient, FtpCommand command) { - if (ftpClient.IsConnected()) + try { - try + if (ftpClient.Mode == TransferMode.NONE) { - if (ftpClient.Mode == TransferMode.NONE) - { - ftpClient.SendReply(425, "Can't open data connection."); - } - else if (ftpClient.Mode == TransferMode.ACTV) - { - ftpClient.Data.Connect(ftpClient.Address, ftpClient.Port); - - DoList(ftpClient, command); - } - else if (ftpClient.Mode == TransferMode.PASV) - { - ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); - ftpClient.DataListener.Stop(); + ftpClient.SendReply(425, "Can't open data connection."); + } + else if (ftpClient.Mode == TransferMode.ACTV) + { + ftpClient.Data.Connect(ftpClient.Address, ftpClient.Port); - DoList(ftpClient, command); - } + DoList(ftpClient, command); } - catch + else if (ftpClient.Mode == TransferMode.PASV) { - ftpClient.SendReply(425, "Can't open data connection."); + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); + + DoList(ftpClient, command); } } + catch + { + ftpClient.SendReply(425, "Can't open data connection."); + } } /// @@ -337,30 +330,27 @@ private void DoList(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessDele(FtpClient ftpClient, FtpCommand command) { - if (ftpClient.IsConnected()) + if (String.IsNullOrEmpty(command.Content)) { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } - try + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (File.Exists(CurrentDirectory + "\\" + command.Content)) { - if (File.Exists(CurrentDirectory + "\\" + command.Content)) - { - File.Delete(CurrentDirectory + "\\" + command.Content); - ftpClient.SendReply(250, "Requested file action okay, completed."); - } - else - { - ftpClient.SendReply(550, "Requested action not taken."); - } + File.Delete(CurrentDirectory + "\\" + command.Content); + ftpClient.SendReply(250, "Requested file action okay, completed."); } - catch + else { ftpClient.SendReply(550, "Requested action not taken."); } } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } } /// @@ -370,30 +360,27 @@ internal void ProcessDele(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessRmd(FtpClient ftpClient, FtpCommand command) { - if (ftpClient.IsConnected()) + if (String.IsNullOrEmpty(command.Content)) { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } - try + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) { - if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) - { - Directory.Delete(CurrentDirectory + "\\" + command.Content, true); - ftpClient.SendReply(200, "Command okay."); - } - else - { - ftpClient.SendReply(550, "Requested action not taken."); - } + Directory.Delete(CurrentDirectory + "\\" + command.Content, true); + ftpClient.SendReply(200, "Command okay."); } - catch + else { ftpClient.SendReply(550, "Requested action not taken."); } } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } } /// @@ -403,30 +390,27 @@ internal void ProcessRmd(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessMkd(FtpClient ftpClient, FtpCommand command) { - if (ftpClient.IsConnected()) + if (String.IsNullOrEmpty(command.Content)) { - if (String.IsNullOrEmpty(command.Content)) - { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; - } - try + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try + { + if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) { - if (Directory.Exists(CurrentDirectory + "\\" + command.Content)) - { - ftpClient.SendReply(550, "Requested action not taken."); - } - else - { - Directory.CreateDirectory(CurrentDirectory + "\\" + command.Content); - ftpClient.SendReply(200, "Command okay."); - } + ftpClient.SendReply(550, "Requested action not taken."); } - catch + else { - ftpClient.SendReply(550, "Requested action not taken."); + Directory.CreateDirectory(CurrentDirectory + "\\" + command.Content); + ftpClient.SendReply(200, "Command okay."); } } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); + } } /// @@ -436,17 +420,14 @@ internal void ProcessMkd(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessCdup(FtpClient ftpClient, FtpCommand command) { - if (ftpClient.IsConnected()) + try { - try - { - CurrentDirectory = new DirectoryInfo(CurrentDirectory).Parent.FullName; - ftpClient.SendReply(250, "Requested file action okay."); - } - catch - { - ftpClient.SendReply(550, "Requested action not taken."); - } + CurrentDirectory = new DirectoryInfo(CurrentDirectory).Parent.FullName; + ftpClient.SendReply(250, "Requested file action okay."); + } + catch + { + ftpClient.SendReply(550, "Requested action not taken."); } } @@ -457,40 +438,37 @@ internal void ProcessCdup(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessStor(FtpClient ftpClient, FtpCommand command) { - if (ftpClient.IsConnected()) + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try { - if (String.IsNullOrEmpty(command.Content)) + if (ftpClient.Mode == TransferMode.NONE) { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; + ftpClient.SendReply(425, "Can't open data connection."); } - try + else if (ftpClient.Mode == TransferMode.ACTV) { - if (ftpClient.Mode == TransferMode.NONE) - { - ftpClient.SendReply(425, "Can't open data connection."); - } - else if (ftpClient.Mode == TransferMode.ACTV) - { - ftpClient.Data.Connect(ftpClient.Address, ftpClient.Port); + ftpClient.Data.Connect(ftpClient.Address, ftpClient.Port); - DoStor(ftpClient, command); - } - else if (ftpClient.Mode == TransferMode.PASV) - { - Global.mDebugger.Send("Test."); - - ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); - ftpClient.DataListener.Stop(); - - DoStor(ftpClient, command); - } + DoStor(ftpClient, command); } - catch + else if (ftpClient.Mode == TransferMode.PASV) { - ftpClient.SendReply(425, "Can't open data connection."); + Global.mDebugger.Send("Test."); + + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); + + DoStor(ftpClient, command); } } + catch + { + ftpClient.SendReply(425, "Can't open data connection."); + } } /// @@ -524,38 +502,35 @@ private void DoStor(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessRetr(FtpClient ftpClient, FtpCommand command) { - if (ftpClient.IsConnected()) + if (String.IsNullOrEmpty(command.Content)) + { + ftpClient.SendReply(501, "Syntax error in parameters or arguments."); + return; + } + try { - if (String.IsNullOrEmpty(command.Content)) + if (ftpClient.Mode == TransferMode.NONE) { - ftpClient.SendReply(501, "Syntax error in parameters or arguments."); - return; + ftpClient.SendReply(425, "Can't open data connection."); } - try + else if (ftpClient.Mode == TransferMode.ACTV) { - if (ftpClient.Mode == TransferMode.NONE) - { - ftpClient.SendReply(425, "Can't open data connection."); - } - else if (ftpClient.Mode == TransferMode.ACTV) - { - ftpClient.Data.Connect(ftpClient.Address, ftpClient.Port); + ftpClient.Data.Connect(ftpClient.Address, ftpClient.Port); - DoRetr(ftpClient, command); - } - else if (ftpClient.Mode == TransferMode.PASV) - { - ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); - ftpClient.DataListener.Stop(); - - DoRetr(ftpClient, command); - } + DoRetr(ftpClient, command); } - catch + else if (ftpClient.Mode == TransferMode.PASV) { - ftpClient.SendReply(425, "Can't open data connection."); + ftpClient.Data = ftpClient.DataListener.AcceptTcpClient(); + ftpClient.DataListener.Stop(); + + DoRetr(ftpClient, command); } } + catch + { + ftpClient.SendReply(425, "Can't open data connection."); + } } /// From acd4dc6052cab3db948bdf6f43842cbe47329b4d Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Fri, 4 Jun 2021 17:07:46 +0200 Subject: [PATCH 197/314] Set only one FTP connection for now + CDUP fix --- .../Network/IPv4/TCP/FTP/FtpCommandManager.cs | 13 +++++++++++-- .../Network/IPv4/TCP/FTP/FtpServer.cs | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs index 2129b126da..31f84c85ee 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs @@ -422,8 +422,17 @@ internal void ProcessCdup(FtpClient ftpClient, FtpCommand command) { try { - CurrentDirectory = new DirectoryInfo(CurrentDirectory).Parent.FullName; - ftpClient.SendReply(250, "Requested file action okay."); + var root = FileSystem.GetDirectory(CurrentDirectory); + + if (CurrentDirectory.Length > 3) + { + CurrentDirectory = root.mParent.mFullPath; + ftpClient.SendReply(250, "Requested file action okay."); + } + else + { + ftpClient.SendReply(550, "Requested action not taken."); + } } catch { diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index 0ba3b17886..725e7e411b 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -93,6 +93,8 @@ public void Listen() global::System.Console.WriteLine("Client[0] : New connection from " + client.StateMachine.LocalAddress.ToString()); ReceiveNewClient(client); + + break; } } From a3acb7dd28affd033ac6f85934cfd6874c6ae609 Mon Sep 17 00:00:00 2001 From: Arawn-Davies Date: Sun, 6 Jun 2021 00:33:01 +0100 Subject: [PATCH 198/314] More XML summaries and documentation for methods, renamed AtaPio to more fitting ATA_PIO to avoid confusion with ATAPI (which I do occasionally :) ) I've tested this change in my own kernel and tests so no issues there. --- source/Cosmos.Core/IOGroup/ATA.cs | 5 ++ source/Cosmos.HAL2/BlockDevice/ATAPI.cs | 88 ++++++++++++++++--- .../BlockDevice/{AtaPio.cs => ATA_PIO.cs} | 71 ++++++++++++++- source/Cosmos.HAL2/BlockDevice/IDE.cs | 8 +- 4 files changed, 154 insertions(+), 18 deletions(-) rename source/Cosmos.HAL2/BlockDevice/{AtaPio.cs => ATA_PIO.cs} (80%) diff --git a/source/Cosmos.Core/IOGroup/ATA.cs b/source/Cosmos.Core/IOGroup/ATA.cs index 51e5e11423..5b5398e584 100644 --- a/source/Cosmos.Core/IOGroup/ATA.cs +++ b/source/Cosmos.Core/IOGroup/ATA.cs @@ -74,6 +74,11 @@ public class ATA : IOGroup /// public readonly IOPortWrite Control; // BAR1 + 2 - write only + /// + /// Constructor for ATA-spec device (including ATAPI?) + /// aSecondary boolean to check if Primary or Secondary channel, used in modern ATA controllers + /// + /// public ATA(bool aSecondary) { if (aSecondary) diff --git a/source/Cosmos.HAL2/BlockDevice/ATAPI.cs b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs index 1caeec5bee..baed7144d7 100644 --- a/source/Cosmos.HAL2/BlockDevice/ATAPI.cs +++ b/source/Cosmos.HAL2/BlockDevice/ATAPI.cs @@ -3,26 +3,53 @@ using System; using System.Collections.Generic; using static Cosmos.HAL.BlockDevice.Ata; -using static Cosmos.HAL.BlockDevice.AtaPio; +using static Cosmos.HAL.BlockDevice.ATA_PIO; namespace Cosmos.HAL.BlockDevice { public class ATAPI : BlockDevice { + /// + /// Static list of all ATAPI devices. This is usually populated upon boot + /// public static List ATAPIDevices = new List(); + + /// + /// CPU IOGroup for all ATA devices, ATAPI uses this group too + /// protected static Core.IOGroup.ATA IO; + + /// + /// Default sector size of all ATAPI drives is 2048 + /// public const ushort SectorSize = 2048; + + /// + /// Is the ATAPI drive on the Primary or Secondary channel of the IDE controller. + /// private bool Primary { get; set; } + + /// + /// Each IDE channel also has a Master or a Slave. This just gets or sets which position it is at. + /// private BusPositionEnum BusPosition { get; set; } - private AtaPio device; + private ATA_PIO device; + + /// + /// Collection of predefined command packets to be sent to the ATAPI device + /// public class PacketCommands { - public static byte[] ReadSector = { (byte)AtaPio.Cmd.Read, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; - public static byte[] Unload = { (byte)AtaPio.Cmd.Eject, 0, 0, 0, 0x02, 0, 0, 0, 0, 0, 0, 0 }; + public static byte[] ReadSector = { (byte)ATA_PIO.Cmd.Read, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; + public static byte[] Unload = { (byte)ATA_PIO.Cmd.Eject, 0, 0, 0, 0x02, 0, 0, 0, 0, 0, 0, 0 }; } - public ATAPI(AtaPio parentDevice) + /// + /// Constructor for ATAPI speclevel device. + /// + /// + public ATAPI(ATA_PIO parentDevice) { device = parentDevice; this.BusPosition = parentDevice.BusPosition; @@ -39,7 +66,10 @@ public ATAPI(AtaPio parentDevice) Init(); } - + /// + /// Check if ATAPI-speclevel device is on Primary or Secondary channel, + /// and register the appropriate interrupt + /// public void Init() { if (Primary) @@ -53,11 +83,22 @@ public void Init() IO.Control.Byte = 0; //Enable IRQs } + + /// + /// Handles the ATAPI IRQ as specified in Init() + /// + /// private void HandleIRQ(ref INTs.IRQContext aContext) { Ata.AtaDebugger.Send("ATAPI IRQ"); } + /// + /// Override method for BlockDevice.ReadBlock, returns the specified buffered sector of ATAPI drive + /// + /// + /// + /// public override void ReadBlock(ulong SectorNum, ulong SectorCount, ref byte[] aData) { if (SectorCount != 1) @@ -69,7 +110,7 @@ public override void ReadBlock(ulong SectorNum, ulong SectorCount, ref byte[] aD byte[] packet = new byte[12]; - packet[0] = (byte)AtaPio.Cmd.Read;//Read Sector + packet[0] = (byte)ATA_PIO.Cmd.Read;//Read Sector packet[1] = 0; packet[2] = (byte)((SectorNum >> 24) & 0xFF);//MSB packet[3] = (byte)((SectorNum >> 16) & 0xFF); @@ -106,11 +147,24 @@ public override void ReadBlock(ulong SectorNum, ulong SectorCount, ref byte[] aD aData = array; } + /// + /// ATAPI writing is not currently supported, that's a future milestone, + /// probably very distant future as we do all development on an existing OS :) + /// + /// + /// + /// public override void WriteBlock(ulong aBlockNo, ulong aBlockCount, ref byte[] aData) { throw new NotImplementedException(); } + /// + /// Sends a SCSI packet to the device + /// + /// + /// + /// private void SendCmd(byte[] AtapiPacket, int size, ref ushort[] outputData) { //Select the ATAPI device @@ -160,12 +214,19 @@ private void SendCmd(byte[] AtapiPacket, int size, ref ushort[] outputData) } } + /// + /// Ejects the ATAPI drive (optical media, iomega Zip etc.) + /// public void Eject() { ushort[] output = new ushort[12]; SendCmd(ATAPI.PacketCommands.Unload, SectorSize, ref output); } + /// + /// Is the ATAPI device still in the middle of an operation? If so, wait! + /// + /// private void Poll(bool checkDRQ = true) { // 400ns until BSR is set @@ -176,14 +237,14 @@ private void Poll(bool checkDRQ = true) // Wait for the ATAPI Device to no longer be busy... if (checkDRQ) { - if ((IO.Status.Byte & (byte)AtaPio.Status.Busy) == 0 && (IO.Status.Byte & (byte)AtaPio.Status.DRQ) != 0) + if ((IO.Status.Byte & (byte)ATA_PIO.Status.Busy) == 0 && (IO.Status.Byte & (byte)ATA_PIO.Status.DRQ) != 0) { break; } } else { - if ((IO.Status.Byte & (byte)AtaPio.Status.Busy) == 0) + if ((IO.Status.Byte & (byte)ATA_PIO.Status.Busy) == 0) { break; } @@ -191,18 +252,21 @@ private void Poll(bool checkDRQ = true) } } + /// + /// Checks the status flag of the ATAPI device. + /// private void CheckForErrors() { - if ((IO.Status.Byte & (byte)AtaPio.Status.Error) != 0) + if ((IO.Status.Byte & (byte)ATA_PIO.Status.Error) != 0) { throw new Exception("ATA Error occured!"); } - if ((IO.Status.Byte & (byte)AtaPio.Status.ATA_SR_DF) != 0) + if ((IO.Status.Byte & (byte)ATA_PIO.Status.ATA_SR_DF) != 0) { throw new Exception("ATA device fault encountered!"); } - if ((IO.Status.Byte & (byte)AtaPio.Status.DRQ) == 0) + if ((IO.Status.Byte & (byte)ATA_PIO.Status.DRQ) == 0) { //throw new Exception("ATAPI DRQ not set"); } diff --git a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs b/source/Cosmos.HAL2/BlockDevice/ATA_PIO.cs similarity index 80% rename from source/Cosmos.HAL2/BlockDevice/AtaPio.cs rename to source/Cosmos.HAL2/BlockDevice/ATA_PIO.cs index 87ee7465cf..83a3ba8aa5 100644 --- a/source/Cosmos.HAL2/BlockDevice/AtaPio.cs +++ b/source/Cosmos.HAL2/BlockDevice/ATA_PIO.cs @@ -15,7 +15,7 @@ namespace Cosmos.HAL.BlockDevice // to do this as capabilities can also be detected, but all ATA devices must support PIO // and thus it can also be used to read the partition table and perform other tasks before // initializing another ATA class in favour of AtaPio - public class AtaPio : Ata + public class ATA_PIO : Ata { #region Properties protected Core.IOGroup.ATA IO; @@ -130,18 +130,33 @@ public enum SpecLevel internal static Debugger mDebugger = new Debugger("HAL", "AtaPio"); + /// + /// Internal Debugger method + /// + /// private static void Debug(string message) { mDebugger.Send("AtaPio debug: " + message); } + /// + /// Internal Debugger method + /// + /// + /// private static void DebugHex(string message, uint number) { Debug(message); mDebugger.SendNumber(number); } - public AtaPio(Core.IOGroup.ATA aIO, Ata.ControllerIdEnum aControllerId, Ata.BusPositionEnum aBusPosition) + /// + /// ATA_PIO mode constructor + /// + /// + /// + /// + public ATA_PIO(Core.IOGroup.ATA aIO, Ata.ControllerIdEnum aControllerId, Ata.BusPositionEnum aBusPosition) { IO = aIO; mControllerID = aControllerId; @@ -160,6 +175,10 @@ public AtaPio(Core.IOGroup.ATA aIO, Ata.ControllerIdEnum aControllerId, Ata.BusP //#define ATA_READ 0x00 //#define ATA_WRITE 0x01 + /// + /// Does this drive even exist? Are there any drives out there in the wild ATA desert? + /// + /// public SpecLevel DiscoverDrive() { SelectDrive(0); @@ -217,17 +236,32 @@ protected void Wait() xVoid = IO.Status.Byte; } + /// + /// Selects the drive + /// + /// public void SelectDrive(byte aLbaHigh4) { IO.DeviceSelect.Byte = (byte)((byte)(DvcSelVal.Default | DvcSelVal.LBA | (mBusPosition == BusPositionEnum.Slave ? DvcSelVal.Slave : 0)) | aLbaHigh4); Wait(); } + /// + /// Returns the status of the sent command, and always throws an exception + /// + /// + /// public Status SendCmd(Cmd aCmd) { return SendCmd(aCmd, true); } + /// + /// Returns the status of a sent command, and throws an exception depending on the status + /// + /// + /// + /// public Status SendCmd(Cmd aCmd, bool aThrowOnError) { IO.Command.Byte = (byte)aCmd; @@ -250,6 +284,13 @@ public Status SendCmd(Cmd aCmd, bool aThrowOnError) return xStatus; } + /// + /// + /// + /// + /// + /// + /// protected string GetString(ushort[] aBuffer, int aIndexStart, int aStringLength) { //Convert ushort[] to byte[] @@ -267,6 +308,10 @@ protected string GetString(ushort[] aBuffer, int aIndexStart, int aStringLength) } public bool LBA48Bit; + + /// + /// Initializes the ATA drive. This includes ATAPI devices too AFAIK + /// protected void InitDrive() { if (mDriveType == SpecLevel.ATA) @@ -314,6 +359,11 @@ protected void InitDrive() } } + /// + /// SelectSector selects the specified starting sector and the following sectors. + /// + /// + /// protected void SelectSector(UInt64 aSectorNo, UInt64 aSectorCount) { CheckBlockNo(aSectorNo, aSectorCount); @@ -343,6 +393,12 @@ protected void SelectSector(UInt64 aSectorNo, UInt64 aSectorCount) //TODO LBA3 ... } + /// + /// Reads the data from a specific starting block using aBlockCount (how many blocks to be read), and fills the specified byte[] with the block. + /// + /// + /// + /// public override void ReadBlock(UInt64 aBlockNo, UInt64 aBlockCount, ref byte[] aData) { CheckDataSize(aData, aBlockCount); @@ -351,6 +407,13 @@ public override void ReadBlock(UInt64 aBlockNo, UInt64 aBlockCount, ref byte[] a IO.Data.Read8(aData); } + /// + /// Writes the specific block of data using the starting block, + /// and the count of how many blocks to be written. + /// + /// + /// + /// public override void WriteBlock(UInt64 aBlockNo, UInt64 aBlockCount, ref byte[] aData) { CheckDataSize(aData, aBlockCount); @@ -371,6 +434,10 @@ public override void WriteBlock(UInt64 aBlockNo, UInt64 aBlockCount, ref byte[] SendCmd(Cmd.CacheFlush); } + /// + /// + /// + /// public override string ToString() { return "AtaPio"; diff --git a/source/Cosmos.HAL2/BlockDevice/IDE.cs b/source/Cosmos.HAL2/BlockDevice/IDE.cs index 08f387f02f..acf1bbeff7 100644 --- a/source/Cosmos.HAL2/BlockDevice/IDE.cs +++ b/source/Cosmos.HAL2/BlockDevice/IDE.cs @@ -26,17 +26,17 @@ internal static void InitDriver() private static void Initialize(Ata.ControllerIdEnum aControllerID, Ata.BusPositionEnum aBusPosition) { var xIO = aControllerID == Ata.ControllerIdEnum.Primary ? Core.Global.BaseIOGroups.ATA1 : Core.Global.BaseIOGroups.ATA2; - var xATA = new AtaPio(xIO, aControllerID, aBusPosition); - if (xATA.DriveType == AtaPio.SpecLevel.Null) + var xATA = new ATA_PIO(xIO, aControllerID, aBusPosition); + if (xATA.DriveType == ATA_PIO.SpecLevel.Null) { return; } - else if (xATA.DriveType == AtaPio.SpecLevel.ATA) + else if (xATA.DriveType == ATA_PIO.SpecLevel.ATA) { BlockDevice.Devices.Add(xATA); Ata.AtaDebugger.Send("ATA device with speclevel ATA found."); } - else if (xATA.DriveType == AtaPio.SpecLevel.ATAPI) + else if (xATA.DriveType == ATA_PIO.SpecLevel.ATAPI) { var atapi = new ATAPI(xATA); BlockDevice.Devices.Add(atapi); From 9b6a2f688d0ce9ecf0459040c9053414727bfff8 Mon Sep 17 00:00:00 2001 From: ShiningLea <49339966+AnErrupTion@users.noreply.github.com> Date: Sun, 6 Jun 2021 14:42:22 +0200 Subject: [PATCH 199/314] [Documentation] Improve VFS article --- Docs/articles/Kernel/VFS.md | 143 +++++++++++++++++++++--------------- 1 file changed, 83 insertions(+), 60 deletions(-) diff --git a/Docs/articles/Kernel/VFS.md b/Docs/articles/Kernel/VFS.md index 09e306a681..b2ff1aadda 100644 --- a/Docs/articles/Kernel/VFS.md +++ b/Docs/articles/Kernel/VFS.md @@ -3,56 +3,73 @@ In this article we will discuss about using Cosmos VFS (virtual file system). Cosmos VFS and the VFS manager classes, let you manage your file system. +**Attention**: **Always** format your drive with Cosmos and **only** Cosmos if you plan to use it with Cosmos. Using any other tool such as Parted, FDisk (or any other tool) might lead to weird things when using that drive with Cosmos' VFS. Those tools are much more advanced and might format and read/write to the disk differently than Cosmos. + First, we should create and initialize an instance of the VFS, this will initialize the partition and files-system lists, as well as register the new VFS. This is essential for using the VFS. -We start with creating global CosmosVFS, this line should appear outside of any function, and before the BeforeRun() function. +We start with creating a global CosmosVFS, this line should appear outside of any function, and before the BeforeRun() function. ```C# -CosmosVFS fs = new Sys.FileSystem.CosmosVFS(); +var fs = new Sys.FileSystem.CosmosVFS(); ``` -Next, we register our VFS at the VFS manager, this will initiate the VFS and make it usable, add this to your kernel's BeforeRun(): +Next, we register our VFS at the VFS manager, this will initiate the VFS and make it usable, add this to your kernel's BeforeRun() function: ```C# Sys.FileSystem.VFS.VFSManager.RegisterVFS(fs); ``` -After the initialization process is done, a message like this would apper on your screen: +After the initialization process is done, a message like this would appear on your screen: ![Initialize](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Initialize.PNG) -This message is printed by the register method and it provides info about the file system. +This message is printed by the RegisterVFS() method and it provides info about the partition. + +After our VFS has been initialized, we can use more interesting functions, let's go over some of them: + +## Format drive + +**Note**: You don't have to format your drive if you're debugging your Cosmos project with VMWare. The build will automatically add an already formatted FAT32 VMDK file for your convenience. + +You can format your drive with the Format() function, just like this: + +```C# +fs.Format("0" /*drive id*/, "FAT32" /*fat type*/, true /*use quick format*/); +``` -After our VFS has been initialized, we can use more interesting functions, lets go over some of them: +**Attention**: **Don't** add anything after the drive id, or formatting won't work. You just need to put the drive id, here we put 0 to format the main drive. ## Get available free space We use this function to get the size of the available free space in our file system, in bytes. ```C# -long available_space = fs.GetAvailableFreeSpace(@"0:\"); +var available_space = fs.GetAvailableFreeSpace(@"0:\"); Console.WriteLine("Available Free Space: " + available_space); ``` ![Free Space](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Free%20Space.PNG) -You have probably noticed the "0:/" argument passed to this function, this is the id of the drive that we want to get available free space of. +You have probably noticed the "0:\" argument passed to this function, this is the id of the drive that we want to get available free space of. Cosmos using DOS drive naming system and this is why we use "0". +**Attention**: Typing "0:/" instead of "0:\" might lead to errors, you've been warned. + ## Get file system type This will let us know what is the file system type that we are using. +You **should** be seeing "FAT32", if you see other types of FAT like "FAT16" or "FAT12", then the virtual disk has probably been formatted with one of those FAT types, but remember, the best supported one is FAT32. ![System Type](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Type.PNG) ```C# -string fs_type = fs.GetFileSystemType(@"0:\"); +var fs_type = fs.GetFileSystemType(@"0:\"); Console.WriteLine("File System Type: " + fs_type); ``` ## Get files list -We start by getting the directory entrys list, using: +We start by getting a list of DirectoryEntry, using: ```C# var directory_list = fs.GetDirectoryListing(@"0:\"); @@ -71,36 +88,38 @@ foreach (var directoryEntry in directory_list) ## Read all the files in a directory -This one is more tricky, -We need to get a directoryEntryList, find files in the list and print the content to the screen. +This one is a bit more tricky. We'll need to use our list of DirectoryEntry, loop through all files and print their raw content to the standard output. -of course, we start with geting the directory listing; +Of course, we'll start with geting the list of DirectoryEntry: ```C# var directory_list = fs.GetDirectoryListing(@"0:\"); ``` -Now we can go through our list, and and print the txt file content. +Now we can go through our list, and print the raw content of each file. ```C# try { foreach (var directoryEntry in directory_list) { - var file_stream = directoryEntry.GetFileStream(); - var entry_type = directoryEntry.mEntryType; - if(entry_type == Sys.FileSystem.Listing.DirectoryEntryTypeEnum.File) + var file_stream = directoryEntry.GetFileStream(); + if (file_stream.CanRead) { - byte[] content = new byte[file_stream.Length]; - file_stream.Read(content, 0, (int)file_stream.Length); - Console.WriteLine("File name: " + directoryEntry.mName); - Console.WriteLine("File size: " + directoryEntry.mSize); - Console.WriteLine("Content: "); - foreach (char ch in content) + var entry_type = directoryEntry.mEntryType; + if(entry_type == Sys.FileSystem.Listing.DirectoryEntryTypeEnum.File) { - Console.Write(ch.ToString()); + var content = new byte[file_stream.Length]; + file_stream.Read(content, 0, content.Length); + Console.WriteLine("File name: " + directoryEntry.mName); + Console.WriteLine("File size: " + directoryEntry.mSize); + Console.WriteLine("Content: "); + foreach (var ch in content) + { + Console.Write(ch.ToString()); + } + Console.WriteLine(); } - Console.WriteLine(); } } } @@ -111,23 +130,14 @@ catch(Exception e) ``` ![Read File](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Read%20File.PNG) -## Read specific file - -Now we will read specific file from a path. -As usual, we do it in a try catch block. +## Create new file +Reading and writing is working on existing files, but it's much more useful to write to our own files. +let's jump right into it: ```C# try { - var hello_file = fs.GetFile(@"0:\hello_from_elia.txt"); - var hello_file_stream = hello_file.GetFileStream(); - - if (hello_file_stream.CanRead) - { - byte[] text_to_read = new byte[hello_file_stream.Length]; - hello_file_stream.Read(text_to_read, 0, (int)hello_file_stream.Length); - Console.WriteLine(Encoding.Default.GetString(text_to_read)); - } + var directory_entry = fs.CreateFile(@"0:\hello_from_elia.txt"); } catch (Exception e) { @@ -135,31 +145,28 @@ catch (Exception e) } ``` -We use the GetFile() method, which returns a file from a path. -Next we open a stream to the file and check if we can read it. -The last thing we do is reading from the stream, we use Read() method, which write the stream to a byte array. +This would create new, empty file (its size is 0 bytes). We can directly write to the created DirectoryEntry like the section below except replacing the **file** variable which uses the GetFile() function by this **directory_entry** which uses the CreateFile() function. -![Read Specific File](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Read%20Specified%20File.PNG) +We can also [check our files list](https://github.com/CosmosOS/Cosmos/wiki/FAT-FileSystem#get-files-list) and see our new file in it. -Notice that there is no much difference between this and [read all the files in a directory](https://github.com/CosmosOS/Cosmos/wiki/FAT-FileSystem#read-all-the-files-in-a-directory). -Actually the difference is by using GetFile() instead of GetDirectoryListing(), as the first returns single DirectoryEntry, and the second returns DirectoryEntryList. +![Create File](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Create%20File.PNG) -## Write to a file +## Write to file -Now we will write to an existing file. -Writing to a file is almost the same as reading from a file. -Always remember, we should use try catch block. +Now we will write to an existing file. +Writing to a file is almost the same as reading from a file. +Always remember that we should put our code in a try catch block. ```C# try { - var hello_file = fs.GetFile(@"0:\hello_from_elia.txt"); - var hello_file_stream = hello_file.GetFileStream(); + var file = fs.GetFile(@"0:\testing.txt"); + var file_stream = file.GetFileStream(); - if (hello_file_stream.CanWrite) + if (file_stream.CanWrite) { - byte[] text_to_write = Encoding.ASCII.GetBytes("Learning how to use VFS!"); - hello_file_stream.Write(text_to_write, 0, text_to_write.Length); + byte[] write_buffer = Encoding.ASCII.GetBytes("Learning how to use VFS!"); + file_stream.Write(write_buffer, 0, write_buffer.Length); } } catch (Exception e) @@ -172,14 +179,26 @@ Again we use the GetFile() method, which returns a file from a path. Next we open a stream to the file and check if we can write to it. The last thing we do is writing to the stream, we use Write() method, which write a byte array to the stream. -## Create new file -Reading and writing is working on existing files, but it's much more useful to write to our own files. -let's jump right into it: +## Read specific file + +Now we will read a specific file from a given path. +As usual, we'll do it in a try catch block. ```C# try { - fs.CreateFile(@"0:\hello_from_elia.txt"); + var file = fs.GetFile(@"0:\testing.txt"); + var file_stream = file.GetFileStream(); + + if (file_stream.CanRead) + { + byte[] file_buffer = new byte[file_stream.Length]; + file_stream.Read(file_buffer, 0, file_buffer.Length); + foreach (var ch in file_buffer) + { + Console.Write(ch.ToString()); + } + } } catch (Exception e) { @@ -187,7 +206,11 @@ catch (Exception e) } ``` -This would create new, empty file (its size is 0 bytes), we can write to it by using [this method](https://github.com/CosmosOS/Cosmos/wiki/FAT-FileSystem/_edit#write-to-a-file). -Now we can [check our files list](https://github.com/CosmosOS/Cosmos/wiki/FAT-FileSystem#get-files-list) and see our new file in it: +We use the GetFile() method, which returns a DirectoryEntry from a path. +Next we open its stream and check if we can read it. +The last thing we do is reading from the stream, we use the Read() method, which writes the stream to a byte array. -![Create File](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Create%20File.PNG) +![Read Specific File](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Read%20Specified%20File.PNG) + +Notice that there is not much difference between this and [read all the files in a directory](https://github.com/CosmosOS/Cosmos/wiki/FAT-FileSystem#read-all-the-files-in-a-directory). +Actually the difference is by using GetFile() instead of GetDirectoryListing(), as the first returns a single DirectoryEntry, and the second returns a list of DirectoryEntry. \ No newline at end of file From 09e2ca4b2e641523318daa7efb70c65d46649f9d Mon Sep 17 00:00:00 2001 From: ShiningLea <49339966+AnErrupTion@users.noreply.github.com> Date: Sun, 6 Jun 2021 14:47:56 +0200 Subject: [PATCH 200/314] Add second note for formatting --- Docs/articles/Kernel/VFS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Docs/articles/Kernel/VFS.md b/Docs/articles/Kernel/VFS.md index b2ff1aadda..273d9d5b81 100644 --- a/Docs/articles/Kernel/VFS.md +++ b/Docs/articles/Kernel/VFS.md @@ -31,6 +31,8 @@ After our VFS has been initialized, we can use more interesting functions, let's **Note**: You don't have to format your drive if you're debugging your Cosmos project with VMWare. The build will automatically add an already formatted FAT32 VMDK file for your convenience. +**Note 2**: You can only format a drive that already has been formatted with FAT32. + You can format your drive with the Format() function, just like this: ```C# From e0b635f8565a1aeb5ef1fd6e873345b166b8562d Mon Sep 17 00:00:00 2001 From: ShiningLea <49339966+AnErrupTion@users.noreply.github.com> Date: Mon, 7 Jun 2021 21:58:33 +0200 Subject: [PATCH 201/314] Use System.IO functions --- Docs/articles/Kernel/VFS.md | 86 ++++++++++--------------------------- 1 file changed, 22 insertions(+), 64 deletions(-) diff --git a/Docs/articles/Kernel/VFS.md b/Docs/articles/Kernel/VFS.md index 273d9d5b81..5951202927 100644 --- a/Docs/articles/Kernel/VFS.md +++ b/Docs/articles/Kernel/VFS.md @@ -11,7 +11,7 @@ This is essential for using the VFS. We start with creating a global CosmosVFS, this line should appear outside of any function, and before the BeforeRun() function. ```C# -var fs = new Sys.FileSystem.CosmosVFS(); +Sys.FileSystem.CosmosVFS fs = new Sys.FileSystem.CosmosVFS(); ``` Next, we register our VFS at the VFS manager, this will initiate the VFS and make it usable, add this to your kernel's BeforeRun() function: @@ -25,7 +25,7 @@ After the initialization process is done, a message like this would appear on yo This message is printed by the RegisterVFS() method and it provides info about the partition. -After our VFS has been initialized, we can use more interesting functions, let's go over some of them: +**Note**: From now on, we'll be using some plugged functions from ``System.IO``, so be sure to use that reference to your code. Alright, now, let's get started over some useful functions: ## Format drive @@ -71,18 +71,18 @@ Console.WriteLine("File System Type: " + fs_type); ## Get files list -We start by getting a list of DirectoryEntry, using: +We start by getting a list of files, using: ```C# -var directory_list = fs.GetDirectoryListing(@"0:\"); +var directory_list = Directory.GetFiles(@"0:\"); ``` Once we have it, we can get the names of our files: ```C# -foreach (var directoryEntry in directory_list) +foreach (var file in directory_list) { - Console.WriteLine(directoryEntry.mName); + Console.WriteLine(file); } ``` @@ -90,12 +90,13 @@ foreach (var directoryEntry in directory_list) ## Read all the files in a directory -This one is a bit more tricky. We'll need to use our list of DirectoryEntry, loop through all files and print their raw content to the standard output. +This one is more tricky, +We need to get a list of files and print all of their content to the screen. -Of course, we'll start with geting the list of DirectoryEntry: +Of course, we'll start with geting that files list: ```C# -var directory_list = fs.GetDirectoryListing(@"0:\"); +var directory_list = Directory.GetFiles(@"0:\"); ``` Now we can go through our list, and print the raw content of each file. @@ -103,26 +104,13 @@ Now we can go through our list, and print the raw content of each file. ```C# try { - foreach (var directoryEntry in directory_list) + foreach (var file in directory_list) { - var file_stream = directoryEntry.GetFileStream(); - if (file_stream.CanRead) - { - var entry_type = directoryEntry.mEntryType; - if(entry_type == Sys.FileSystem.Listing.DirectoryEntryTypeEnum.File) - { - var content = new byte[file_stream.Length]; - file_stream.Read(content, 0, content.Length); - Console.WriteLine("File name: " + directoryEntry.mName); - Console.WriteLine("File size: " + directoryEntry.mSize); - Console.WriteLine("Content: "); - foreach (var ch in content) - { - Console.Write(ch.ToString()); - } - Console.WriteLine(); - } - } + var content = File.ReadAllText(file); + + Console.WriteLine("File name: " + file); + Console.WriteLine("File size: " + content.Length); + Console.WriteLine("Content: " + content); } } catch(Exception e) @@ -130,16 +118,17 @@ catch(Exception e) Console.WriteLine(e.ToString()); } ``` + ![Read File](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Read%20File.PNG) ## Create new file Reading and writing is working on existing files, but it's much more useful to write to our own files. -let's jump right into it: +Let's jump right into it: ```C# try { - var directory_entry = fs.CreateFile(@"0:\hello_from_elia.txt"); + var file_stream = File.Create(@"0:\testing.txt"); } catch (Exception e) { @@ -147,8 +136,6 @@ catch (Exception e) } ``` -This would create new, empty file (its size is 0 bytes). We can directly write to the created DirectoryEntry like the section below except replacing the **file** variable which uses the GetFile() function by this **directory_entry** which uses the CreateFile() function. - We can also [check our files list](https://github.com/CosmosOS/Cosmos/wiki/FAT-FileSystem#get-files-list) and see our new file in it. ![Create File](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Create%20File.PNG) @@ -162,14 +149,7 @@ Always remember that we should put our code in a try catch block. ```C# try { - var file = fs.GetFile(@"0:\testing.txt"); - var file_stream = file.GetFileStream(); - - if (file_stream.CanWrite) - { - byte[] write_buffer = Encoding.ASCII.GetBytes("Learning how to use VFS!"); - file_stream.Write(write_buffer, 0, write_buffer.Length); - } + File.WriteAllText(@"0:\testing.txt", "Learning how to use VFS!"); } catch (Exception e) { @@ -177,10 +157,6 @@ catch (Exception e) } ``` -Again we use the GetFile() method, which returns a file from a path. -Next we open a stream to the file and check if we can write to it. -The last thing we do is writing to the stream, we use Write() method, which write a byte array to the stream. - ## Read specific file Now we will read a specific file from a given path. @@ -189,18 +165,7 @@ As usual, we'll do it in a try catch block. ```C# try { - var file = fs.GetFile(@"0:\testing.txt"); - var file_stream = file.GetFileStream(); - - if (file_stream.CanRead) - { - byte[] file_buffer = new byte[file_stream.Length]; - file_stream.Read(file_buffer, 0, file_buffer.Length); - foreach (var ch in file_buffer) - { - Console.Write(ch.ToString()); - } - } + Console.WriteLine(File.ReadAllText(@"0:\testing.txt")); } catch (Exception e) { @@ -208,11 +173,4 @@ catch (Exception e) } ``` -We use the GetFile() method, which returns a DirectoryEntry from a path. -Next we open its stream and check if we can read it. -The last thing we do is reading from the stream, we use the Read() method, which writes the stream to a byte array. - -![Read Specific File](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Read%20Specified%20File.PNG) - -Notice that there is not much difference between this and [read all the files in a directory](https://github.com/CosmosOS/Cosmos/wiki/FAT-FileSystem#read-all-the-files-in-a-directory). -Actually the difference is by using GetFile() instead of GetDirectoryListing(), as the first returns a single DirectoryEntry, and the second returns a list of DirectoryEntry. \ No newline at end of file +![Read Specific File](https://raw.githubusercontent.com/CosmosOS/Cosmos/master/Docs/articles/Kernel/images/File%20System%20Read%20Specified%20File.PNG) \ No newline at end of file From 8fe8164ceb07123b8828508a93478a9b976dd8be Mon Sep 17 00:00:00 2001 From: Arawn Davies Date: Mon, 7 Jun 2021 23:38:55 +0100 Subject: [PATCH 202/314] Update index.md Pointed newcomers to the appropriate documentation --- Docs/index.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Docs/index.md b/Docs/index.md index 81343a8b66..fb07b55f7a 100644 --- a/Docs/index.md +++ b/Docs/index.md @@ -1,9 +1,12 @@ -# Cosmos Documentation - -
- -Some docs are outdated, and we are currently working on updating them and adding new ones. - -
- -*Looking for the [Cosmos website](https://gocosmos.org)?* +# Welcome to the Official Cosmos Documentation + +If you're knew to Cosmos, welcome! Before you get stuck in the API documentation, we highly recommend you visit the website linked at the bottom. + +The Articles section of this website includes some articles which have been written many years ago for websites such as www.codeproject.com and are kept for archival purposes. These discuss elements such as the Cosmos Virtual FIle System. We prefer newcomers who want to develop their own operating systems to read the API documentation while we update these articles to comply with the current Cosmos project. + +For projects using the VFS directly, we recommend you use System.IO methods where possible. This is because these were written before much progress was made making .NET assemblies usable + + +For the up-to-date API documentation generated from the master branch, please visit the [Cosmos API Documentation](https://cosmosos.github.io/api/Cosmos.Build.Tasks.html) + +If you're looking for general information about Cosmos e.g. our goals and various links to chat with us or for help with using Cosmos that can't be answered with existing documentation, please visit the [Cosmos website](https://gocosmos.org) From d09bc443037def7cd6a10c7144f13a4b1ed8a089 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 8 Jun 2021 11:41:34 +0200 Subject: [PATCH 203/314] Add code documentation + Transmission Control Block --- .../Network/IPv4/TCP/TCPClient.cs | 39 ++-- .../Network/IPv4/TCP/TCPPacket.cs | 37 ++-- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 208 ++++++++++++++---- 3 files changed, 217 insertions(+), 67 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 893929d545..058e2c5e73 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -80,21 +80,30 @@ public void Connect(Address dest, int destPort, int timeout = 5000) } StateMachine.RemoteAddress = dest; - StateMachine.RemotePort = (ushort)destPort; - StateMachine.LocalAddress = IPConfig.FindNetwork(dest); + StateMachine.RemotePort = (ushort)destPort; //Generate Random Sequence Number var rnd = new Random(); - StateMachine.SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); + var SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); + + //Fill TCB + StateMachine.TCB.SndUna = SequenceNumber; + StateMachine.TCB.SndNxt = SequenceNumber; + StateMachine.TCB.SndWnd = Tcp.TcpWindowSize; + StateMachine.TCB.SndUp = 0; + StateMachine.TCB.SndWl1 = 0; + StateMachine.TCB.SndWl2 = 0; + StateMachine.TCB.ISS = SequenceNumber; + + StateMachine.TCB.RcvNxt = 0; + StateMachine.TCB.RcvWnd = Tcp.TcpWindowSize; + StateMachine.TCB.RcvUp = 0; + StateMachine.TCB.IRS = 0; Tcp.Connections.Add(StateMachine); - // Flags=0x02 -> Syn - var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, (ushort)StateMachine.LocalPort, (ushort)destPort, StateMachine.SequenceNumber, 0, 20, (byte)Flags.SYN, 0xFAF0, 0); - - OutgoingBuffer.AddPacket(packet); - NetworkStack.Update(); + StateMachine.SendEmptyPacket(Flags.SYN); StateMachine.Status = Status.SYN_SENT; @@ -113,11 +122,9 @@ public void Close() { if (StateMachine.Status == Status.ESTABLISHED) { - var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, (ushort)StateMachine.LocalPort, (ushort)StateMachine.RemotePort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, (byte)(Flags.FIN | Flags.ACK), 0xFAF0, 0); - OutgoingBuffer.AddPacket(packet); - NetworkStack.Update(); + StateMachine.SendEmptyPacket(Flags.FIN | Flags.ACK); - StateMachine.SequenceNumber++; + StateMachine.TCB.SndNxt++; StateMachine.Status = Status.FIN_WAIT1; @@ -162,20 +169,20 @@ public void Send(byte[] data) for (int i = 0; i < chunks.Length; i++) { - var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, (ushort)StateMachine.LocalPort, (ushort)StateMachine.RemotePort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, i == chunks.Length - 2 ? (byte)(Flags.PSH | Flags.ACK) : (byte)(Flags.ACK), 0xFAF0, 0, chunks[i]); + var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, StateMachine.LocalPort, StateMachine.RemotePort, StateMachine.TCB.SndNxt, StateMachine.TCB.RcvNxt, 20, i == chunks.Length - 2 ? (byte)(Flags.PSH | Flags.ACK) : (byte)(Flags.ACK), Tcp.TcpWindowSize, 0, chunks[i]); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - StateMachine.SequenceNumber += (uint)chunks[i].Length; + StateMachine.TCB.SndNxt += (uint)chunks[i].Length; } } else { - var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, (ushort)StateMachine.LocalPort, (ushort)StateMachine.RemotePort, StateMachine.SequenceNumber, StateMachine.AckNumber, 20, (byte)(Flags.PSH | Flags.ACK), 0xFAF0, 0, data); + var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, StateMachine.LocalPort, StateMachine.RemotePort, StateMachine.TCB.SndNxt, StateMachine.TCB.RcvNxt, 20, (byte)(Flags.PSH | Flags.ACK), Tcp.TcpWindowSize, 0, data); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); - StateMachine.SequenceNumber += (uint)data.Length; + StateMachine.TCB.SndNxt += (uint)data.Length; } StateMachine.WaitingAck = true; } diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs index d57f12c992..2cfeb5f890 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPPacket.cs @@ -17,11 +17,34 @@ namespace Cosmos.System.Network.IPv4.TCP ///
public enum Flags : byte { + /// + /// No more data from sender. + /// FIN = (1 << 0), + + /// + /// Synchronize sequence numbers. + /// SYN = (1 << 1), + + /// + /// Reset the connection. + /// RST = (1 << 2), + + /// + /// Push Function. + /// PSH = (1 << 3), + + /// + /// Acknowledgment field significant. + /// ACK = (1 << 4), + + /// + /// Urgent Pointer field significant. + /// URG = (1 << 5) } @@ -413,20 +436,6 @@ internal byte[] TCP_Data } } - /// - /// Convert a byte to a hexadecimal char. - /// - /// - /// Hex string. - static string ToHex(byte b) - { - string r = ""; - string chars = "0123456789ABCDEF"; - - r += chars[b >> 4]; - return r += chars[b &= 0x0F]; - } - /// /// Get string representation of TCP flags. /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index f10df708e0..4bfe17722e 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -12,19 +12,127 @@ namespace Cosmos.System.Network.IPv4.TCP ///
public enum Status { + /// + /// Wait for a connection request from any remote TCP and port. + /// LISTEN, + + /// + /// Wait for a matching connection request after having sent a connection request. + /// SYN_SENT, + + /// + /// Wait for a confirming connection request acknowledgment after having both received and sent a connection request. + /// SYN_RECEIVED, + + /// + /// Represents an open connection, data received can be delivered to the user. The normal state for the data transfer phase of the connection. + /// ESTABLISHED, + + /// + /// Wait for a connection termination request from the remote TCP, or an acknowledgment of the connection termination request previously sent. + /// FIN_WAIT1, + + /// + /// Wait for a connection termination request from the remote TCP. + /// FIN_WAIT2, + + /// + /// Wait for a connection termination request from the local user. + /// CLOSE_WAIT, + + /// + /// Wait for a connection termination request acknowledgment from the remote TCP. + /// CLOSING, + + /// + /// Wait for an acknowledgment of the connection termination request previously sent to the remote TCP (which includes an acknowledgment of its connection termination request). + /// LAST_ACK, + + /// + /// Wait for enough time to pass to be sure the remote TCP received the acknowledgment of its connection termination request. + /// TIME_WAIT, + + /// + /// represents no connection state at all. + /// CLOSED } + /// + /// Transmission Control Block (TCB). + /// + public class TransmissionControlBlock + { + /** Send Sequence Variables **/ + + /// + /// Send unacknowledged. + /// + public uint SndUna { get; set; } + + /// + /// Send next. + /// + public uint SndNxt { get; set; } + + /// + /// Send window. + /// + public uint SndWnd { get; set; } + + /// + /// Send urgent pointer. + /// + public uint SndUp { get; set; } + + /// + /// Segment sequence number used for last window update. + /// + public uint SndWl1 { get; set; } + + /// + /// Segment acknowledgment number used for last window update. + /// + public uint SndWl2 { get; set; } + + /// + /// Initial send sequence number + /// + public uint ISS { get; set; } + + /** Receive Sequence Variables **/ + + /// + /// Receive next. + /// + public uint RcvNxt { get; set; } + + /// + /// Receive window. + /// + public uint RcvWnd { get; set; } + + /// + /// Receive urgent pointer. + /// + public uint RcvUp { get; set; } + + /// + /// Initial receive sequence number. + /// + public uint IRS { get; set; } + } + /// /// Tcp class. Used to manage the TCP state machine. /// Handle received packets according to current TCP connection Status. Also contains TCB (Transmission Control Block) information. @@ -32,6 +140,13 @@ public enum Status /// internal class Tcp { + /// + /// TCP Window Size. + /// + public const ushort TcpWindowSize = 8192; + + #region Static + /// /// Connection list. /// @@ -88,6 +203,8 @@ internal static Tcp GetConnection(ushort localPort, ushort remotePort, Address l return null; } + #endregion + /// /// Local port. /// @@ -119,29 +236,24 @@ internal static Tcp GetConnection(ushort localPort, ushort remotePort, Address l internal Status Status; /// - /// Connection Acknowledgement number. + /// Connection Transmission Control Block. /// - internal uint AckNumber; + internal TransmissionControlBlock TCB { get; set; } /// - /// Connection Sequence number. + /// Is waiting for an acknowledgement packet. /// - internal uint SequenceNumber; + internal bool WaitingAck; /// /// Last recveived Connection Sequence number. /// internal uint LastSequenceNumber; - /// - /// Is waiting for an acknowledgement packet. - /// - internal bool WaitingAck; - /// /// TCP Received Data. /// - internal byte[] Data; + internal byte[] Data { get; set; } public Tcp(ushort localPort, ushort remotePort, Address localIp, Address remoteIp) { @@ -150,6 +262,8 @@ public Tcp(ushort localPort, ushort remotePort, Address localIp, Address remoteI LocalAddress = localIp; RemoteAddress = remoteIp; + TCB = new TransmissionControlBlock(); + WaitingAck = false; } @@ -223,8 +337,8 @@ public void ProcessListen(TCPPacket packet) } else if (packet.ACK) { - AckNumber = packet.SequenceNumber; - SequenceNumber = packet.AckNumber; + TCB.RcvNxt = packet.SequenceNumber; + TCB.SndNxt = packet.AckNumber; Status = Status.ESTABLISHED; } @@ -234,10 +348,10 @@ public void ProcessListen(TCPPacket packet) LocalAddress = IPConfig.FindNetwork(packet.SourceIP); - AckNumber = packet.SequenceNumber + 1; + TCB.RcvNxt = packet.SequenceNumber + 1; var rnd = new Random(); - SequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); + TCB.SndNxt = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); RemoteAddress = packet.SourceIP; RemotePort = packet.SourcePort; @@ -260,7 +374,7 @@ public void ProcessSynReceived(TCPPacket packet) { LastSequenceNumber = packet.SequenceNumber - 1; //TODO: Fix this trick (for dup check when PSH ACK) - SequenceNumber++; + TCB.SndNxt++; Status = Status.ESTABLISHED; } @@ -272,18 +386,27 @@ public void ProcessSynReceived(TCPPacket packet) /// Packet to receive. public void ProcessSynSent(TCPPacket packet) { - if (packet.FIN) + if (packet.TCPFlags == (byte)Flags.ACK) { - Status = Status.CLOSED; + if ((packet.AckNumber - TCB.ISS) < 0 || (packet.AckNumber - TCB.SndNxt) > 0) + { + SendEmptyPacket(Flags.RST, packet.AckNumber); - throw new Exception("TCP connection closed! (FIN received on SYN_SENT state)"); + Global.mDebugger.Send("Bad ACK received at SYN_SENT."); + } + else + { + TCB.RcvNxt = packet.SequenceNumber; + TCB.SndNxt = packet.AckNumber; + + Status = Status.ESTABLISHED; + } } - else if (packet.TCPFlags == (byte)Flags.ACK) + else if (packet.FIN) { - AckNumber = packet.SequenceNumber; - SequenceNumber = packet.AckNumber; + Status = Status.CLOSED; - Status = Status.ESTABLISHED; + throw new Exception("TCP connection closed! (FIN received on SYN_SENT state)"); } else if (packet.RST) { @@ -295,8 +418,8 @@ public void ProcessSynSent(TCPPacket packet) { if (packet.ACK) { - AckNumber = packet.SequenceNumber + 1; - SequenceNumber++; + TCB.RcvNxt = packet.SequenceNumber + 1; + TCB.SndNxt++; LastSequenceNumber = packet.SequenceNumber; @@ -331,7 +454,7 @@ public void ProcessEstablished(TCPPacket packet) { if (packet.SequenceNumber > LastSequenceNumber) //dup check { - AckNumber += packet.TCP_DataLength; + TCB.RcvNxt += packet.TCP_DataLength; LastSequenceNumber = packet.SequenceNumber; @@ -345,16 +468,16 @@ public void ProcessEstablished(TCPPacket packet) if (WaitingAck) { - if (packet.AckNumber == SequenceNumber) + if (packet.AckNumber == TCB.SndNxt) { WaitingAck = false; } } else if (!packet.PSH) { - if (packet.SequenceNumber >= AckNumber && packet.TCP_DataLength > 0) //packet sequencing + if (packet.SequenceNumber >= TCB.RcvNxt && packet.TCP_DataLength > 0) //packet sequencing { - AckNumber += packet.TCP_DataLength; + TCB.RcvNxt += packet.TCP_DataLength; Data = ArrayHelper.Concat(Data, packet.TCP_Data); } @@ -369,7 +492,7 @@ public void ProcessEstablished(TCPPacket packet) } else if (packet.FIN && packet.ACK) { - AckNumber++; + TCB.RcvNxt++; SendEmptyPacket(Flags.ACK); @@ -377,7 +500,7 @@ public void ProcessEstablished(TCPPacket packet) } else if (packet.FIN) { - AckNumber++; + TCB.RcvNxt++; SendEmptyPacket(Flags.ACK); @@ -399,7 +522,7 @@ public void ProcessFinWait1(TCPPacket packet) { if (packet.FIN && packet.ACK) { - AckNumber++; + TCB.RcvNxt++; SendEmptyPacket(Flags.ACK); @@ -407,7 +530,7 @@ public void ProcessFinWait1(TCPPacket packet) } else if (packet.FIN) { - AckNumber++; + TCB.RcvNxt++; SendEmptyPacket(Flags.ACK); @@ -427,7 +550,7 @@ public void ProcessFinWait2(TCPPacket packet) { if (packet.FIN) { - AckNumber++; + TCB.RcvNxt++; SendEmptyPacket(Flags.ACK); @@ -509,18 +632,29 @@ internal bool WaitStatus(Status status) } /// - /// Send acknowledgement packet + /// Send empty packet. + /// + internal void SendEmptyPacket(Flags flag) + { + var packet = new TCPPacket(LocalAddress, RemoteAddress, LocalPort, RemotePort, TCB.SndNxt, TCB.RcvNxt, 20, (byte)flag, TcpWindowSize, 0); + + OutgoingBuffer.AddPacket(packet); + NetworkStack.Update(); + } + + /// + /// Send empty packet. /// - private void SendEmptyPacket(Flags flag) + internal void SendEmptyPacket(Flags flag, uint sequenceNumber) { - var packet = new TCPPacket(LocalAddress, RemoteAddress, (ushort)LocalPort, (ushort)RemotePort, SequenceNumber, AckNumber, 20, (byte)flag, 0xFAF0, 0); + var packet = new TCPPacket(LocalAddress, RemoteAddress, LocalPort, RemotePort, sequenceNumber, TCB.RcvNxt, 20, (byte)flag, TcpWindowSize, 0); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); } /// - /// Equals connection + /// Equals connection. /// internal bool Equals(ushort localPort, ushort remotePort, Address localIp, Address remoteIp) { From b8bac558c1ea2d89a76957740abd3669ec5f25f9 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 8 Jun 2021 12:49:36 +0200 Subject: [PATCH 204/314] Add TCB checks to SYN_SENT + SYN_RECEIVED --- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 80 ++++++++++++------- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index 4bfe17722e..ab046b6abc 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -205,6 +205,8 @@ internal static Tcp GetConnection(ushort localPort, ushort remotePort, Address l #endregion + #region TCB + /// /// Local port. /// @@ -225,21 +227,13 @@ internal static Tcp GetConnection(ushort localPort, ushort remotePort, Address l ///
internal Address RemoteAddress; - /// - /// RX buffer queue. - /// - internal Queue rxBuffer; - - /// - /// Connection status. - /// - internal Status Status; - /// /// Connection Transmission Control Block. /// internal TransmissionControlBlock TCB { get; set; } + #endregion + /// /// Is waiting for an acknowledgement packet. /// @@ -250,6 +244,16 @@ internal static Tcp GetConnection(ushort localPort, ushort remotePort, Address l ///
internal uint LastSequenceNumber; + /// + /// RX buffer queue. + /// + internal Queue rxBuffer; + + /// + /// Connection status. + /// + internal Status Status; + /// /// TCP Received Data. /// @@ -366,17 +370,18 @@ public void ProcessListen(TCPPacket packet) /// Packet to receive. public void ProcessSynReceived(TCPPacket packet) { - if (packet.RST) - { - Status = Status.LISTEN; - } - else if (packet.ACK) + if (packet.ACK) { - LastSequenceNumber = packet.SequenceNumber - 1; //TODO: Fix this trick (for dup check when PSH ACK) + if (TCB.SndUna <= packet.AckNumber && packet.AckNumber <= TCB.SndNxt) + { + TCB.SndWnd = packet.WindowSize; + TCB.SndWl1 = packet.SequenceNumber; + TCB.SndWl2 = packet.SequenceNumber; - TCB.SndNxt++; + LastSequenceNumber = packet.SequenceNumber - 1; //TODO: Fix this trick (for dup check when PSH ACK) - Status = Status.ESTABLISHED; + Status = Status.ESTABLISHED; + } } } @@ -406,20 +411,25 @@ public void ProcessSynSent(TCPPacket packet) { Status = Status.CLOSED; - throw new Exception("TCP connection closed! (FIN received on SYN_SENT state)"); + Global.mDebugger.Send("TCP connection closed! (FIN received on SYN_SENT state)."); } else if (packet.RST) { Status = Status.CLOSED; - throw new Exception("Connection refused by remote computer."); + Global.mDebugger.Send("Connection refused by remote computer."); } else if (packet.SYN) { + TCB.IRS = packet.SequenceNumber; + TCB.RcvNxt = packet.SequenceNumber + 1; + if (packet.ACK) { - TCB.RcvNxt = packet.SequenceNumber + 1; - TCB.SndNxt++; + TCB.SndUna = packet.AckNumber; + TCB.SndWnd = packet.WindowSize; + TCB.SndWl1 = packet.SequenceNumber; + TCB.SndWl2 = packet.SequenceNumber; LastSequenceNumber = packet.SequenceNumber; @@ -431,13 +441,13 @@ public void ProcessSynSent(TCPPacket packet) { Status = Status.CLOSED; - throw new NotImplementedException("Simultaneous open not supported."); + Global.mDebugger.Send("Simultaneous open not supported."); } else { Status = Status.CLOSED; - throw new Exception("TCP connection closed! (Flag " + packet.TCPFlags + " received on SYN_SENT state)"); + Global.mDebugger.Send("TCP connection closed! (" + packet.getFlags() + " received on SYN_SENT state)"); } } } @@ -454,10 +464,10 @@ public void ProcessEstablished(TCPPacket packet) { if (packet.SequenceNumber > LastSequenceNumber) //dup check { - TCB.RcvNxt += packet.TCP_DataLength; - LastSequenceNumber = packet.SequenceNumber; + TCB.RcvNxt += packet.TCP_DataLength; + Data = ArrayHelper.Concat(Data, packet.TCP_Data); rxBuffer.Enqueue(packet); @@ -636,10 +646,7 @@ internal bool WaitStatus(Status status) ///
internal void SendEmptyPacket(Flags flag) { - var packet = new TCPPacket(LocalAddress, RemoteAddress, LocalPort, RemotePort, TCB.SndNxt, TCB.RcvNxt, 20, (byte)flag, TcpWindowSize, 0); - - OutgoingBuffer.AddPacket(packet); - NetworkStack.Update(); + SendPacket(new TCPPacket(LocalAddress, RemoteAddress, LocalPort, RemotePort, TCB.SndNxt, TCB.RcvNxt, 20, (byte)flag, TcpWindowSize, 0)); } /// @@ -647,10 +654,21 @@ internal void SendEmptyPacket(Flags flag) /// internal void SendEmptyPacket(Flags flag, uint sequenceNumber) { - var packet = new TCPPacket(LocalAddress, RemoteAddress, LocalPort, RemotePort, sequenceNumber, TCB.RcvNxt, 20, (byte)flag, TcpWindowSize, 0); + SendPacket(new TCPPacket(LocalAddress, RemoteAddress, LocalPort, RemotePort, sequenceNumber, TCB.RcvNxt, 20, (byte)flag, TcpWindowSize, 0)); + } + /// + /// Send TCP packet. + /// + private void SendPacket(TCPPacket packet) + { OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); + + if (packet.SYN || packet.FIN) + { + TCB.SndNxt++; + } } /// From dc78a489de9f3d83adafd4c96206e2aaf3fe0692 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 8 Jun 2021 15:32:18 +0200 Subject: [PATCH 205/314] Add more TCP checks --- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 121 +++++++++++------- 1 file changed, 78 insertions(+), 43 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index ab046b6abc..485eec3bd5 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -281,41 +281,61 @@ internal void ReceiveData(TCPPacket packet) { Global.mDebugger.Send("[" + table[(int)Status] + "] " + packet.ToString()); - switch (Status) + if (Status == Status.CLOSED) { - case Status.LISTEN: - ProcessListen(packet); - break; - case Status.SYN_SENT: - ProcessSynSent(packet); - break; - case Status.SYN_RECEIVED: - ProcessSynReceived(packet); - break; - case Status.ESTABLISHED: - ProcessEstablished(packet); - break; - case Status.FIN_WAIT1: - ProcessFinWait1(packet); - break; - case Status.FIN_WAIT2: - ProcessFinWait2(packet); - break; - case Status.CLOSE_WAIT: - ProcessCloseWait(packet); - break; - case Status.CLOSING: - ProcessClosing(packet); - break; - case Status.LAST_ACK: - ProcessCloseWait(packet); - break; - case Status.TIME_WAIT: - break; - case Status.CLOSED: - break; - default: - throw new Exception("Unknown TCP connection state."); + //DO NOTHING + } + else if (Status == Status.LISTEN) + { + ProcessListen(packet); + } + else if (Status == Status.SYN_SENT) + { + ProcessSynSent(packet); + } + else + { + // Check sequence number and segment data. + if (TCB.RcvNxt <= packet.SequenceNumber && packet.SequenceNumber + packet.TCP_DataLength < TCB.RcvNxt + TCB.RcvWnd) + { + switch (Status) + { + case Status.SYN_RECEIVED: + ProcessSynReceived(packet); + break; + case Status.ESTABLISHED: + ProcessEstablished(packet); + break; + case Status.FIN_WAIT1: + ProcessFinWait1(packet); + break; + case Status.FIN_WAIT2: + ProcessFinWait2(packet); + break; + case Status.CLOSE_WAIT: + ProcessCloseWait(packet); + break; + case Status.CLOSING: + ProcessClosing(packet); + break; + case Status.LAST_ACK: + ProcessCloseWait(packet); + break; + case Status.TIME_WAIT: + break; + default: + throw new Exception("Unknown TCP connection state."); + } + } + else + { + if (!packet.RST) + { + SendEmptyPacket(Flags.ACK); + } + + Global.mDebugger.Send("Sequence number or segment data invalid, packet passed."); + } } } @@ -329,9 +349,9 @@ public void ProcessListen(TCPPacket packet) { if (packet.RST) { - Status = Status.CLOSED; + Global.mDebugger.Send("RST received at LISTEN state, packet passed."); - throw new Exception("TCP connection resetted! (RST received on LISTEN state)"); + return; } else if (packet.FIN) { @@ -348,19 +368,30 @@ public void ProcessListen(TCPPacket packet) } else if (packet.SYN) { - Status = Status.SYN_RECEIVED; - LocalAddress = IPConfig.FindNetwork(packet.SourceIP); - - TCB.RcvNxt = packet.SequenceNumber + 1; + RemoteAddress = packet.SourceIP; + RemotePort = packet.SourcePort; var rnd = new Random(); - TCB.SndNxt = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); + var sequenceNumber = (uint)((rnd.Next(0, Int32.MaxValue)) << 32) | (uint)(rnd.Next(0, Int32.MaxValue)); - RemoteAddress = packet.SourceIP; - RemotePort = packet.SourcePort; + //Fill TCB + TCB.SndUna = sequenceNumber; + TCB.SndNxt = sequenceNumber; + TCB.SndWnd = Tcp.TcpWindowSize; + TCB.SndUp = 0; + TCB.SndWl1 = packet.SequenceNumber - 1; + TCB.SndWl2 = 0; + TCB.ISS = sequenceNumber; + + TCB.RcvNxt = packet.SequenceNumber + 1; + TCB.RcvWnd = Tcp.TcpWindowSize; + TCB.RcvUp = 0; + TCB.IRS = packet.SequenceNumber; SendEmptyPacket(Flags.SYN | Flags.ACK); + + Status = Status.SYN_RECEIVED; } } @@ -382,6 +413,10 @@ public void ProcessSynReceived(TCPPacket packet) Status = Status.ESTABLISHED; } + else + { + SendEmptyPacket(Flags.RST, packet.AckNumber); + } } } From bf877501a22c066425d7db4566d4689965adb5bc Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 8 Jun 2021 15:44:53 +0200 Subject: [PATCH 206/314] Remove useless packet duplication check --- .../Network/IPv4/TCP/TCPClient.cs | 1 - source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 22 ++++--------------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 058e2c5e73..18ea6b0d76 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -49,7 +49,6 @@ public TcpClient(int localPort) StateMachine.rxBuffer = new Queue(8); StateMachine.Status = Status.CLOSED; - StateMachine.LastSequenceNumber = 0; } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index 485eec3bd5..b10c5d3a68 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -239,11 +239,6 @@ internal static Tcp GetConnection(ushort localPort, ushort remotePort, Address l /// internal bool WaitingAck; - /// - /// Last recveived Connection Sequence number. - /// - internal uint LastSequenceNumber; - /// /// RX buffer queue. /// @@ -409,8 +404,6 @@ public void ProcessSynReceived(TCPPacket packet) TCB.SndWl1 = packet.SequenceNumber; TCB.SndWl2 = packet.SequenceNumber; - LastSequenceNumber = packet.SequenceNumber - 1; //TODO: Fix this trick (for dup check when PSH ACK) - Status = Status.ESTABLISHED; } else @@ -466,8 +459,6 @@ public void ProcessSynSent(TCPPacket packet) TCB.SndWl1 = packet.SequenceNumber; TCB.SndWl2 = packet.SequenceNumber; - LastSequenceNumber = packet.SequenceNumber; - SendEmptyPacket(Flags.ACK); Status = Status.ESTABLISHED; @@ -497,18 +488,13 @@ public void ProcessEstablished(TCPPacket packet) { if (packet.PSH) { - if (packet.SequenceNumber > LastSequenceNumber) //dup check - { - LastSequenceNumber = packet.SequenceNumber; + TCB.RcvNxt += packet.TCP_DataLength; - TCB.RcvNxt += packet.TCP_DataLength; - - Data = ArrayHelper.Concat(Data, packet.TCP_Data); + Data = ArrayHelper.Concat(Data, packet.TCP_Data); - rxBuffer.Enqueue(packet); + rxBuffer.Enqueue(packet); - SendEmptyPacket(Flags.ACK); - } + SendEmptyPacket(Flags.ACK); } if (WaitingAck) From 93dc384e48aaeb5eaf3ac30b663abf88e9c050fc Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 8 Jun 2021 16:29:37 +0200 Subject: [PATCH 207/314] Update window + More TCP checks for ESTABLISHED state --- .../Network/IPv4/TCP/TCPClient.cs | 5 +- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 153 ++++++++++-------- 2 files changed, 86 insertions(+), 72 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs index 18ea6b0d76..4f5e7d09d1 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/TCPClient.cs @@ -168,7 +168,7 @@ public void Send(byte[] data) for (int i = 0; i < chunks.Length; i++) { - var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, StateMachine.LocalPort, StateMachine.RemotePort, StateMachine.TCB.SndNxt, StateMachine.TCB.RcvNxt, 20, i == chunks.Length - 2 ? (byte)(Flags.PSH | Flags.ACK) : (byte)(Flags.ACK), Tcp.TcpWindowSize, 0, chunks[i]); + var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, StateMachine.LocalPort, StateMachine.RemotePort, StateMachine.TCB.SndNxt, StateMachine.TCB.RcvNxt, 20, i == chunks.Length - 2 ? (byte)(Flags.PSH | Flags.ACK) : (byte)(Flags.ACK), StateMachine.TCB.SndWnd, 0, chunks[i]); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); @@ -177,13 +177,12 @@ public void Send(byte[] data) } else { - var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, StateMachine.LocalPort, StateMachine.RemotePort, StateMachine.TCB.SndNxt, StateMachine.TCB.RcvNxt, 20, (byte)(Flags.PSH | Flags.ACK), Tcp.TcpWindowSize, 0, data); + var packet = new TCPPacket(StateMachine.LocalAddress, StateMachine.RemoteAddress, StateMachine.LocalPort, StateMachine.RemotePort, StateMachine.TCB.SndNxt, StateMachine.TCB.RcvNxt, 20, (byte)(Flags.PSH | Flags.ACK), StateMachine.TCB.SndWnd, 0, data); OutgoingBuffer.AddPacket(packet); NetworkStack.Update(); StateMachine.TCB.SndNxt += (uint)data.Length; } - StateMachine.WaitingAck = true; } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index b10c5d3a68..180cb38123 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -88,7 +88,7 @@ public class TransmissionControlBlock /// /// Send window. /// - public uint SndWnd { get; set; } + public ushort SndWnd { get; set; } /// /// Send urgent pointer. @@ -234,11 +234,6 @@ internal static Tcp GetConnection(ushort localPort, ushort remotePort, Address l #endregion - /// - /// Is waiting for an acknowledgement packet. - /// - internal bool WaitingAck; - /// /// RX buffer queue. /// @@ -262,8 +257,6 @@ public Tcp(ushort localPort, ushort remotePort, Address localIp, Address remoteI RemoteAddress = remoteIp; TCB = new TransmissionControlBlock(); - - WaitingAck = false; } /// @@ -419,8 +412,38 @@ public void ProcessSynReceived(TCPPacket packet) /// Packet to receive. public void ProcessSynSent(TCPPacket packet) { - if (packet.TCPFlags == (byte)Flags.ACK) + if (packet.SYN) + { + TCB.IRS = packet.SequenceNumber; + TCB.RcvNxt = packet.SequenceNumber + 1; + + if (packet.ACK) + { + TCB.SndUna = packet.AckNumber; + TCB.SndWnd = packet.WindowSize; + TCB.SndWl1 = packet.SequenceNumber; + TCB.SndWl2 = packet.AckNumber; + + SendEmptyPacket(Flags.ACK); + + Status = Status.ESTABLISHED; + } + else if (packet.TCPFlags == (byte)Flags.SYN) + { + Status = Status.CLOSED; + + Global.mDebugger.Send("Simultaneous open not supported."); + } + else + { + Status = Status.CLOSED; + + Global.mDebugger.Send("TCP connection closed! (" + packet.getFlags() + " received on SYN_SENT state)"); + } + } + else if (packet.ACK) { + //Check for bad ACK packet if ((packet.AckNumber - TCB.ISS) < 0 || (packet.AckNumber - TCB.SndNxt) > 0) { SendEmptyPacket(Flags.RST, packet.AckNumber); @@ -447,45 +470,42 @@ public void ProcessSynSent(TCPPacket packet) Global.mDebugger.Send("Connection refused by remote computer."); } - else if (packet.SYN) - { - TCB.IRS = packet.SequenceNumber; - TCB.RcvNxt = packet.SequenceNumber + 1; + } - if (packet.ACK) + /// + /// Process ESTABLISHED Status. + /// + /// Packet to receive. + public void ProcessEstablished(TCPPacket packet) + { + if (packet.ACK) + { + if (TCB.SndUna < packet.AckNumber && packet.AckNumber <= TCB.SndNxt) { TCB.SndUna = packet.AckNumber; - TCB.SndWnd = packet.WindowSize; - TCB.SndWl1 = packet.SequenceNumber; - TCB.SndWl2 = packet.SequenceNumber; - - SendEmptyPacket(Flags.ACK); - Status = Status.ESTABLISHED; + //Update Window Size + if (TCB.SndWl1 < packet.SequenceNumber || (TCB.SndWl1 == packet.SequenceNumber && TCB.SndWl2 <= packet.AckNumber)) + { + TCB.SndWnd = packet.WindowSize; + TCB.SndWl1 = packet.SequenceNumber; + TCB.SndWl2 = packet.AckNumber; + } } - else if (packet.TCPFlags == (byte)Flags.SYN) - { - Status = Status.CLOSED; - Global.mDebugger.Send("Simultaneous open not supported."); - } - else + // Check for duplicate packet + if (packet.AckNumber < TCB.SndUna) { - Status = Status.CLOSED; + return; + } - Global.mDebugger.Send("TCP connection closed! (" + packet.getFlags() + " received on SYN_SENT state)"); + // Something not yet sent + if (packet.AckNumber > TCB.SndNxt) + { + SendEmptyPacket(Flags.ACK); + return; } - } - } - /// - /// Process ESTABLISHED Status. - /// - /// Packet to receive. - public void ProcessEstablished(TCPPacket packet) - { - if (packet.ACK && !packet.FIN) - { if (packet.PSH) { TCB.RcvNxt += packet.TCP_DataLength; @@ -495,25 +515,25 @@ public void ProcessEstablished(TCPPacket packet) rxBuffer.Enqueue(packet); SendEmptyPacket(Flags.ACK); + return; } - - if (WaitingAck) + else if (packet.FIN) { - if (packet.AckNumber == TCB.SndNxt) - { - WaitingAck = false; - } + TCB.RcvNxt++; + + SendEmptyPacket(Flags.ACK); + + WaitAndClose(); + + return; } - else if (!packet.PSH) + + if (packet.TCP_DataLength > 0 && packet.SequenceNumber >= TCB.RcvNxt) //packet sequencing { - if (packet.SequenceNumber >= TCB.RcvNxt && packet.TCP_DataLength > 0) //packet sequencing - { - TCB.RcvNxt += packet.TCP_DataLength; + TCB.RcvNxt += packet.TCP_DataLength; - Data = ArrayHelper.Concat(Data, packet.TCP_Data); - } + Data = ArrayHelper.Concat(Data, packet.TCP_Data); } - return; } if (packet.RST) { @@ -521,14 +541,6 @@ public void ProcessEstablished(TCPPacket packet) throw new Exception("TCP Connection resetted!"); } - else if (packet.FIN && packet.ACK) - { - TCB.RcvNxt++; - - SendEmptyPacket(Flags.ACK); - - WaitAndClose(); - } else if (packet.FIN) { TCB.RcvNxt++; @@ -551,13 +563,20 @@ public void ProcessEstablished(TCPPacket packet) /// Packet to receive. public void ProcessFinWait1(TCPPacket packet) { - if (packet.FIN && packet.ACK) + if (packet.ACK) { - TCB.RcvNxt++; + if (packet.FIN) + { + TCB.RcvNxt++; - SendEmptyPacket(Flags.ACK); + SendEmptyPacket(Flags.ACK); - WaitAndClose(); + WaitAndClose(); + } + else + { + Status = Status.FIN_WAIT2; + } } else if (packet.FIN) { @@ -567,10 +586,6 @@ public void ProcessFinWait1(TCPPacket packet) Status = Status.CLOSING; } - else if (packet.ACK) - { - Status = Status.FIN_WAIT2; - } } /// @@ -667,7 +682,7 @@ internal bool WaitStatus(Status status) /// internal void SendEmptyPacket(Flags flag) { - SendPacket(new TCPPacket(LocalAddress, RemoteAddress, LocalPort, RemotePort, TCB.SndNxt, TCB.RcvNxt, 20, (byte)flag, TcpWindowSize, 0)); + SendPacket(new TCPPacket(LocalAddress, RemoteAddress, LocalPort, RemotePort, TCB.SndNxt, TCB.RcvNxt, 20, (byte)flag, TCB.SndWnd, 0)); } /// @@ -675,7 +690,7 @@ internal void SendEmptyPacket(Flags flag) /// internal void SendEmptyPacket(Flags flag, uint sequenceNumber) { - SendPacket(new TCPPacket(LocalAddress, RemoteAddress, LocalPort, RemotePort, sequenceNumber, TCB.RcvNxt, 20, (byte)flag, TcpWindowSize, 0)); + SendPacket(new TCPPacket(LocalAddress, RemoteAddress, LocalPort, RemotePort, sequenceNumber, TCB.RcvNxt, 20, (byte)flag, TCB.SndWnd, 0)); } /// From 7568caa0aff76452306ef6e79261b3936596ef1a Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 8 Jun 2021 16:33:10 +0200 Subject: [PATCH 208/314] Change thrown new Exception to debugger messages https://github.com/CosmosOS/Cosmos/issues/1769 --- source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs index 180cb38123..979fffef1b 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/Tcp.cs @@ -312,7 +312,8 @@ internal void ReceiveData(TCPPacket packet) case Status.TIME_WAIT: break; default: - throw new Exception("Unknown TCP connection state."); + Global.mDebugger.Send("Unknown TCP connection state."); + break; } } else @@ -345,7 +346,7 @@ public void ProcessListen(TCPPacket packet) { Status = Status.CLOSED; - throw new Exception("TCP connection closed! (FIN received on LISTEN state)"); + Global.mDebugger.Send("TCP connection closed! (FIN received on LISTEN state)"); } else if (packet.ACK) { @@ -539,7 +540,7 @@ public void ProcessEstablished(TCPPacket packet) { Status = Status.CLOSED; - throw new Exception("TCP Connection resetted!"); + Global.mDebugger.Send("TCP Connection resetted!"); } else if (packet.FIN) { From 160f6f73c9f4d3d74888f7eb2d7d44da4df3351d Mon Sep 17 00:00:00 2001 From: Arawn Davies Date: Tue, 8 Jun 2021 15:56:45 +0100 Subject: [PATCH 209/314] Update index.md --- Docs/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Docs/index.md b/Docs/index.md index fb07b55f7a..6d8e8acc9c 100644 --- a/Docs/index.md +++ b/Docs/index.md @@ -1,8 +1,8 @@ # Welcome to the Official Cosmos Documentation -If you're knew to Cosmos, welcome! Before you get stuck in the API documentation, we highly recommend you visit the website linked at the bottom. +If you're new to Cosmos, welcome! Before you get stuck in the API documentation, we highly recommend you visit the website linked at the bottom. -The Articles section of this website includes some articles which have been written many years ago for websites such as www.codeproject.com and are kept for archival purposes. These discuss elements such as the Cosmos Virtual FIle System. We prefer newcomers who want to develop their own operating systems to read the API documentation while we update these articles to comply with the current Cosmos project. +The Articles section of this website includes some articles which have been written many years ago for websites such as www.codeproject.com and are kept for archival purposes. These discuss elements such as the Cosmos Virtual File System. We prefer newcomers who want to develop their own operating systems to read the API documentation while we update these articles to comply with the current Cosmos project. For projects using the VFS directly, we recommend you use System.IO methods where possible. This is because these were written before much progress was made making .NET assemblies usable From f900925bc350fa96ea8c2341495918e16210c3f0 Mon Sep 17 00:00:00 2001 From: valentinbreiz Date: Tue, 8 Jun 2021 17:25:29 +0200 Subject: [PATCH 210/314] FTP CWD fixes + Remove PASV mode for now --- .../Network/IPv4/TCP/FTP/FtpCommandManager.cs | 36 ++++++++++++++++--- .../Network/IPv4/TCP/FTP/FtpServer.cs | 2 +- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs index 31f84c85ee..4132364ca7 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpCommandManager.cs @@ -192,9 +192,22 @@ internal void ProcessCwd(FtpClient ftpClient, FtpCommand command) command.Content += "\\"; } - if (Directory.Exists(command.Content)) + while (command.Content[0] == '\\') + { + command.Content = command.Content.Remove(0, 1); + } + + if (command.Content.Contains(":\\")) //full path check { CurrentDirectory = command.Content; + } + else + { + CurrentDirectory += "\\" + command.Content; + } + + if (Directory.Exists(CurrentDirectory)) + { Directory.SetCurrentDirectory(CurrentDirectory); ftpClient.SendReply(250, "Requested file action okay."); } @@ -216,7 +229,15 @@ internal void ProcessCwd(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessPwd(FtpClient ftpClient, FtpCommand command) { - ftpClient.SendReply(257, "/" + CurrentDirectory + " created."); + string tmp = "Cosmos"; + + if (CurrentDirectory.Length == 3) //root check + { + int i = CurrentDirectory.IndexOf(":") + 1; + tmp += CurrentDirectory.Substring(i); + } + + ftpClient.SendReply(257, "/" + tmp + " created."); } /// @@ -226,7 +247,14 @@ internal void ProcessPwd(FtpClient ftpClient, FtpCommand command) /// FTP Command. internal void ProcessPasv(FtpClient ftpClient, FtpCommand command) { - //TODO: Find port dynamically. + /* + TODO: - Fix new TCP SYN connection (https://stackoverflow.com/questions/67824462/why-does-my-ftp-client-open-multiple-control-connection) + - Find port dynamically. + */ + + throw new NotImplementedException("FTP Passive mode not supported yet!"); + + /* int port = 20; var address = ftpClient.Control.StateMachine.LocalAddress.ToByteArray(); @@ -235,7 +263,7 @@ internal void ProcessPasv(FtpClient ftpClient, FtpCommand command) ftpClient.DataListener = new TcpListener(port); ftpClient.DataListener.Start(); - ftpClient.Mode = TransferMode.PASV; + ftpClient.Mode = TransferMode.PASV;*/ } /// diff --git a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs index 725e7e411b..1c9a9ea578 100644 --- a/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs +++ b/source/Cosmos.System2/Network/IPv4/TCP/FTP/FtpServer.cs @@ -118,7 +118,7 @@ private void ReceiveNewClient(TcpClient client) /// Parse and execute FTP command. /// /// FTP Client. - internal void ReceiveRequest(FtpClient ftpClient) + private void ReceiveRequest(FtpClient ftpClient) { var ep = new EndPoint(Address.Zero, 0); var data = Encoding.ASCII.GetString(ftpClient.Control.Receive(ref ep)); From c10a6b05906906c163380b3eeaeca0f7cdd2b6e2 Mon Sep 17 00:00:00 2001 From: Arawn Davies Date: Tue, 8 Jun 2021 16:54:48 +0100 Subject: [PATCH 211/314] Create install.md The WordPress site is currently experiencing some issues, so I suggest adding an install how-to page onto cosmosos.github.io as I discussed with @quajak. --- Docs/install.md | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Docs/install.md diff --git a/Docs/install.md b/Docs/install.md new file mode 100644 index 0000000000..8ccec27bb7 --- /dev/null +++ b/Docs/install.md @@ -0,0 +1,76 @@ +### Prerequisites + +* **Visual Studio 2019** - [Download](https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx) +* **Visual Studio 2019 Workload: .NET Core Tools** - .NET Core cross-platform development +* **.NET Framework 4.6.2 Developer Pack** - [Download](https://www.microsoft.com/en-us/download/details.aspx?id=53321) +* **VMware Player OR Workstation** VMware Player is free, so that is recommended instead - [Download](https://www.vmware.com/uk/products/workstation-player/workstation-player-evaluation.html) + +### Installing Cosmos + +First, you need to choose between the User Kit and the Dev Kit. It is recommended that new users start with the User Kit but only move later to the Dev Kit if you need the latest features and want to contribute back to the main project. +The Dev Kit is the live source against which the Cosmos Team develops directly. The Dev Kit has the latest and greatest features, but at various times has known issues, and sometimes may not even build. Thus to use the Dev Kit be sure to join our support channels and inquire about the current status before using the Dev Kit or updating it. + +The User Kit is a snapshot stable version of Cosmos including a premade installer. The UserKit however is often quite a bit out of date compared to the DevKit and is only occasionally updated. The User Kit is a great easy way to get familiar with Cosmos, but active developers should transition to the Dev Kit after becoming very familiar with the UserKit, and expect some bugs here and there. + +### User Kit + +1. Download [the latest release of Cosmos](http://github.com/CosmosOS/Cosmos/releases/latest) (download the **exe** file) +2. Wait for the download to complete then run the installer. Allow it to run as admin. Make sure **VS2019 is NOT running** when you do this. +3. Click "Next" then "Install" +4. Wait for the install to progress. **Tip:** At the end the installer may look like it has stalled, but it is still doing something in the background. WAIT for the "Finish" button to become available. +5. Cosmos should now be installed. Follow other tutorials to find out how to create your first OS. + +### Dev Kit + +##### **Additional Prerequisites** + +* **Visual Studio 2019 Workload: Visual Studio Extension Development** +* **Inno Quick Start Pack (Free)** – Install with defaults, keep Preprocessor option checked [Download](http://www.jrsoftware.org/isdl.php#qsp) +* **.NET Core 2.0 SDK** - [Download](https://www.microsoft.com/net/download/core) + +##### Get the Source + +Cosmos source is hosted at GitHub. The simplest method to obtain the source is download a .zip file, however this makes updating and getting the latest updates a bit tricky. +To update the Cosmos source more efficiently, use the Git command line, or any of the many Git User Interfaces. Any frontend may work fine but for users new to Git, we suggest [GitHub Desktop](https://desktop.github.com/). For more experienced Git users, we really like [Git Kraken](https://www.gitkraken.com/). Git Kraken is free for non-commercial use such as Cosmos. SourceTree, Git GUI, and others are also available. + +To aid in better encapsulation and to invite more developers to assist in various areas, Cosmos is split into four Git repositories. Each of these is designed to be an independent project although Cosmos relies on the other three. +You will need to pull the source for all four repositories and they must exist in sibling directories as shown in the diagram below. The Cosmos base directory can be named anything and exist anywhere. But the directories inside it must match exactly.   + +Windows is not case sensitive for files, but many of the ._**NET Core tools used to build are case sensitive even on Windows for file paths**_. Make sure to create the subdirectories exactly as shown. For demonstration purposes let us assume that you will use c:\\source\\Cosmos to install to. +This base directory is referred to as the Cosmos directory. Each of the four repositories then must be cloned or extracted to the corresponding sub folder of the Cosmos directory. Using this example, the set up should look like this: +``` +c:\\source\\CosmosOS\\ +c:\\source\\CosmosOS\\Cosmos\\ - [Git Repository for Cosmos](https://github.com/CosmosOS/Cosmos) +c:\\source\\CosmosOS\\IL2CPU\\ - [Git Repository for IL2CPU](https://github.com/CosmosOS/IL2CPU) +c:\\source\\CosmosOS\\XSharp\\ - [Git Repository for XSharp](https://github.com/CosmosOS/XSharp) +c:\\source\\CosmosOS\\Common\\ - [Git Repository for Common](https://github.com/CosmosOS/Common) +``` +A tree diagram of the source should look like the following: +![](https://www.gocosmos.org/wp-content/uploads/2021/06/tree-214x300.png) + +We are working to make syncing code easier. We have already experimented with Git Submodules, however the simple use of submodules presents a few issues, but the biggest of them is that they trigger a fireworks show of problems and errors in every Git UI we tried and would have limited developers options and forced them to the command line in most cases. We are currently investigating subtrees. + +For now, it's much easier to handle the 4 repositories as most of the time, new Cosmos developers may only have to work in the Cosmos repository. Only when you are comfortable with the concept of Operating System development and C# should you venture into IL2CPU and XSharp. + +If you want to keep your source up to date in a one-click method, paste this code into a .bat file in the CosmosOS folder ( as shown in the above example). This .bat file will only work after the repositories have been cloned with git at least once. + +cd C:\\XSharp +git pull +cd ..\\IL2CPU +git pull +cd ..\\Cosmos +git pull +cd ..\\Common +git pull +cd .. + +##### Building and Installing + +(if you have already installed) If you edited the Cosmos DevKit source using _Cosmos.sln_ or _Test.sln_, be sure to set solution config to **Debug x86**. + +1. Make sure Visual Studio is **NOT running**. +2. In the root directory of the DevKit files, you downloaded earlier, run `install-VS2019.bat`. +3. Wait for the install to progress. (**Tip:** At the end the installer may look like it is stalling, it is still doing something, just in the background) +4. VS will open with Cosmos loaded. You can now make changes to core assemblies of Cosmos. If you don't want to, you can close this VS window and create a new Cosmos project as with the user kit. + +Happy Cosmos-ing! From c46d864c92a2595f0aafbf2689f3e1143f0b773e Mon Sep 17 00:00:00 2001 From: Arawn Davies Date: Tue, 8 Jun 2021 17:45:53 +0100 Subject: [PATCH 212/314] Create docs_or_website.md Added a template for users to file a bug report with Cosmos documentation or the website --- .github/ISSUE_TEMPLATE/docs_or_website.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/docs_or_website.md diff --git a/.github/ISSUE_TEMPLATE/docs_or_website.md b/.github/ISSUE_TEMPLATE/docs_or_website.md new file mode 100644 index 0000000000..d3018e2ef8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/docs_or_website.md @@ -0,0 +1,17 @@ +--- +name: Documentation/Website Bug Report +about: For bugs involving the Cosmos documentation & website +title: '' +labels: Bug +assignees: '' + +--- + +#### URL of Documentation - What page of documentation are we dealing with? + + +#### Expected Behaviour - What do you think should happen? + + +#### Actual Behaviour - What is the issue? + From 2088840aa01132570efbb2903f917a0f919ceea2 Mon Sep 17 00:00:00 2001 From: Arawn Davies Date: Tue, 8 Jun 2021 18:28:09 +0100 Subject: [PATCH 213/314] Update docs_or_website.md --- .github/ISSUE_TEMPLATE/docs_or_website.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/docs_or_website.md b/.github/ISSUE_TEMPLATE/docs_or_website.md index d3018e2ef8..50cc37c7da 100644 --- a/.github/ISSUE_TEMPLATE/docs_or_website.md +++ b/.github/ISSUE_TEMPLATE/docs_or_website.md @@ -2,7 +2,7 @@ name: Documentation/Website Bug Report about: For bugs involving the Cosmos documentation & website title: '' -labels: Bug +labels: 'Area: Documentation' assignees: '' --- From 02ec77c5cf7182ad41982af7adec05b8018c0df7 Mon Sep 17 00:00:00 2001 From: MishaTY <46088515+MishaTY@users.noreply.github.com> Date: Tue, 8 Jun 2021 13:40:13 -0400 Subject: [PATCH 214/314] Add new UI --- source/Cosmos.Build.Builder/App.xaml | 12 ++++- .../BuildTasks/ProcessBuildTaskBase.cs | 14 +++++- .../Cosmos.Build.Builder.csproj | 1 + .../DependencyInstallationDialogViewModel.cs | 4 ++ .../ViewModels/MainWindowViewModel.cs | 28 +++++++---- .../Views/DependencyInstallationDialog.xaml | 20 ++++---- .../Views/MainWindow.xaml | 46 +++++++++++++++---- .../Views/VisualStudioInstanceDialog.xaml | 12 +++-- 8 files changed, 103 insertions(+), 34 deletions(-) diff --git a/source/Cosmos.Build.Builder/App.xaml b/source/Cosmos.Build.Builder/App.xaml index a9e0e5a35c..a5f8938efd 100644 --- a/source/Cosmos.Build.Builder/App.xaml +++ b/source/Cosmos.Build.Builder/App.xaml @@ -1,3 +1,13 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:ui="http://schemas.modernwpf.com/2019"> + + + + + + + + + diff --git a/source/Cosmos.Build.Builder/BuildTasks/ProcessBuildTaskBase.cs b/source/Cosmos.Build.Builder/BuildTasks/ProcessBuildTaskBase.cs index 781fb25713..a688a86275 100644 --- a/source/Cosmos.Build.Builder/BuildTasks/ProcessBuildTaskBase.cs +++ b/source/Cosmos.Build.Builder/BuildTasks/ProcessBuildTaskBase.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; @@ -12,6 +13,7 @@ internal abstract class ProcessBuildTaskBase : IBuildTask private readonly bool _waitForExit; private readonly bool _createWindow; + private static List Lines = new List(); protected ProcessBuildTaskBase(bool waitForExit, bool createWindow) { @@ -26,6 +28,7 @@ public Task RunAsync(ILogger logger) logger.LogMessage($"\"{exePath}\" {args}"); + Lines.Clear(); var process = new Process(); var processStartInfo = new ProcessStartInfo(exePath, args); @@ -62,7 +65,14 @@ private static void WaitForExit(Process process) if (process.ExitCode != 0) { - throw new Exception("The process failed to execute!"); + if (Lines.Count == 0) + { + throw new Exception("The process failed to execute!"); + } + else + { + throw new Exception("The process failed to execute!\nLast 1 line from output: \n"+Lines[Lines.Count - 1]); + } } } @@ -76,7 +86,7 @@ private static async Task ReadOutputAsync(StreamReader reader, ILogger logger) { return; } - + Lines.Add(line); logger.LogMessage(line); } } diff --git a/source/Cosmos.Build.Builder/Cosmos.Build.Builder.csproj b/source/Cosmos.Build.Builder/Cosmos.Build.Builder.csproj index c37e2fd0c7..09f03de122 100644 --- a/source/Cosmos.Build.Builder/Cosmos.Build.Builder.csproj +++ b/source/Cosmos.Build.Builder/Cosmos.Build.Builder.csproj @@ -23,6 +23,7 @@ + diff --git a/source/Cosmos.Build.Builder/ViewModels/DependencyInstallationDialogViewModel.cs b/source/Cosmos.Build.Builder/ViewModels/DependencyInstallationDialogViewModel.cs index 8c63e41ed5..a5d1d0ce42 100644 --- a/source/Cosmos.Build.Builder/ViewModels/DependencyInstallationDialogViewModel.cs +++ b/source/Cosmos.Build.Builder/ViewModels/DependencyInstallationDialogViewModel.cs @@ -70,6 +70,10 @@ public DependencyInstallationDialogViewModel(IDependency dependency) public void Dispose() { + if (_installTask == null) + { + return; + } _installTask.Dispose(); _installTaskCancellationTokenSource.Dispose(); } diff --git a/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs b/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs index fd4d6fd827..5ae1d66468 100644 --- a/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs +++ b/source/Cosmos.Build.Builder/ViewModels/MainWindowViewModel.cs @@ -62,7 +62,7 @@ public MainWindowViewModel( CopyCommand = new RelayCommand(CopyLogToClipboard); CloseWhenCompleted = true; - + _logger = new MainWindowLogger(this); _buildTask = BuildAsync(); @@ -95,10 +95,9 @@ Builder Log private async Task BuildAsync() { + _logger.NewSection("Checking Dependencies"); try { - _logger.NewSection("Checking Dependencies"); - foreach (var dependency in _buildDefinition.GetDependencies()) { if (await dependency.IsInstalledAsync(CancellationToken.None).ConfigureAwait(false)) @@ -107,7 +106,7 @@ private async Task BuildAsync() } else { - _logger.LogMessage($"{dependency.Name} not found. Install {dependency.OtherDependencysThatAreMissing}"); + _logger.LogMessage($"{dependency.Name} not found. Install {dependency.OtherDependencysThatAreMissing.TrimEnd(',')}"); if (dependency.ShouldInstallByDefault) { @@ -132,7 +131,14 @@ private async Task BuildAsync() } } } + } + catch (Exception e) + { + OnError("Error while installing dependencies: " + e.Message); + } + try + { foreach (var buildTask in _buildDefinition.GetBuildTasks()) { _logger.NewSection(buildTask.Name); @@ -142,11 +148,7 @@ private async Task BuildAsync() } catch (Exception e) { - _logger.SetError(); - - _logger.NewSection("Error"); - _logger.LogMessage(e.ToString()); - _logger.SetError(); + OnError(e.Message); } await Task.Delay(5000).ConfigureAwait(false); @@ -163,5 +165,13 @@ private async Task BuildAsync() } } } + public void OnError(string message) + { + _logger.SetError(); + + _logger.NewSection("Error"); + _logger.LogMessage(message); + _logger.SetError(); + } } } diff --git a/source/Cosmos.Build.Builder/Views/DependencyInstallationDialog.xaml b/source/Cosmos.Build.Builder/Views/DependencyInstallationDialog.xaml index 943571d54a..571ca24a40 100644 --- a/source/Cosmos.Build.Builder/Views/DependencyInstallationDialog.xaml +++ b/source/Cosmos.Build.Builder/Views/DependencyInstallationDialog.xaml @@ -10,7 +10,9 @@ ShowInTaskbar="False" SizeToContent="WidthAndHeight" Title="Cosmos Kit Builder" - WindowStartupLocation="CenterOwner"> + WindowStartupLocation="CenterOwner" + xmlns:ui="http://schemas.modernwpf.com/2019" + ui:WindowHelper.UseModernWindowStyle="True"> @@ -37,12 +39,13 @@ -