Skip to content

Commit

Permalink
Merge pull request #601 from WildernessLabs/debugger-init-audit-fixes
Browse files Browse the repository at this point in the history
Debugger init audit fixes
  • Loading branch information
ctacke authored Oct 25, 2024
2 parents e056745 + 7a61ee8 commit 4f56455
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 88 deletions.
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 @@ public partial class DebuggingServer
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 @@ private async Task SendToMeadowAsync()
{
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 @@ private async Task SendToMeadowAsync()
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 @@ -96,12 +91,10 @@ private async Task SendToMeadowAsync()
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 @@ private async Task SendToVisualStudio()
{
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

0 comments on commit 4f56455

Please sign in to comment.