Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Debugger init audit fixes #601

Merged
merged 4 commits into from
Oct 25, 2024
Merged
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
2 changes: 1 addition & 1 deletion Source/v2/Meadow.Cli/Meadow.CLI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<Authors>Wilderness Labs, Inc</Authors>
<Company>Wilderness Labs, Inc</Company>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageVersion>2.0.58.0</PackageVersion>
<PackageVersion>2.0.60.0</PackageVersion>
<Platforms>AnyCPU</Platforms>
<PackageProjectUrl>http://developer.wildernesslabs.co/Meadow/Meadow.CLI/</PackageProjectUrl>
<RepositoryUrl>https://github.com/WildernessLabs/Meadow.CLI</RepositoryUrl>
Expand Down
2 changes: 1 addition & 1 deletion Source/v2/Meadow.Cli/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ namespace Meadow.CLI;

public static class Constants
{
public const string CLI_VERSION = "2.0.58.0";
public const string CLI_VERSION = "2.0.60.0";
}
64 changes: 40 additions & 24 deletions Source/v2/Meadow.HCom/Connections/SerialConnection.ListenerProc.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Meadow.Hcom
namespace Meadow.Hcom
{
public partial class SerialConnection
{
Expand Down Expand Up @@ -52,6 +52,34 @@ private async Task ListenerProc()
var delimiter = new byte[] { 0x00 };
var receivedLength = 0;

async Task ReOpen() // local function
{
Debug.WriteLine($"Device reset detected");

var timeout = 20;
try { _port.Close(); } catch { } // Swallow any exceptions on close - there is nothing we can do about it

while (!_port.IsOpen)
{
await Task.Delay(500);

if (timeout-- < 0)
{
return;
}

try
{
Open();
Debug.WriteLine($"Port re-opened");
}
catch
{
Debug.WriteLine($"Failed to re-open port");
}
}
}

while (!_isDisposed)
{
if (_port.IsOpen)
Expand All @@ -64,32 +92,20 @@ private async Task ListenerProc()
try
{
receivedLength = _port.Read(readBuffer, 0, readBuffer.Length);
if (receivedLength == 0)
{
Debug.WriteLine($"Received 0 bytes");
throw new OperationCanceledException();
}
}
catch (OperationCanceledException)
{
Debug.WriteLine($"Device reset detected");

var timeout = 20;

while (!_port.IsOpen)
{
await Task.Delay(500);

if (timeout-- < 0)
{
return;
}

try
{
Open();
Debug.WriteLine($"Port re-opened");
}
catch
{
Debug.WriteLine($"Failed to re-open port");
}
}
await ReOpen();
goto read;
}
catch (InvalidOperationException)
{
await ReOpen();
goto read;
}

Expand Down
4 changes: 2 additions & 2 deletions Source/v2/Meadow.HCom/Connections/SerialConnection.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Buffers;
using System.Buffers;
using System.IO.Ports;
using System.Security.Cryptography;

Expand Down Expand Up @@ -1254,7 +1254,7 @@ public override async Task<DebuggingServer> StartDebuggingSession(int port, ILog
var debuggingServer = new DebuggingServer(this, port, logger);

logger?.LogDebug("Tell the Debugging Server to Start Listening");
_ = debuggingServer.StartListening(cancellationToken);
await debuggingServer.StartListening(cancellationToken);

logger?.LogDebug($"Start Debugging on port: {port}");
await Device.StartDebugging(port, logger, cancellationToken);
Expand Down
73 changes: 28 additions & 45 deletions Source/v2/Meadow.HCom/Debugging/DebuggingServer.ActiveClient.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Buffers;
using System.Buffers;
using System.Collections.Concurrent;
using System.Net.Sockets;
using System.Security.Cryptography;

namespace Meadow.Hcom;

Expand All @@ -10,39 +9,39 @@
private class ActiveClient : IDisposable
{
private readonly IMeadowConnection _connection;
private readonly TcpClient _tcpClient;
private readonly NetworkStream _networkStream;
private TcpClient _tcpClient;
private NetworkStream _networkStream;
private readonly CancellationTokenSource _cts;
private readonly Task _receiveVsDebugDataTask;
private readonly Task _receiveMeadowDebugDataTask;
private Task _receiveVsDebugDataTask;
private Task _receiveMeadowDebugDataTask;
private readonly ILogger? _logger;
private bool _disposed;
private readonly BlockingCollection<byte[]> _debuggerMessages = new();
private readonly AutoResetEvent _vsDebugDataReady = new(false);

internal ActiveClient(IMeadowConnection connection, TcpClient tcpClient, ILogger? logger, CancellationToken? cancellationToken)
internal ActiveClient(IMeadowConnection connection, ILogger? logger, CancellationToken? cancellationToken)

Check warning on line 21 in Source/v2/Meadow.HCom/Debugging/DebuggingServer.ActiveClient.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field '_tcpClient' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.

Check warning on line 21 in Source/v2/Meadow.HCom/Debugging/DebuggingServer.ActiveClient.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field '_networkStream' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.

Check warning on line 21 in Source/v2/Meadow.HCom/Debugging/DebuggingServer.ActiveClient.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field '_receiveVsDebugDataTask' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.

Check warning on line 21 in Source/v2/Meadow.HCom/Debugging/DebuggingServer.ActiveClient.cs

View workflow job for this annotation

GitHub Actions / build

Non-nullable field '_receiveMeadowDebugDataTask' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
{
_cts = cancellationToken != null
? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken.Value)
: new CancellationTokenSource();

_logger = logger;
_connection = connection;
_tcpClient = tcpClient;
_networkStream = tcpClient.GetStream();

_logger?.LogDebug("Starting receive task");

_connection.DebuggerMessageReceived += MeadowConnection_DebuggerMessageReceived;
}

public async Task Start(TcpListener tcpListener)
{
_tcpClient = await tcpListener.AcceptTcpClientAsync();
_networkStream = _tcpClient.GetStream();

_logger?.LogDebug("Starting receive task");
_receiveVsDebugDataTask = Task.Factory.StartNew(SendToMeadowAsync, _cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
_receiveMeadowDebugDataTask = Task.Factory.StartNew(SendToVisualStudio, _cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}

private void MeadowConnection_DebuggerMessageReceived(object sender, byte[] e)
{
_debuggerMessages.Add(e);
_vsDebugDataReady.Set();
}

private const int RECEIVE_BUFFER_SIZE = 256;
Expand All @@ -51,9 +50,7 @@
{
try
{
using var md5 = MD5.Create();
var receiveBuffer = ArrayPool<byte>.Shared.Rent(RECEIVE_BUFFER_SIZE);
var meadowBuffer = Array.Empty<byte>();

while (!_cts.Token.IsCancellationRequested)
{
Expand All @@ -69,21 +66,19 @@
continue;
}

var destIndex = meadowBuffer.Length;
Array.Resize(ref meadowBuffer, destIndex + bytesRead);
Array.Copy(receiveBuffer, 0, meadowBuffer, destIndex, bytesRead);
var meadowBuffer = new byte[bytesRead];
Array.Copy(receiveBuffer, 0, meadowBuffer, 0, bytesRead);

_logger?.LogTrace("Received {count} bytes from VS, will forward to HCOM/Meadow. {hash}",
meadowBuffer.Length,
BitConverter.ToString(md5.ComputeHash(meadowBuffer))
BitConverter.ToString(meadowBuffer)
.Replace("-", string.Empty)
.ToLowerInvariant());

await _connection.SendDebuggerData(meadowBuffer, 0, _cts.Token);

Debug.WriteLine($"ToMeadow: {BitConverter.ToString(meadowBuffer)}");

meadowBuffer = Array.Empty<byte>();
} while (_networkStream.DataAvailable);
}
else
Expand All @@ -93,15 +88,13 @@
}
}
}
catch (IOException ioe)

Check warning on line 91 in Source/v2/Meadow.HCom/Debugging/DebuggingServer.ActiveClient.cs

View workflow job for this annotation

GitHub Actions / build

The variable 'ioe' is declared but never used
{
_logger?.LogInformation("Visual Studio has Disconnected");
_logger?.LogTrace(ioe, "Visual Studio has Disconnected");
}
catch (ObjectDisposedException ode)

Check warning on line 95 in Source/v2/Meadow.HCom/Debugging/DebuggingServer.ActiveClient.cs

View workflow job for this annotation

GitHub Actions / build

The variable 'ode' is declared but never used
{
_logger?.LogInformation("Visual Studio has stopped debugging");
_logger?.LogTrace(ode, "Visual Studio has stopped debugging");
}
catch (Exception ex)
{
Expand All @@ -114,33 +107,23 @@
{
try
{
while (!_cts.Token.IsCancellationRequested)
while (!_cts.IsCancellationRequested)
{
if (_networkStream != null && _networkStream.CanWrite)
if (!_debuggerMessages.TryTake(out var byteData, 500, _cts.Token))
{
_vsDebugDataReady.WaitOne(500);

while (_debuggerMessages.Count > 0)
{
var byteData = _debuggerMessages.Take(_cts.Token);

_logger?.LogTrace("Received {count} bytes from Meadow, will forward to VS", byteData.Length);
if (!_tcpClient.Connected)
{
_logger?.LogDebug("Cannot forward data, Visual Studio is not connected");
return;
}

await _networkStream.WriteAsync(byteData, 0, byteData.Length, _cts.Token);
_logger?.LogTrace("Forwarded {count} bytes to VS", byteData.Length);

Debug.WriteLine($"ToVisStu: {BitConverter.ToString(byteData)}");
}
continue;
}
else

_logger?.LogTrace("Received {count} bytes from Meadow, will forward to VS", byteData.Length);
if (!_tcpClient.Connected || _networkStream == null || !_networkStream.CanWrite)
{
_logger?.LogInformation("Unable to Write Data from Visual Studio");
_logger?.LogDebug("Cannot forward data, Visual Studio is not connected");
break;
}

await _networkStream.WriteAsync(byteData, 0, byteData.Length, _cts.Token);
_logger?.LogTrace("Forwarded {count} bytes to VS", byteData.Length);
Debug.WriteLine($"ToVisStu: {BitConverter.ToString(byteData)}");
}
}
catch (OperationCanceledException oce)
Expand Down
28 changes: 13 additions & 15 deletions Source/v2/Meadow.HCom/Debugging/DebuggingServer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Net;
using System.Net;
using System.Net.Sockets;

namespace Meadow.Hcom;
Expand Down Expand Up @@ -50,8 +50,7 @@ public async Task StartListening(CancellationToken cancellationToken)
_logger?.LogInformation($"Listening for Visual Studio to connect");

// This call will wait for the client to connect, before continuing.
var tcpClient = await _listener.AcceptTcpClientAsync();
_activeClient = CreateActiveClient(tcpClient);
_activeClient = await CreateActiveClient(_listener);
}

/// <summary>
Expand All @@ -70,23 +69,22 @@ public async Task StopListening()
}
}

private ActiveClient? CreateActiveClient(TcpClient tcpClient)
private async Task<ActiveClient?> CreateActiveClient(TcpListener listener)
{
try
{
lock (_lck)
if (_activeClient != null)
{
_logger?.LogInformation("Visual Studio has Connected" + Environment.NewLine);

if (_activeClient != null)
{
_logger?.LogDebug("Closing active client");
_activeClient?.Dispose();
_activeClient = null;
}

return new ActiveClient(_connection, tcpClient, _logger, _cancellationTokenSource?.Token);
_logger?.LogDebug("Closing active client");
_activeClient?.Dispose();
_activeClient = null;
}


var client = new ActiveClient(_connection, _logger, _cancellationTokenSource?.Token);
await client.Start(listener);
_logger?.LogInformation("Debugger has connected" + Environment.NewLine);
return client;
}
catch (Exception ex)
{
Expand Down
Loading