Files
MicrosoftIris/UIX/Microsoft/Iris/Debug/SystemNet/NetDebuggerServer.cs
T

160 lines
4.8 KiB
C#
Raw Normal View History

2023-06-01 20:18:53 -05:00
using Microsoft.Iris.Debug.Data;
2024-01-20 20:32:30 -06:00
using Microsoft.Iris.Markup;
2023-06-01 20:18:53 -05:00
using System;
2023-06-01 22:49:47 -05:00
using System.Collections.Concurrent;
2023-06-01 20:18:53 -05:00
using System.Net.Sockets;
using System.Runtime.Serialization;
namespace Microsoft.Iris.Debug.SystemNet;
internal class NetDebuggerServer : IDebuggerServer, IDisposable
{
public static IDebuggerServer Current { get; private set; }
2023-06-01 22:49:47 -05:00
private readonly ConcurrentQueue<byte[]> _outQueue = new();
2023-06-01 20:18:53 -05:00
private readonly TcpListener _listener;
private readonly IFormatter _formatter;
private Socket _socket;
2023-06-01 20:36:32 -05:00
private bool _disposed = false;
private InterpreterCommand _uibCommand;
public event Action<IDebuggerState, object> Connected;
public Uri ConnectionUri { get; }
public InterpreterCommand DebuggerCommand
{
get => _uibCommand;
set
{
2024-01-20 20:32:30 -06:00
QueueDebuggerMessage(new(0, DebuggerMessageType.InterpreterCommand, value, _formatter));
_uibCommand = value;
}
}
2023-06-01 20:18:53 -05:00
public NetDebuggerServer(string connectionUri) : this(new Uri(connectionUri))
{
}
public NetDebuggerServer(Uri connectionUri)
{
ConnectionUri = connectionUri ?? DebugRemoting.DEFAULT_TCP_URI;
_listener = TcpListener.Create(connectionUri.Port);
_listener.Start();
_formatter = DebugRemoting.CreateBsonFormatter();
System.Threading.Thread connectThread = new(ConnectLoop) { IsBackground = true };
2023-06-01 20:18:53 -05:00
connectThread.Start();
Current = this;
}
2024-01-20 20:32:30 -06:00
public MarkupLineNumberEntry[] OnLineNumberTableRequested(string uri)
{
var loadResult = LoadResultCache.Read(uri) as MarkupLoadResult;
var lineNumberTable = loadResult.LineNumberTable.DumpTable();
return lineNumberTable;
}
2023-10-09 14:46:51 -05:00
public void LogInterpreterDecode(object context, InterpreterInstruction instruction)
2023-06-01 20:18:53 -05:00
{
2024-01-20 20:32:30 -06:00
QueueDebuggerMessage(new(0, DebuggerMessageType.InterpreterDecode, instruction, _formatter));
2023-10-09 14:46:51 -05:00
}
public void LogInterpreterExecute(object context, InterpreterEntry entry)
{
2024-01-20 20:32:30 -06:00
QueueDebuggerMessage(new(0, DebuggerMessageType.InterpreterExecute, entry, _formatter));
2023-06-01 20:18:53 -05:00
}
public void LogDispatcher(string message)
{
2024-01-20 20:32:30 -06:00
QueueDebuggerMessage(new(0, DebuggerMessageType.DispatcherStep, message, _formatter));
2023-06-01 20:18:53 -05:00
}
public void Dispose()
{
2023-06-01 20:36:32 -05:00
if (_disposed)
return;
_disposed = true;
2023-06-01 20:18:53 -05:00
_listener.Stop();
_socket?.Dispose();
}
private void QueueDebuggerMessage(DebuggerMessageFrame frame)
{
_outQueue.Enqueue(frame.ToBytes());
}
private void MessageReceiveLoop()
2023-06-01 20:18:53 -05:00
{
while (_socket.Connected)
{
DebuggerMessageFrame frame;
2024-01-20 20:32:30 -06:00
while ((frame = DebugRemoting.ReceiveDebuggerMessage(_socket, _formatter)) == null)
if (!_socket.Connected) return;
2023-06-01 20:18:53 -05:00
switch (frame.Type)
{
case DebuggerMessageType.UpdateBreakpoint:
2024-01-20 20:32:30 -06:00
var breakpoint = frame.GetValue<Breakpoint>();
if (breakpoint.Enabled)
Application.DebugSettings.Breakpoints.Add(breakpoint);
else
Application.DebugSettings.Breakpoints.Remove(breakpoint);
break;
case DebuggerMessageType.InterpreterCommand:
2024-01-20 20:32:30 -06:00
_uibCommand = frame.GetValue<InterpreterCommand>();
break;
case DebuggerMessageType.LineNumberTable:
var lineNumberTable = OnLineNumberTableRequested(frame.GetValue<string>());
DebuggerMessageFrame<MarkupLineNumberEntry[]> responseFrame =
new(frame.TransactionId, DebuggerMessageType.LineNumberTable, lineNumberTable, _formatter);
QueueDebuggerMessage(responseFrame);
break;
2023-06-01 20:18:53 -05:00
default:
Trace.WriteLine(TraceCategory.MarkupDebug, "Recieved unknown debugger message of type '{0}'.", frame.Type);
break;
}
}
}
private void MessageSendLoop()
{
while (_socket.Connected)
{
2023-06-01 22:49:47 -05:00
byte[] frameBytes;
while (!_outQueue.TryDequeue(out frameBytes)) ;
2023-06-01 20:18:53 -05:00
try
{
_socket.Send(BitConverter.GetBytes(frameBytes.Length));
_socket.Send(frameBytes);
}
catch (SocketException) { }
2023-06-01 20:18:53 -05:00
}
}
private void ConnectLoop()
{
2023-06-01 20:36:32 -05:00
while (!_listener.Pending())
if (_disposed) return;
2023-06-01 20:18:53 -05:00
_socket = _listener.AcceptSocket();
Connected?.Invoke(this, _socket);
2023-06-01 20:18:53 -05:00
System.Threading.Thread receiveThread = new(MessageReceiveLoop) { IsBackground = true };
System.Threading.Thread sendThread = new(MessageSendLoop) { IsBackground = true };
2023-06-01 20:18:53 -05:00
receiveThread.Start();
sendThread.Start();
}
}