From 77cb0dea0aaa30aed04dbc870614cf43962e2127 Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Mon, 3 Nov 2025 23:51:06 +0200 Subject: [PATCH 01/18] Update sonarcloud.yml --- .github/workflows/sonarcloud.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index e7840696..1518b38c 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -56,8 +56,8 @@ jobs: dotnet tool install --global dotnet-sonarscanner echo "$env:USERPROFILE\.dotnet\tools" >> $env:GITHUB_PATH dotnet sonarscanner begin ` - /k:"ppanchen_NetSdrClient" ` - /o:"ppanchen" ` + /d:sonar.projectKey="Starenkiyy_NetSdrClient" ` + /d:sonar.organization="starenkiyy" ` /d:sonar.token="${{ secrets.SONAR_TOKEN }}" ` /d:sonar.cs.opencover.reportsPaths="**/coverage.xml" ` /d:sonar.cpd.cs.minimumTokens=40 ` From 18a9575a6f5abb94fee9d978523ce030bd6ff2f0 Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Tue, 4 Nov 2025 00:12:17 +0200 Subject: [PATCH 02/18] Update sonarcloud.yml --- .github/workflows/sonarcloud.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 1518b38c..a4943a29 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -56,8 +56,8 @@ jobs: dotnet tool install --global dotnet-sonarscanner echo "$env:USERPROFILE\.dotnet\tools" >> $env:GITHUB_PATH dotnet sonarscanner begin ` - /d:sonar.projectKey="Starenkiyy_NetSdrClient" ` - /d:sonar.organization="starenkiyy" ` + /d:"Starenkiyy_NetSdrClient" ` + /d:"starenkiyy" ` /d:sonar.token="${{ secrets.SONAR_TOKEN }}" ` /d:sonar.cs.opencover.reportsPaths="**/coverage.xml" ` /d:sonar.cpd.cs.minimumTokens=40 ` From ef18daa9192e89228586d564cdc4bae9c176ae02 Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Tue, 4 Nov 2025 00:14:56 +0200 Subject: [PATCH 03/18] Update sonarcloud.yml --- .github/workflows/sonarcloud.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index a4943a29..68234276 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -56,8 +56,8 @@ jobs: dotnet tool install --global dotnet-sonarscanner echo "$env:USERPROFILE\.dotnet\tools" >> $env:GITHUB_PATH dotnet sonarscanner begin ` - /d:"Starenkiyy_NetSdrClient" ` - /d:"starenkiyy" ` + /k:"Starenkiyy_NetSdrClient" ` + /o:"starenkiyy" ` /d:sonar.token="${{ secrets.SONAR_TOKEN }}" ` /d:sonar.cs.opencover.reportsPaths="**/coverage.xml" ` /d:sonar.cpd.cs.minimumTokens=40 ` From 161a8c6083f7b01ddd128450d9eb805214db7cec Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 00:54:58 +0200 Subject: [PATCH 04/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0eb9d3b4..0030eae1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Лабораторні з реінжинірингу (8×) -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=ppanchen_NetSdrClient&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=ppanchen_NetSdrClient) +[![Quality Gate Status]([![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Starenkiyy_NetSdrClient&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Starenkiyy_NetSdrClient)) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=ppanchen_NetSdrClient&metric=coverage)](https://sonarcloud.io/summary/new_code?id=ppanchen_NetSdrClient) [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=ppanchen_NetSdrClient&metric=bugs)](https://sonarcloud.io/summary/new_code?id=ppanchen_NetSdrClient) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=ppanchen_NetSdrClient&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=ppanchen_NetSdrClient) From b2e75fd5cf3ccd21d7ded8e290c067c97de7c0d6 Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 00:55:40 +0200 Subject: [PATCH 05/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0030eae1..499010ef 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Лабораторні з реінжинірингу (8×) -[![Quality Gate Status]([![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Starenkiyy_NetSdrClient&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Starenkiyy_NetSdrClient)) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Starenkiyy_NetSdrClient&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Starenkiyy_NetSdrClient)) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=ppanchen_NetSdrClient&metric=coverage)](https://sonarcloud.io/summary/new_code?id=ppanchen_NetSdrClient) [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=ppanchen_NetSdrClient&metric=bugs)](https://sonarcloud.io/summary/new_code?id=ppanchen_NetSdrClient) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=ppanchen_NetSdrClient&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=ppanchen_NetSdrClient) From 3a3703cff337a0f10e03842228baba74abe1acfe Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 00:55:51 +0200 Subject: [PATCH 06/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 499010ef..8b31dede 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Лабораторні з реінжинірингу (8×) -[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Starenkiyy_NetSdrClient&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Starenkiyy_NetSdrClient)) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=Starenkiyy_NetSdrClient&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=Starenkiyy_NetSdrClient) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=ppanchen_NetSdrClient&metric=coverage)](https://sonarcloud.io/summary/new_code?id=ppanchen_NetSdrClient) [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=ppanchen_NetSdrClient&metric=bugs)](https://sonarcloud.io/summary/new_code?id=ppanchen_NetSdrClient) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=ppanchen_NetSdrClient&metric=code_smells)](https://sonarcloud.io/summary/new_code?id=ppanchen_NetSdrClient) From a6f541cc2de657a113edc55fa3ae6b031dd270fa Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 01:24:02 +0200 Subject: [PATCH 07/18] EchoTcpServer/Program.cs --- EchoTcpServer/Program.cs | 154 ++++++++++++++++++++------------------- 1 file changed, 79 insertions(+), 75 deletions(-) diff --git a/EchoTcpServer/Program.cs b/EchoTcpServer/Program.cs index 5966c579..c9b18219 100644 --- a/EchoTcpServer/Program.cs +++ b/EchoTcpServer/Program.cs @@ -9,105 +9,109 @@ /// This program was designed for test purposes only /// Not for a review /// -public class EchoServer +namespace NetSdrClient { - private readonly int _port; - private TcpListener _listener; - private CancellationTokenSource _cancellationTokenSource; - + public class EchoServer - public EchoServer(int port) { - _port = port; - _cancellationTokenSource = new CancellationTokenSource(); - } + private readonly int _port; + private TcpListener _listener; + private CancellationTokenSource _cancellationTokenSource; - public async Task StartAsync() - { - _listener = new TcpListener(IPAddress.Any, _port); - _listener.Start(); - Console.WriteLine($"Server started on port {_port}."); - while (!_cancellationTokenSource.Token.IsCancellationRequested) + public EchoServer(int port) { - try - { - TcpClient client = await _listener.AcceptTcpClientAsync(); - Console.WriteLine("Client connected."); - - _ = Task.Run(() => HandleClientAsync(client, _cancellationTokenSource.Token)); - } - catch (ObjectDisposedException) - { - // Listener has been closed - break; - } + _port = port; + _cancellationTokenSource = new CancellationTokenSource(); } - Console.WriteLine("Server shutdown."); - } - - private async Task HandleClientAsync(TcpClient client, CancellationToken token) - { - using (NetworkStream stream = client.GetStream()) + public async Task StartAsync() { - try + _listener = new TcpListener(IPAddress.Any, _port); + _listener.Start(); + Console.WriteLine($"Server started on port {_port}."); + + while (!_cancellationTokenSource.Token.IsCancellationRequested) { - byte[] buffer = new byte[8192]; - int bytesRead; + try + { + TcpClient client = await _listener.AcceptTcpClientAsync(); + Console.WriteLine("Client connected."); - while (!token.IsCancellationRequested && (bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, token)) > 0) + _ = Task.Run(() => HandleClientAsync(client, _cancellationTokenSource.Token)); + } + catch (ObjectDisposedException) { - // Echo back the received message - await stream.WriteAsync(buffer, 0, bytesRead, token); - Console.WriteLine($"Echoed {bytesRead} bytes to the client."); + // Listener has been closed + break; } } - catch (Exception ex) when (!(ex is OperationCanceledException)) - { - Console.WriteLine($"Error: {ex.Message}"); - } - finally + + Console.WriteLine("Server shutdown."); + } + + private async Task HandleClientAsync(TcpClient client, CancellationToken token) + { + using (NetworkStream stream = client.GetStream()) { - client.Close(); - Console.WriteLine("Client disconnected."); + try + { + byte[] buffer = new byte[8192]; + int bytesRead; + + while (!token.IsCancellationRequested && (bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, token)) > 0) + { + // Echo back the received message + await stream.WriteAsync(buffer, 0, bytesRead, token); + Console.WriteLine($"Echoed {bytesRead} bytes to the client."); + } + } + catch (Exception ex) when (!(ex is OperationCanceledException)) + { + Console.WriteLine($"Error: {ex.Message}"); + } + finally + { + client.Close(); + Console.WriteLine("Client disconnected."); + } } } - } - - public void Stop() - { - _cancellationTokenSource.Cancel(); - _listener.Stop(); - _cancellationTokenSource.Dispose(); - Console.WriteLine("Server stopped."); - } - public static async Task Main(string[] args) - { - EchoServer server = new EchoServer(5000); + public void Stop() + { + _cancellationTokenSource.Cancel(); + _listener.Stop(); + _cancellationTokenSource.Dispose(); + Console.WriteLine("Server stopped."); + } - // Start the server in a separate task - _ = Task.Run(() => server.StartAsync()); + public static async Task Main(string[] args) + { + EchoServer server = new EchoServer(5000); - string host = "127.0.0.1"; // Target IP - int port = 60000; // Target Port - int intervalMilliseconds = 5000; // Send every 3 seconds + // Start the server in a separate task + _ = Task.Run(() => server.StartAsync()); - using (var sender = new UdpTimedSender(host, port)) - { - Console.WriteLine("Press any key to stop sending..."); - sender.StartSending(intervalMilliseconds); + string host = "127.0.0.1"; // Target IP + int port = 60000; // Target Port + int intervalMilliseconds = 5000; // Send every 3 seconds - Console.WriteLine("Press 'q' to quit..."); - while (Console.ReadKey(intercept: true).Key != ConsoleKey.Q) + using (var sender = new UdpTimedSender(host, port)) { - // Just wait until 'q' is pressed - } + Console.WriteLine("Press any key to stop sending..."); + sender.StartSending(intervalMilliseconds); - sender.StopSending(); - server.Stop(); - Console.WriteLine("Sender stopped."); + Console.WriteLine("Press 'q' to quit..."); + while (Console.ReadKey(intercept: true).Key != ConsoleKey.Q) + { + // Just wait until 'q' is pressed + } + + sender.StopSending(); + server.Stop(); + Console.WriteLine("Sender stopped."); + } } } } From c269c85b27c48fd5aca4b671e3ae541713bffb19 Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 01:30:01 +0200 Subject: [PATCH 08/18] namespace NetSdrClient --- EchoTcpServer/Program.cs | 89 +++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/EchoTcpServer/Program.cs b/EchoTcpServer/Program.cs index c9b18219..666605b4 100644 --- a/EchoTcpServer/Program.cs +++ b/EchoTcpServer/Program.cs @@ -116,62 +116,65 @@ public static async Task Main(string[] args) } } - -public class UdpTimedSender : IDisposable +namespace NetSdrClient { - private readonly string _host; - private readonly int _port; - private readonly UdpClient _udpClient; - private Timer _timer; - public UdpTimedSender(string host, int port) + public class UdpTimedSender : IDisposable { - _host = host; - _port = port; - _udpClient = new UdpClient(); - } + private readonly string _host; + private readonly int _port; + private readonly UdpClient _udpClient; + private Timer _timer; - public void StartSending(int intervalMilliseconds) - { - if (_timer != null) - throw new InvalidOperationException("Sender is already running."); + public UdpTimedSender(string host, int port) + { + _host = host; + _port = port; + _udpClient = new UdpClient(); + } - _timer = new Timer(SendMessageCallback, null, 0, intervalMilliseconds); - } + public void StartSending(int intervalMilliseconds) + { + if (_timer != null) + throw new InvalidOperationException("Sender is already running."); - ushort i = 0; + _timer = new Timer(SendMessageCallback, null, 0, intervalMilliseconds); + } - private void SendMessageCallback(object state) - { - try + ushort i = 0; + + private void SendMessageCallback(object state) { - //dummy data - Random rnd = new Random(); - byte[] samples = new byte[1024]; - rnd.NextBytes(samples); - i++; + try + { + //dummy data + Random rnd = new Random(); + byte[] samples = new byte[1024]; + rnd.NextBytes(samples); + i++; - byte[] msg = (new byte[] { 0x04, 0x84 }).Concat(BitConverter.GetBytes(i)).Concat(samples).ToArray(); - var endpoint = new IPEndPoint(IPAddress.Parse(_host), _port); + byte[] msg = (new byte[] { 0x04, 0x84 }).Concat(BitConverter.GetBytes(i)).Concat(samples).ToArray(); + var endpoint = new IPEndPoint(IPAddress.Parse(_host), _port); - _udpClient.Send(msg, msg.Length, endpoint); - Console.WriteLine($"Message sent to {_host}:{_port} "); + _udpClient.Send(msg, msg.Length, endpoint); + Console.WriteLine($"Message sent to {_host}:{_port} "); + } + catch (Exception ex) + { + Console.WriteLine($"Error sending message: {ex.Message}"); + } } - catch (Exception ex) + + public void StopSending() { - Console.WriteLine($"Error sending message: {ex.Message}"); + _timer?.Dispose(); + _timer = null; } - } - public void StopSending() - { - _timer?.Dispose(); - _timer = null; - } - - public void Dispose() - { - StopSending(); - _udpClient.Dispose(); + public void Dispose() + { + StopSending(); + _udpClient.Dispose(); + } } } \ No newline at end of file From ea48231aaedb90b0550850595caa2d1a1bc45cdf Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 01:37:06 +0200 Subject: [PATCH 09/18] IUdpClient.cs --- NetSdrClientApp/Networking/IUdpClient.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/NetSdrClientApp/Networking/IUdpClient.cs b/NetSdrClientApp/Networking/IUdpClient.cs index 1b9f9311..b85244c2 100644 --- a/NetSdrClientApp/Networking/IUdpClient.cs +++ b/NetSdrClientApp/Networking/IUdpClient.cs @@ -1,10 +1,12 @@ - -public interface IUdpClient +namespace NetSdrClientApp.Networking { - event EventHandler? MessageReceived; + public interface IUdpClient + { + event EventHandler? MessageReceived; - Task StartListeningAsync(); + Task StartListeningAsync(); - void StopListening(); - void Exit(); + void StopListening(); + void Exit(); + } } \ No newline at end of file From f722e00495a97b0dad950db4ddce4404882fc152 Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 01:41:04 +0200 Subject: [PATCH 10/18] namespace NetSdrClientApp.Networking --- NetSdrClientApp/Networking/IUdpClient.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/NetSdrClientApp/Networking/IUdpClient.cs b/NetSdrClientApp/Networking/IUdpClient.cs index b85244c2..5b5e5753 100644 --- a/NetSdrClientApp/Networking/IUdpClient.cs +++ b/NetSdrClientApp/Networking/IUdpClient.cs @@ -1,4 +1,11 @@ -namespace NetSdrClientApp.Networking +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace NetSdrClientApp.Networking { public interface IUdpClient { From dbad9e1ac33f54032d3a7007a80eddbddb783bae Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 01:46:06 +0200 Subject: [PATCH 11/18] =?UTF-8?q?=D0=BD=D0=B5=D0=B9=D0=BC=D1=81=D0=BF?= =?UTF-8?q?=D0=B5=D0=B9=D1=81=20+=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NetSdrClientApp/Networking/IUdpClient.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/NetSdrClientApp/Networking/IUdpClient.cs b/NetSdrClientApp/Networking/IUdpClient.cs index 5b5e5753..9e56a5e5 100644 --- a/NetSdrClientApp/Networking/IUdpClient.cs +++ b/NetSdrClientApp/Networking/IUdpClient.cs @@ -1,19 +1,17 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; -using static System.Runtime.InteropServices.JavaScript.JSType; + namespace NetSdrClientApp.Networking { public interface IUdpClient { - event EventHandler? MessageReceived; + event EventHandler? MessageReceived; Task StartListeningAsync(); void StopListening(); + void Exit(); } } \ No newline at end of file From b5513d57f7272f0bd81ce94a12a81f07e6245b79 Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 01:56:38 +0200 Subject: [PATCH 12/18] =?UTF-8?q?=D0=9D=D0=B5=D0=B9=D0=BC=D1=81=D0=BF?= =?UTF-8?q?=D0=B5=D0=B9=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NetSdrClientApp/Networking/IUdpClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NetSdrClientApp/Networking/IUdpClient.cs b/NetSdrClientApp/Networking/IUdpClient.cs index 9e56a5e5..d2f7135b 100644 --- a/NetSdrClientApp/Networking/IUdpClient.cs +++ b/NetSdrClientApp/Networking/IUdpClient.cs @@ -6,7 +6,7 @@ namespace NetSdrClientApp.Networking { public interface IUdpClient { - event EventHandler? MessageReceived; + event EventHandler? MessageReceived; Task StartListeningAsync(); From a0d2f2f846df8237fe58af1a2ee0e142e111767a Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 02:01:38 +0200 Subject: [PATCH 13/18] UpdClientWrapped namespace --- .../Networking/UdpClientWrapper.cs | 117 +++++++++--------- 1 file changed, 60 insertions(+), 57 deletions(-) diff --git a/NetSdrClientApp/Networking/UdpClientWrapper.cs b/NetSdrClientApp/Networking/UdpClientWrapper.cs index 31e0b798..fe52572f 100644 --- a/NetSdrClientApp/Networking/UdpClientWrapper.cs +++ b/NetSdrClientApp/Networking/UdpClientWrapper.cs @@ -6,80 +6,83 @@ using System.Threading; using System.Threading.Tasks; -public class UdpClientWrapper : IUdpClient +namespace NetSdrClientApp.Networking { - private readonly IPEndPoint _localEndPoint; - private CancellationTokenSource? _cts; - private UdpClient? _udpClient; - - public event EventHandler? MessageReceived; - - public UdpClientWrapper(int port) + public class UdpClientWrapper : IUdpClient { - _localEndPoint = new IPEndPoint(IPAddress.Any, port); - } + private readonly IPEndPoint _localEndPoint; + private CancellationTokenSource? _cts; + private UdpClient? _udpClient; - public async Task StartListeningAsync() - { - _cts = new CancellationTokenSource(); - Console.WriteLine("Start listening for UDP messages..."); + public event EventHandler? MessageReceived; - try + public UdpClientWrapper(int port) { - _udpClient = new UdpClient(_localEndPoint); - while (!_cts.Token.IsCancellationRequested) + _localEndPoint = new IPEndPoint(IPAddress.Any, port); + } + + public async Task StartListeningAsync() + { + _cts = new CancellationTokenSource(); + Console.WriteLine("Start listening for UDP messages..."); + + try { - UdpReceiveResult result = await _udpClient.ReceiveAsync(_cts.Token); - MessageReceived?.Invoke(this, result.Buffer); + _udpClient = new UdpClient(_localEndPoint); + while (!_cts.Token.IsCancellationRequested) + { + UdpReceiveResult result = await _udpClient.ReceiveAsync(_cts.Token); + MessageReceived?.Invoke(this, result.Buffer); - Console.WriteLine($"Received from {result.RemoteEndPoint}"); + Console.WriteLine($"Received from {result.RemoteEndPoint}"); + } + } + catch (OperationCanceledException ex) + { + //empty + } + catch (Exception ex) + { + Console.WriteLine($"Error receiving message: {ex.Message}"); } } - catch (OperationCanceledException ex) - { - //empty - } - catch (Exception ex) - { - Console.WriteLine($"Error receiving message: {ex.Message}"); - } - } - public void StopListening() - { - try + public void StopListening() { - _cts?.Cancel(); - _udpClient?.Close(); - Console.WriteLine("Stopped listening for UDP messages."); - } - catch (Exception ex) - { - Console.WriteLine($"Error while stopping: {ex.Message}"); + try + { + _cts?.Cancel(); + _udpClient?.Close(); + Console.WriteLine("Stopped listening for UDP messages."); + } + catch (Exception ex) + { + Console.WriteLine($"Error while stopping: {ex.Message}"); + } } - } - public void Exit() - { - try - { - _cts?.Cancel(); - _udpClient?.Close(); - Console.WriteLine("Stopped listening for UDP messages."); - } - catch (Exception ex) + public void Exit() { - Console.WriteLine($"Error while stopping: {ex.Message}"); + try + { + _cts?.Cancel(); + _udpClient?.Close(); + Console.WriteLine("Stopped listening for UDP messages."); + } + catch (Exception ex) + { + Console.WriteLine($"Error while stopping: {ex.Message}"); + } } - } - public override int GetHashCode() - { - var payload = $"{nameof(UdpClientWrapper)}|{_localEndPoint.Address}|{_localEndPoint.Port}"; + public override int GetHashCode() + { + var payload = $"{nameof(UdpClientWrapper)}|{_localEndPoint.Address}|{_localEndPoint.Port}"; - using var md5 = MD5.Create(); - var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(payload)); + using var md5 = MD5.Create(); + var hash = md5.ComputeHash(Encoding.UTF8.GetBytes(payload)); - return BitConverter.ToInt32(hash, 0); + return BitConverter.ToInt32(hash, 0); + } } } \ No newline at end of file From e575bc483aaebdf9af3a45a93a4f7485a3c1a1b7 Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 02:26:52 +0200 Subject: [PATCH 14/18] OpenCover --- .github/workflows/sonarcloud.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 68234276..d6031e4e 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -70,13 +70,13 @@ jobs: run: dotnet restore NetSdrClient.sln - name: Build run: dotnet build NetSdrClient.sln -c Release --no-restore - #- name: Tests with coverage (OpenCover) - # run: | - # dotnet test NetSdrClientAppTests/NetSdrClientAppTests.csproj -c Release --no-build ` - # /p:CollectCoverage=true ` - # /p:CoverletOutput=TestResults/coverage.xml ` - # /p:CoverletOutputFormat=opencover - # shell: pwsh + - name: Tests with coverage (OpenCover) + run: | + dotnet test NetSdrClientAppTests/NetSdrClientAppTests.csproj -c Release --no-build ` + /p:CollectCoverage=true ` + /p:CoverletOutput=TestResults/coverage.xml ` + /p:CoverletOutputFormat=opencover + shell: pwsh # 3) END: SonarScanner - name: SonarScanner End run: dotnet sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}" From f56712412f84d1ccaf047e57b1f349e104ff3a6b Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 02:47:10 +0200 Subject: [PATCH 15/18] Update NetSdrClientTests.cs --- NetSdrClientAppTests/NetSdrClientTests.cs | 46 +++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/NetSdrClientAppTests/NetSdrClientTests.cs b/NetSdrClientAppTests/NetSdrClientTests.cs index ad00c4f8..a779ab58 100644 --- a/NetSdrClientAppTests/NetSdrClientTests.cs +++ b/NetSdrClientAppTests/NetSdrClientTests.cs @@ -116,4 +116,50 @@ public async Task StopIQTest() } //TODO: cover the rest of the NetSdrClient code here + [Test] + public async Task StartIQAsync_Does_Nothing_If_Already_Started() + { + await _client.ConnectAsync(); + await _client.StartIQAsync(); + + await _client.StartIQAsync(); + + _updMock.Verify(udp => udp.StartListeningAsync(), Times.Once); + Assert.That(_client.IQStarted, Is.True); + } + + [Test] + public async Task StopIQAsync_Does_Nothing_If_Not_Started() + { + await _client.ConnectAsync(); + + await _client.StopIQAsync(); + + _updMock.Verify(udp => udp.StopListening(), Times.Never); + Assert.That(_client.IQStarted, Is.False); + } + + [Test] + public async Task Disconnect_Resets_IQStarted_State() + { + await _client.ConnectAsync(); + await _client.StartIQAsync(); + Assert.That(_client.IQStarted, Is.True); + + _client.Disconect(); + + Assert.That(_client.IQStarted, Is.False); + _updMock.Verify(udp => udp.StopListening(), Times.Once); + } + + [Test] + public async Task ConnectAsync_Handles_Connection_Exception() + { + _tcpMock.Setup(tcp => tcp.Connect()).Throws(new System.Net.Sockets.SocketException()); + + await _client.ConnectAsync(); + + _tcpMock.Verify(tcp => tcp.SendMessageAsync(It.IsAny()), Times.Never); + Assert.That(_client.IQStarted, Is.False); + } } From fd02995d674b426194df739c8c14a2ed6551d2a4 Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 03:02:34 +0200 Subject: [PATCH 16/18] =?UTF-8?q?=D0=B4=D0=BE=D0=B4=D0=B0=D0=BD=D0=BE=20?= =?UTF-8?q?=D0=B7=D0=BD=D0=B0=D0=BA=20=D0=BF=D0=B8=D1=82=D0=B0=D0=BD=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NetSdrClientApp/NetSdrClient.cs | 2 +- NetSdrClientApp/Networking/TcpClientWrapper.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NetSdrClientApp/NetSdrClient.cs b/NetSdrClientApp/NetSdrClient.cs index b0a7c058..fdec9dcc 100644 --- a/NetSdrClientApp/NetSdrClient.cs +++ b/NetSdrClientApp/NetSdrClient.cs @@ -131,7 +131,7 @@ private void _udpClient_MessageReceived(object? sender, byte[] e) } } - private TaskCompletionSource responseTaskSource; + private TaskCompletionSource? responseTaskSource; private async Task SendTcpRequest(byte[] msg) { diff --git a/NetSdrClientApp/Networking/TcpClientWrapper.cs b/NetSdrClientApp/Networking/TcpClientWrapper.cs index 1f37e2e5..6405f323 100644 --- a/NetSdrClientApp/Networking/TcpClientWrapper.cs +++ b/NetSdrClientApp/Networking/TcpClientWrapper.cs @@ -16,7 +16,7 @@ public class TcpClientWrapper : ITcpClient private int _port; private TcpClient? _tcpClient; private NetworkStream? _stream; - private CancellationTokenSource _cts; + private CancellationTokenSource? _cts; public bool Connected => _tcpClient != null && _tcpClient.Connected && _stream != null; From be0f47edede9635fedd37e29cedea5a71799620c Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 03:14:43 +0200 Subject: [PATCH 17/18] NetSdrClient.cs update --- NetSdrClientApp/NetSdrClient.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/NetSdrClientApp/NetSdrClient.cs b/NetSdrClientApp/NetSdrClient.cs index fdec9dcc..f5ceccf1 100644 --- a/NetSdrClientApp/NetSdrClient.cs +++ b/NetSdrClientApp/NetSdrClient.cs @@ -1,21 +1,21 @@ using NetSdrClientApp.Messages; using NetSdrClientApp.Networking; using System; -using System.Collections.Generic; +//using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Channels; +//using System.Text; +//using System.Threading; +//using System.Threading.Channels; using System.Threading.Tasks; using static NetSdrClientApp.Messages.NetSdrMessageHelper; -using static System.Runtime.InteropServices.JavaScript.JSType; +//using static System.Runtime.InteropServices.JavaScript.JSType; namespace NetSdrClientApp { public class NetSdrClient { - private ITcpClient _tcpClient; - private IUdpClient _udpClient; + private readonly ITcpClient _tcpClient; + private readonly IUdpClient _udpClient; public bool IQStarted { get; set; } @@ -133,7 +133,7 @@ private void _udpClient_MessageReceived(object? sender, byte[] e) private TaskCompletionSource? responseTaskSource; - private async Task SendTcpRequest(byte[] msg) + private async Task SendTcpRequest(byte[] msg) { if (!_tcpClient.Connected) { From b0ff39d06ffa3451fafa458a05dc17381ee17559 Mon Sep 17 00:00:00 2001 From: Starenkiyy <9100759@stud.kai.edu.ua> Date: Thu, 13 Nov 2025 03:38:34 +0200 Subject: [PATCH 18/18] TcpClientWrappr Update --- NetSdrClientApp/Networking/TcpClientWrapper.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/NetSdrClientApp/Networking/TcpClientWrapper.cs b/NetSdrClientApp/Networking/TcpClientWrapper.cs index 6405f323..f79858ed 100644 --- a/NetSdrClientApp/Networking/TcpClientWrapper.cs +++ b/NetSdrClientApp/Networking/TcpClientWrapper.cs @@ -56,7 +56,8 @@ public void Disconnect() { if (Connected) { - _cts?.Cancel(); + _cts?.close(); + _cts?.Dispose(); _stream?.Close(); _tcpClient?.Close(); @@ -100,7 +101,7 @@ public async Task SendMessageAsync(string str) private async Task StartListeningAsync() { - if (Connected && _stream != null && _stream.CanRead) + if (Connected && _stream != null && _stream.CanRead && _cts != null) { try {