Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 22 additions & 52 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
@@ -1,31 +1,3 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# This workflow helps you trigger a SonarCloud analysis of your code and populates
# GitHub Code Scanning alerts with the vulnerabilities found.
# Free for open source project.

# 1. Login to SonarCloud.io using your GitHub account

# 2. Import your project on SonarCloud
# * Add your GitHub organization first, then add your repository as a new project.
# * Please note that many languages are eligible for automatic analysis,
# which means that the analysis will start automatically without the need to set up GitHub Actions.
# * This behavior can be changed in Administration > Analysis Method.
#
# 3. Follow the SonarCloud in-product tutorial
# * a. Copy/paste the Project Key and the Organization Key into the args parameter below
# (You'll find this information in SonarCloud. Click on "Information" at the bottom left)
#
# * b. Generate a new token and add it to your Github repository's secrets using the name SONAR_TOKEN
# (On SonarCloud, click on your avatar on top-right > My account > Security
# or go directly to https://sonarcloud.io/account/security/)

# Feel free to take a look at our documentation (https://docs.sonarcloud.io/getting-started/github/)
# or reach out to our community forum if you need some help (https://community.sonarsource.com/c/help/sc/9)

name: SonarCloud analysis

on:
Expand All @@ -36,48 +8,46 @@ on:
workflow_dispatch:

permissions:
pull-requests: read # allows SonarCloud to decorate PRs with analysis results
contents: read
pull-requests: read

jobs:
sonar-check:
name: Sonar Check
runs-on: windows-latest # безпечно для будь-яких .NET проектів
sonar:
name: SonarCloud Analysis
runs-on: windows-latest

steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
with:
fetch-depth: 0

- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'

# 1) BEGIN: SonarScanner for .NET
- name: SonarScanner Begin
- name: Install SonarScanner
run: |
dotnet tool install --global dotnet-sonarscanner
echo "$env:USERPROFILE\.dotnet\tools" >> $env:GITHUB_PATH
shell: pwsh

- name: SonarScanner Begin
run: |
dotnet sonarscanner begin `
/k:"ppanchen_NetSdrClient" `
/o:"ppanchen" `
/d:sonar.token="${{ secrets.SONAR_TOKEN }}" `
/d:sonar.cs.opencover.reportsPaths="**/coverage.xml" `
/d:sonar.cpd.cs.minimumTokens=40 `
/d:sonar.cpd.cs.minimumLines=5 `
/d:sonar.exclusions=**/bin/**,**/obj/**,**/sonarcloud.yml `
/d:sonar.qualitygate.wait=true
/k:"olekca160406_NetSdrClient" `
/o:"olekca160406" `
/d:sonar.token="${{ secrets.SONAR_TOKEN }}" `
/d:sonar.cs.opencover.reportsPaths="**/coverage.xml" `
/d:sonar.exclusions="**/bin/**,**/obj/**" `

shell: pwsh
# 2) BUILD & TEST

- name: Restore
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
# 3) END: SonarScanner

- name: SonarScanner End
run: dotnet sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
shell: pwsh
231 changes: 116 additions & 115 deletions EchoTcpServer/Program.cs
Original file line number Diff line number Diff line change
@@ -1,173 +1,174 @@
using System;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;


/// <summary>
/// This program was designed for test purposes only
/// Not for a review
/// </summary>
public class EchoServer
namespace NetSdrClientApp.EchoServer
{
private readonly int _port;
private TcpListener _listener;
private CancellationTokenSource _cancellationTokenSource;


public EchoServer(int port)
public class EchoServer
{
_port = port;
_cancellationTokenSource = new CancellationTokenSource();
}
private readonly int _port;
private TcpListener _listener;
private readonly CancellationTokenSource _cancellationTokenSource;

public async Task StartAsync()
{
_listener = new TcpListener(IPAddress.Any, _port);
_listener.Start();
Console.WriteLine($"Server started on port {_port}.");
public EchoServer(int port)
{
_port = port;
_cancellationTokenSource = new CancellationTokenSource();
}

while (!_cancellationTokenSource.Token.IsCancellationRequested)
public async Task StartAsync()
{
try
{
TcpClient client = await _listener.AcceptTcpClientAsync();
Console.WriteLine("Client connected.");
_listener = new TcpListener(IPAddress.Any, _port);
_listener.Start();
Console.WriteLine($"Server started on port {_port}.");

_ = Task.Run(() => HandleClientAsync(client, _cancellationTokenSource.Token));
}
catch (ObjectDisposedException)
while (!_cancellationTokenSource.Token.IsCancellationRequested)
{
// Listener has been closed
break;
try
{
TcpClient client = await _listener.AcceptTcpClientAsync();
Console.WriteLine("Client connected.");

_ = Task.Run(() => HandleClientAsync(client, _cancellationTokenSource.Token));
}
catch (ObjectDisposedException)
{
// Listener has been closed
break;
}
}
}

Console.WriteLine("Server shutdown.");
}
Console.WriteLine("Server shutdown.");
}

private async Task HandleClientAsync(TcpClient client, CancellationToken token)
{
using (NetworkStream stream = client.GetStream())
private async Task HandleClientAsync(TcpClient client, CancellationToken token)
{
try
using (NetworkStream stream = client.GetStream())
{
byte[] buffer = new byte[8192];
int bytesRead;

while (!token.IsCancellationRequested && (bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, token)) > 0)
try
{
// Echo back the received message
await stream.WriteAsync(buffer, 0, bytesRead, token);
Console.WriteLine($"Echoed {bytesRead} bytes to the client.");
byte[] buffer = new byte[8192];
int bytesRead;

while (!token.IsCancellationRequested &&
(bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, token)) > 0)
{
await stream.WriteAsync(buffer, 0, bytesRead, token);
Console.WriteLine($"Echoed {bytesRead} bytes to the client.");
}
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
client.Close();
Console.WriteLine("Client disconnected.");
}
}
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 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 static async Task Main(string[] args)
{
EchoServer server = new EchoServer(5000);

// Start the server in a separate task
_ = Task.Run(() => server.StartAsync());
_ = Task.Run(() => server.StartAsync());

string host = "127.0.0.1"; // Target IP
int port = 60000; // Target Port
int intervalMilliseconds = 5000; // Send every 3 seconds
string host = "127.0.0.1";
int port = 60000;
int intervalMilliseconds = 5000;

using (var sender = new UdpTimedSender(host, port))
{
using var sender = new UdpTimedSender(host, port);
Console.WriteLine("Press any key to stop sending...");
sender.StartSending(intervalMilliseconds);

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.");
}
}
}


public class UdpTimedSender : IDisposable
{
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.");
private ushort _counter;

_timer = new Timer(SendMessageCallback, null, 0, intervalMilliseconds);
}
public UdpTimedSender(string host, int port)
{
_host = host;
_port = port;
_udpClient = new UdpClient();
}

ushort i = 0;
public void StartSending(int intervalMilliseconds)
{
if (_timer != null)
throw new InvalidOperationException("Sender is already running.");

private void SendMessageCallback(object state)
{
try
_timer = new Timer(SendMessageCallback, null, 0, intervalMilliseconds);
}

private void SendMessageCallback(object? state)
{
//dummy data
Random rnd = new Random();
byte[] samples = new byte[1024];
rnd.NextBytes(samples);
i++;
try
{
var rnd = new Random();
byte[] samples = new byte[1024];
rnd.NextBytes(samples);
_counter++;

byte[] msg = new byte[] { 0x04, 0x84 }
.Concat(BitConverter.GetBytes(_counter))
.Concat(samples)
.ToArray();

byte[] msg = (new byte[] { 0x04, 0x84 }).Concat(BitConverter.GetBytes(i)).Concat(samples).ToArray();
var endpoint = new IPEndPoint(IPAddress.Parse(_host), _port);
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();
}
}
}
}
Loading